├── logo.png
├── test3
├── a2.jpg
├── b2.jpg
└── b3.jpg
├── openpivgui.fig
├── readImDir.fig
├── openpiv_logo.mat
├── test1
├── exp1_001_b.bmp
├── exp1_001_c.bmp
└── exp1_001_b.vec
├── test2
├── 00020359.bmp
├── 00020360.bmp
├── 00020361.bmp
└── 00020362.bmp
├── docs
└── Tutorial_OpenPIV
│ ├── Images
│ ├── ROI.png
│ ├── faq.png
│ ├── Output.png
│ ├── website.png
│ ├── IntWindow.png
│ ├── open_window.png
│ ├── parameters.png
│ ├── User_Interface.png
│ └── help_snapshot.png
│ ├── Tutorial_OpenPIV.pdf
│ ├── run
│ ├── Tutorial_OpenPIV.tex
│ ├── PIVbib.bib
│ └── Contents
│ └── Contents.tex
├── getext.m
├── quiver_complex_vector.m
├── isclose.m
├── .gitignore
├── preprocess_invert.m
├── test_fill_holes.m
├── preprocess_rotate.m
├── preprocess_template.m
├── cross_correlate_rect.m
├── preprocess_coronary.m
├── quivertxt.m
├── fill_holes.m
├── plotarrow.m
├── preprocess_remove_vertical_strips.m
├── find_second_peak.m
├── find_peak.m
├── openpiv_imread.m
├── testFindSecondPeak.m
├── testFindPeak.m
├── openpiv_output.m
├── ReadTXTDir.m
├── calculate_subtract_average_image.m
├── Contents.m
├── find_displacement_rect.m
├── sub_pixel_velocity_rect.m
├── get_snr_for_piv.m
├── write_openpiv_vec.m
├── openpiv_filter.m
├── quiverm.m
├── README.md
├── loadopenpivtxtdir.m
├── readURAPIVdata.m
├── read_pair_of_images_rect.m
├── txt2mat.m
├── loadopenpivtxt.m
├── openpiv.m
├── readImDir.m
├── normxcorr2_general.m
├── inpaint_nans.m
├── tiffread2.m
└── openpivgui.m
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/logo.png
--------------------------------------------------------------------------------
/test3/a2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/test3/a2.jpg
--------------------------------------------------------------------------------
/test3/b2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/test3/b2.jpg
--------------------------------------------------------------------------------
/test3/b3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/test3/b3.jpg
--------------------------------------------------------------------------------
/openpivgui.fig:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/openpivgui.fig
--------------------------------------------------------------------------------
/readImDir.fig:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/readImDir.fig
--------------------------------------------------------------------------------
/openpiv_logo.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/openpiv_logo.mat
--------------------------------------------------------------------------------
/test1/exp1_001_b.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/test1/exp1_001_b.bmp
--------------------------------------------------------------------------------
/test1/exp1_001_c.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/test1/exp1_001_c.bmp
--------------------------------------------------------------------------------
/test2/00020359.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/test2/00020359.bmp
--------------------------------------------------------------------------------
/test2/00020360.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/test2/00020360.bmp
--------------------------------------------------------------------------------
/test2/00020361.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/test2/00020361.bmp
--------------------------------------------------------------------------------
/test2/00020362.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/test2/00020362.bmp
--------------------------------------------------------------------------------
/docs/Tutorial_OpenPIV/Images/ROI.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/docs/Tutorial_OpenPIV/Images/ROI.png
--------------------------------------------------------------------------------
/docs/Tutorial_OpenPIV/Images/faq.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/docs/Tutorial_OpenPIV/Images/faq.png
--------------------------------------------------------------------------------
/docs/Tutorial_OpenPIV/Images/Output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/docs/Tutorial_OpenPIV/Images/Output.png
--------------------------------------------------------------------------------
/docs/Tutorial_OpenPIV/Images/website.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/docs/Tutorial_OpenPIV/Images/website.png
--------------------------------------------------------------------------------
/docs/Tutorial_OpenPIV/Images/IntWindow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/docs/Tutorial_OpenPIV/Images/IntWindow.png
--------------------------------------------------------------------------------
/docs/Tutorial_OpenPIV/Tutorial_OpenPIV.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/docs/Tutorial_OpenPIV/Tutorial_OpenPIV.pdf
--------------------------------------------------------------------------------
/docs/Tutorial_OpenPIV/Images/open_window.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/docs/Tutorial_OpenPIV/Images/open_window.png
--------------------------------------------------------------------------------
/docs/Tutorial_OpenPIV/Images/parameters.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/docs/Tutorial_OpenPIV/Images/parameters.png
--------------------------------------------------------------------------------
/docs/Tutorial_OpenPIV/Images/User_Interface.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/docs/Tutorial_OpenPIV/Images/User_Interface.png
--------------------------------------------------------------------------------
/docs/Tutorial_OpenPIV/Images/help_snapshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenPIV/openpiv-matlab/HEAD/docs/Tutorial_OpenPIV/Images/help_snapshot.png
--------------------------------------------------------------------------------
/getext.m:
--------------------------------------------------------------------------------
1 | function ext = getext(filename)
2 | % ext = getext(filename) returns the extension of the filename
3 | [~,~,ext] = fileparts(filename);
4 | ext = ext(2:end);
--------------------------------------------------------------------------------
/quiver_complex_vector.m:
--------------------------------------------------------------------------------
1 | function quiver_complex_vector(vector,varargin)
2 | % compelements openpiv-matlab
3 | % for shortcut of quiver
4 |
5 | quiver(real(vector),imag(vector),varargin{:});
--------------------------------------------------------------------------------
/docs/Tutorial_OpenPIV/run:
--------------------------------------------------------------------------------
1 | pdflatex Tutorial_OpenPIV.tex
2 | bibtex Tutorial_OpenPIV
3 | pdflatex Tutorial_OpenPIV.tex
4 | pdflatex Tutorial_OpenPIV.tex
5 |
6 | pdfopen --file Tutorial_OpenPIV.pdf
7 |
--------------------------------------------------------------------------------
/isclose.m:
--------------------------------------------------------------------------------
1 | function out = isclose(a,b)
2 | % isclose complements isequal
3 | % for tests with assert in the case
4 | % where the differences are very small
5 | %
6 |
7 | EPS = 1e-6;
8 |
9 | out = abs(a-b) < EPS;
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | lastpath.mat
2 | *.m~
3 | *.bck
4 | *.txt
5 | vekplot2.m
6 | test/Particle Image Velocimetry Standard Project.html
7 | test/piv04_1.bmp
8 | test/piv04_2.bmp
9 | test/piv04_3.bmp
10 | test/piv04_4.bmp
11 | Tutorial_OpenPIV.toc
12 |
--------------------------------------------------------------------------------
/preprocess_invert.m:
--------------------------------------------------------------------------------
1 | function out = preprocess_invert(im)
% PREPROCESS_INVERT - Inverts the image (negative)
% Syntax:out = preprocess_invert(im)
%
% Subfunctions:
% See also:
% AUTHOR : Alex Liberzon
% Copyright (c)2017 Tel Aviv University
%%
% out = adapthisteq(im);
out = imcomplement(im);
--------------------------------------------------------------------------------
/test_fill_holes.m:
--------------------------------------------------------------------------------
1 | function test_fill_holes
2 | % test of fill_holes function
3 |
4 |
5 | vector = ones(5,5) + 1i*ones(5,5);
6 | vector(3,3) = 0 + 1i*0;
7 | tmp = fill_holes(vector);
8 | assert(isclose(tmp(3,3), 1+1i));
9 |
10 |
11 |
12 | vector = zeros(5,5) + 1i*zeros(5,5);
13 | vector(1,2) = 1;
14 | vector(2,3) = 1;
15 | vector(5,5) = 1;
16 | vector(3,4) = 1;
17 | tmp = fill_holes(vector);
18 | assert(all(tmp(:)));
--------------------------------------------------------------------------------
/preprocess_rotate.m:
--------------------------------------------------------------------------------
1 | function out = preprocess_rotate(im)
% PREPROCESS_ROTATE - rotates image
% Optional file header info (to give more details about the function than in the H1 line)
%
% Syntax:out = preprocess_template(im)
%
% Inputs:
%
% im - Description
%
% Outputs:
%
% out - Description
%
% Example:
%
% Line 1 of example
%
% Subfunctions:
% See also:
% AUTHOR : Alex Liberzon
% Copyright (c)2012 Tel Aviv University
%%
angle = -1;
% out = adapthisteq(im);
out = imadjust(imrotate(im,angle,'bilinear','crop'));
--------------------------------------------------------------------------------
/preprocess_template.m:
--------------------------------------------------------------------------------
1 | function out = preprocess_template(im)
% PREPROCESS_TEMPLATE - One line description of what the function or script performs (H1 line)
% Optional file header info (to give more details about the function than in the H1 line)
%
% Syntax:out = preprocess_template(im)
%
% Inputs:
%
% im - Description
%
% Outputs:
%
% out - Description
%
% Example:
%
% Line 1 of example
%
% Subfunctions:
% See also:
% AUTHOR : Alex Liberzon
% Copyright (c)2012 Tel Aviv University
%%
out = adapthisteq(im);
--------------------------------------------------------------------------------
/cross_correlate_rect.m:
--------------------------------------------------------------------------------
1 | function [c] = cross_correlate_rect(a2,b2,NfftHeight,NfftWidth)
2 |
3 | % temprorary solution
4 | a2 = a2 - mean2(a2);
5 | b2 = b2 - mean2(b2);
6 |
7 | b2 = b2(end:-1:1,end:-1:1);
8 |
9 | ffta=fft2(single(a2),NfftHeight,NfftWidth);
10 | fftb=fft2(single(b2),NfftHeight,NfftWidth);
11 |
12 | c = real(ifft2(ffta.*fftb));
13 |
14 | % another option not implemented yet, but b2 shall be larger than a2
15 | % see >> help normxcorr2
16 | % c = normxcorr2(b2,a2);
17 |
18 | c(c<0) = 0;
19 |
20 | return
21 |
--------------------------------------------------------------------------------
/preprocess_coronary.m:
--------------------------------------------------------------------------------
1 | function out = preprocess_template(im)
% PREPROCESS_TEMPLATE - One line description of what the function or script performs (H1 line)
% Optional file header info (to give more details about the function than in the H1 line)
%
% Syntax:out = preprocess_template(im)
%
% Inputs:
%
% im - Description
%
% Outputs:
%
% out - Description
%
% Example:
%
% Line 1 of example
%
% Subfunctions:
% See also:
% AUTHOR : Alex Liberzon
% Copyright (c)2012 Tel Aviv University
%%
% out = adapthisteq(im);
out = imadjust(im);
--------------------------------------------------------------------------------
/quivertxt.m:
--------------------------------------------------------------------------------
1 | function [h] = quivertxt(txtfile,varargin)
2 | % QUIVERTXT(TEXTFILENAME,VARARGIN) plots
3 | % quiver plot of the text file produced by the
4 | % OPENPIV program.
5 | %
6 | % Usage:
7 | % quivertxt('test_001_b.txt')
8 | %
9 | % See also: QUIVERM, QUIVER, OPENPIV
10 |
11 | % Author: Alex Liberzon
12 | % Date: July '99
13 | %
14 |
15 | [~,~,ext] = fileparts(txtfile);
16 | if isempty(ext)
17 | x = load([txtfile,'.txt']);
18 | else
19 | x = load(txtfile);
20 | end
21 | quiverm(x,varargin{:});
22 | axis ij
23 | axis tight
24 |
25 |
26 |
--------------------------------------------------------------------------------
/fill_holes.m:
--------------------------------------------------------------------------------
1 | function vector = fill_holes(vector)
2 | % Filling holes in the 2D matrix 'vector'
3 | % using inpaint_nans, thanks to John D'Errico
4 | % Note: openpiv-matlab marks the bad vectors by zero values
5 | % in the future to be replaced by NaNs
6 | % Last modified: Feb 24, 2016
7 | % Author: Alex Liberzon (alex.liberzon@gmail.com)
8 | %
9 | % See also INPAINT_NANS
10 | %
11 | vector(abs(vector) == 0) = NaN;
12 |
13 | while any(isnan(vector(:)))
14 | % vector = inpaint_nans(real(vector)) + 1i*inpaint_nans(imag(vector));
15 | vector = inpaint_nans(vector); % works for complex values out of the box
16 | end
17 |
--------------------------------------------------------------------------------
/plotarrow.m:
--------------------------------------------------------------------------------
1 | function plotarrow(h1,h2,x,y,u,v,scale)
2 |
3 | alpha = 0.33; % Size of arrow head relative to the length of the vector
4 | beta = 0.33; % Width of the base of the arrow head relative to the length
5 |
6 | u = u*scale;
7 | v = v*scale;
8 | uu = [x;x+u;NaN];
9 | vv = [y;y+v;NaN];
10 | % h1 = plot(uu(:),vv(:),'Color',color,'EraseMode','none');
11 |
12 | addpoints(h1, double(uu(:)),double(vv(:)));
13 | hu = [x+u-alpha*(u+beta*(v+eps));x+u; ...
14 | x+u-alpha*(u-beta*(v+eps));NaN];
15 | hv = [y+v-alpha*(v-beta*(u+eps));y+v; ...
16 | y+v-alpha*(v+beta*(u+eps));NaN];
17 | addpoints(h2, double(hu(:)),double(hv(:)));
18 | drawnow
19 | % h2 = plot(hu(:),hv(:),'Color',color,'EraseMode','none');
20 | % drawnow
--------------------------------------------------------------------------------
/preprocess_remove_vertical_strips.m:
--------------------------------------------------------------------------------
1 | function out = preprocess_remove_vertical_strips(im)
% PREPROCESS_TEMPLATE - One line description of what the function or script performs (H1 line)
% Optional file header info (to give more details about the function than in the H1 line)
%
% Syntax:out = preprocess_template(im)
%
% Inputs:
%
% im - Description
%
% Outputs:
%
% out - Description
%
% Example:
%
% Line 1 of example
%
% Subfunctions:
% See also:
% AUTHOR : Alex Liberzon
% Copyright (c)2012 Tel Aviv University
%%
%
% im = imcomplement(im);
% im = imadjust(im);
column_offsets = median(im);
column_offsets = column_offsets - min(column_offsets);
out = bsxfun(@minus,im,column_offsets);
% out = imadjust(out);
% out = adapthisteq(im);
--------------------------------------------------------------------------------
/find_second_peak.m:
--------------------------------------------------------------------------------
1 | function [peak2,pixi2,pixj2] = find_second_peak(c, pixi, pixj)
2 | % find second peak in the matrix c
3 | % typically c is an output of the cross-correlation
4 | %
5 | % Author: Alex Liberzon
6 | % Copyright (c) 2016 OpenPIV - www.openpiv.net
7 |
8 |
9 | % the logic is:
10 | % 1. find the peak
11 | % 2. make it a valley by flipping the peaks/valleys
12 | % 3. fill the hole, or fill the valey
13 | % 4. flip again, the peaks now are the secondary mountains only.
14 |
15 | if all(isnan(c(:)))
16 | peak2 = NaN;
17 | pixi2 = NaN;
18 | pixj2 = NaN;
19 | return
20 | end
21 |
22 | d = c(pixi,pixj) - c;
23 | e = imfill(d);
24 | f = max(e(:)) - e;
25 |
26 | [tmp,tmpi] = max(f);
27 | [peak2, pixj2] = max(tmp);
28 | pixi2 = tmpi(pixj2);
--------------------------------------------------------------------------------
/find_peak.m:
--------------------------------------------------------------------------------
1 | function [peak,x,y] = find_peak(c)
2 | % basic function that just finds the 2D maximum
3 | % and returns it x,y position in pixels.
4 | % The edges are removed, the maximum cannot be on the border
5 | %
6 | % Inputs:
7 | % c - double or single matrix (of size MxN)
8 | % peak - amplitude the maximum value
9 | % x,y - pixel positions (i,j < M,N) of the maximum value
10 | % the function returns NaNs for all matrices without the mean:
11 | % if all is NaN or the data is flat.
12 | %
13 | %
14 | %
15 | if all(isnan(c(:))) || min(c(:)) == max(c(:))
16 | peak = NaN;
17 | x = NaN;
18 | y = NaN;
19 | return
20 | else
21 |
22 | [tmp,tmpi] = max(c);
23 | [peak, y] = max(tmp);
24 | x = tmpi(y);
25 | end
26 |
--------------------------------------------------------------------------------
/openpiv_imread.m:
--------------------------------------------------------------------------------
1 | function im = openpiv_imread(image_name)
2 | % openpiv_imread encapsulates all the image reading functions
3 | % that can be imread for 'jpg','bmp', etc. or 'tiffread2' for TIFF
4 | % images from Insight (tm)
5 | % Usage:
6 | % >> im = openpiv_imread(directory, image_name);
7 | % >> imshow(im);
8 |
9 | try
10 | im = imread(image_name);
11 | catch
12 | tmp = tiffread2(image_name);
13 | im = im2double(tmp.data);
14 | end
15 |
16 | if ndims(im) == 3
17 | im = rgb2gray(im);
18 | end
19 |
20 | % % Custom pre-processing of images, default = 'imadjust'
21 | % preprocess = get(handles.checkbox_preprocess,'Value');
22 | % if preprocess
23 | % prepfun = str2func(handles.preprocess);
24 | % else
25 | % prepfun = @(x)imadjust(x); % default is to stretch the image
26 | % end
27 | % im = prepfun(im);
--------------------------------------------------------------------------------
/testFindSecondPeak.m:
--------------------------------------------------------------------------------
1 | function testFindSecondPeak
2 | %testFindPeak Unit test for find_peak in 2D matrix
3 |
4 | c = peaks(32);
5 |
6 | [~,pixi,pixj] = find_peak(c);
7 |
8 | [second_peak,pixi2,pixj2] = find_second_peak(c,pixi,pixj);
9 |
10 | if abs(second_peak - 6.8019) > 1e-4
11 | error('testFindPeak:notEqual', 'Incorrect output for peak.');
12 | end
13 |
14 |
15 | if ~isequal(pixi2, 25)
16 | error('testFindPeak:notEqual', 'Incorrect output for pixi.');
17 | end
18 |
19 |
20 | if ~isequal(pixj2, 8)
21 | error('testFindPeak:notEqual', 'Incorrect output for pixj.');
22 | end
23 |
24 |
25 | [~,pixi,pixj] = find_peak(ones(32));
26 | if ~isnan(pixi) || ~isnan(pixj)
27 | [second_peak,pixi2,pixj2] = find_second_peak(ones(32),pixi,pixj);
28 |
29 | if abs(second_peak - 0) > 1e-4
30 | error('testFindPeak:notEqual', 'Incorrect output for peak.');
31 | elseif ~isequal(pixi2, 1)
32 | error('testFindPeak:notEqual', 'Incorrect output for pixi.');
33 | elseif ~isequal(pixj2, 1 )
34 | error('testFindPeak:notEqual', 'Incorrect output for pixj.');
35 | end
36 | end
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/testFindPeak.m:
--------------------------------------------------------------------------------
1 | function testFindPeak
2 | %testFindPeak Unit test for find_peak in 2D matrix
3 |
4 | [peak,pixi,pixj] = find_peak(peaks(32));
5 |
6 |
7 | if abs(peak - 7.9770) > 1e-3
8 | error('testFindPeak:notEqual', 'Incorrect output for peak.');
9 | end
10 |
11 |
12 | if ~isequal(pixi, 25)
13 | error('testFindPeak:notEqual', 'Incorrect output for pixi.');
14 | end
15 |
16 |
17 | if ~isequal(pixj, 16)
18 | error('testFindPeak:notEqual', 'Incorrect output for pixj.');
19 | end
20 |
21 | [peak,pixi,pixj] = find_peak(ones(32));
22 | if ~isnan(peak)
23 | error('testFindPeak:notEqual', 'Incorrect output for peak.');
24 | elseif ~isnan(pixi)
25 | error('testFindPeak:notEqual', 'Incorrect output for pixi.');
26 | elseif ~isnan(pixj)
27 | error('testFindPeak:notEqual', 'Incorrect output for pixj.');
28 | end
29 |
30 |
31 | [peak,pixi,pixj] = find_peak(NaN*ones(32));
32 | if ~isnan(peak)
33 | error('testFindPeak:notEqual', 'Incorrect output for peak.');
34 | elseif ~isnan(pixi)
35 | error('testFindPeak:notEqual', 'Incorrect output for pixi.');
36 | elseif ~isnan(pixj )
37 | error('testFindPeak:notEqual', 'Incorrect output for pixj.');
38 | end
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/docs/Tutorial_OpenPIV/Tutorial_OpenPIV.tex:
--------------------------------------------------------------------------------
1 | \title{Tutorial OpenPIV (ver. 0.02)}
2 | \author{
3 | ver 01: ISTA - Institut f\"ur Str\"omungsmechanik und Technische Akustik\\
4 | TU - Berlin, \underline{Germany}\\
5 | ver 02: Turbulence Structure Laboratory, Tel Aviv University, Israel
6 | }
7 |
8 | \date{\today}
9 |
10 | %---------- Set-up ------------------------------------------------------
11 | \documentclass[10pt,a4paper]{article}
12 | \usepackage{graphicx,float,url,mathtools}
13 | \usepackage[T1]{fontenc}
14 | \usepackage{listings}
15 | \lstset{%
16 | language=Matlab,
17 | basicstyle=\footnotesize
18 | }
19 |
20 | %---------- Document ----------------------------------------------------
21 | \begin{document}
22 | \maketitle
23 | \tableofcontents
24 | \newpage
25 |
26 | \include{Contents/Contents}
27 |
28 | %---------- Bibliography ------------------------------------------------
29 | \bibliographystyle{unsrt} % this means that the order of references
30 | % is dtermined by the order in which the
31 | % \cite and \nocite commands appear
32 | \bibliography{PIVbib} % list here all the bibliographies that
33 | % % you need.
34 | \end{document}
35 |
--------------------------------------------------------------------------------
/openpiv_output.m:
--------------------------------------------------------------------------------
1 | function openpiv_output(res, no_filt_res, filt_res, dt, sclt, ...
2 | numrows, numcols, filepath,basename,baseext)
3 |
4 | % scale the pixels and apply the dt
5 |
6 | if sclt ~= 0
7 | res = res * sclt; % pixels to meters
8 | no_filt_res = no_filt_res * sclt;
9 | filt_res = filt_res * sclt;
10 | xUnits = 'm';
11 | else
12 | xUnits = 'pix';
13 | end
14 |
15 | if dt ~= 0
16 | res(:,3:4) = res(:,3:4)/dt;
17 | no_filt_res(:,3:4) = no_filt_res(:,3:4)/dt;
18 | filt_res(:,3:4) = filt_res(:,3:4) /dt;
19 | tUnits = 's';
20 | else
21 | tUnits = 'dt';
22 | end
23 |
24 | % Save results as ASCII (text) files:
25 | % Final (filtered, interpolated) results
26 | % fid = fopen([dirname,filesep,filenames(fileind,1:end-4),baseext],'w');
27 |
28 |
29 | final = fullfile(filepath,[basename,baseext]);
30 | write_openpiv_vec(final,res,xUnits,tUnits,numrows,numcols);
31 |
32 | % Unfiltered, uninterpolated: (comment with % sign if you don't need it)
33 | nofilt = fullfile(filepath,[basename,'_noflt.txt']);
34 | write_openpiv_vec(nofilt,no_filt_res,xUnits,tUnits,numrows,numcols);
35 |
36 |
37 | % Filtered, but not interpolated:
38 | filtered = fullfile(filepath,[basename,'_flt.txt']);
39 | write_openpiv_vec(filtered,filt_res,xUnits,tUnits,numrows,numcols);
--------------------------------------------------------------------------------
/ReadTXTDir.m:
--------------------------------------------------------------------------------
1 | function [filenames] = ReadTXTDir(dirname,data)
% READTXTDIR - Lists all the .txt files in the directory and returns the
% list of files for a certain pattern: '.txt' or '_noflt.txt' or '_flt.txt'
%
%
% Syntax:[filenames] = ReadTXTDir(dirname,data)
%
% Inputs:
%
% dirname - Directory name, default = '.'
% data - 'txt' or '_noflt.txt' or '_flt.txt'
%
% Outputs:
%
% filenames - list of files
%
% Example:
%
% txtfilenames = ReadTXTDir('./results','_noflt.txt');
%
%
% AUTHOR : Alex Liberzon
% Copyright (c)2012 Tel Aviv University
%%
if nargin < 2
data = 'txt';
end
switch data
case{'_noflt.txt'} % a)
direc = dir([dirname,filesep,'*_noflt.txt']);
case{'_flt.txt'} %b)
direc = dir([dirname,filesep,'*_flt.txt']);
case{'txt'} % c)
direc = dir([dirname,filesep,'*.txt']);
tmp = struct('name',[]);
k = 0;
for i=1:length(direc)
if length(findstr(direc(i).name,'_')) < 2
k = k + 1;
tmp(k).name = direc(i).name;
end
end
direc = tmp;
end
if ~isempty(str2num(direc(1).name(1:length(direc(1).name)-4)))
for i = 1:length(direc)
n(i) = str2num(direc(i).name(1:length(direc(i).name)-4));
end
[junk,j] = sort(n);
direc = direc(j);
end
filenames={};
[filenames{1:length(direc),1}] = deal(direc.name);
% filenames = sortrows(filenames);
--------------------------------------------------------------------------------
/calculate_subtract_average_image.m:
--------------------------------------------------------------------------------
1 | % CALCULATE_SUBTRACT_AVERAGE_IMAGE
2 | % reads through the image files in the selected directory (using UIGETDIR)
3 | % and calculates the average image. The average image is saved in the same directory
4 | % under AVERAGE.JPG
5 | % The average image is subtracted from all the files selected and the result images
6 | % are written in subdirectory /TEST with the same file names
7 | % It does both contrast enhancement and uneven background illumination correction
8 | % (including reflections)
9 | %
10 | % Author: Alex Liberzon
11 | % Copyright (c) 1999 alex.liberzon@gmail.com
12 |
13 |
14 |
15 |
16 | % d = dir('*.tif');
17 | [d,pth] = readImdir; % use the OpenPIV function with GUI
18 |
19 | success = mkdir(pth,'test');
20 | if success
21 | newdir = fullfile(pth,'test');
22 | else
23 | error('new directory is not created')
24 | end
25 |
26 | a = im2double(imread(fullfile(pth,d{1})));
27 |
28 | for i = 2:length(d)
29 | imfile = fullfile(pth,d{i});
30 | a = imadd(a,medfilt2(im2double(imread(imfile))));
31 | end
32 |
33 | averageImage = a/length(d);
34 | imwrite(averageImage,fullfile(newdir,'average.jpg'),'jpg');
35 |
36 | for i = 1:length(d)
37 | imfile = fullfile(pth,d{i});
38 | newfile = fullfile(newdir,d{i});
39 | imwrite(imsubtract(im2double(imread(imfile)),averageImage),newfile);
40 | end
--------------------------------------------------------------------------------
/Contents.m:
--------------------------------------------------------------------------------
1 | % OPENPIV-MATLAB
2 | %
3 | % Files
4 | % calculate_subtract_average_image - CALCULATE_SUBTRACT_AVERAGE_IMAGE
5 | % cross_correlate_rect - temprorary solution
6 | % fill_holes - new approach. use inpaint_nans, thanks to John D'Errico
7 | % find_displacement_rect - FIND_DISPLACEMENT - Finds the highest peak in cross-correlation
8 | % inpaint_nans - INPAINT_NANS: in-paints over nans in an array
9 | % openpivgui - - Graphical User Interface (GUI) to the OpenPIV Matlab
10 | % plotarrow -
11 | % preprocess_template - - One line description of what the function or script performs (H1 line)
12 | % quiverm - - plots quiver plot of matrix,
13 | % quivertxt - QUIVERTXT(TEXTFILENAME,VARARGIN) plots
14 | % readImDir -
15 | % ReadTXTDir - - Lists all the .txt files in the directory and returns the
16 | % readURAPIVdata - reads the directory of the experiment,
17 | % sub_pixel_velocity_rect - SUB_PIXEL_VELOCITY - Calculates Signal-To-Noise Ratio, fits Gaussian
18 | % tiffread2 - tiffread, version 2.5 December 21 2007
19 | % txt2mat - TXT2MAT
20 | % vekplot2 - - plot vectors as arrows
21 |
--------------------------------------------------------------------------------
/find_displacement_rect.m:
--------------------------------------------------------------------------------
1 | function [peak1,peak2,pixi,pixj] = find_displacement_rect(c,s2ntype)
2 | % FIND_DISPLACEMENT - Finds the highest peak in cross-correlation
3 | % matrix and the second peak (or mean value) for signal-to-noise
4 | % ratio calculation.
5 | % Inputs:
6 | % c - cross-correlation matrix
7 | % s2ntype - method (1 or 2) of S2N ratio calculation
8 | % Outputs:
9 | % peak1 = highest peak
10 | % peak2 = second highest peak (or mean value)
11 | % pixi,pixj = row,column indeces of the peak1
12 | %
13 | % Authors: Alex Liberzon, Roi Gurka, OpenPIV - www.openpiv.net
14 |
15 |
16 | % Find your majour peak = mean pixel displacement between
17 | % two interrogation areas:
18 |
19 | [NfftHeight,NfftWidth] = size(c);
20 |
21 | [peak1, pixi, pixj] = find_peak(c);
22 |
23 | % If the peak is found on the border, we should not accept it:
24 | if pixi==1 || pixj==1 || pixi == NfftHeight || pixj == NfftWidth
25 | peak2 = peak1; % we'll not accept this peak later, by means of SNR
26 | else
27 | % Look for the Signal-To-Noise ratio by
28 | % 1. Peak detectability method: First-to-second peak ratio
29 | % 2. Peak-to-mean ratio - Signal-to-noise estimation
30 |
31 | if s2ntype == 1 % First-to-second peak ratio
32 | [peak2,x2,y2] = find_second_peak(c,pixi,pixj);
33 | % If second peak is on the borders
34 | if x2 == 1 || y2 == 1 || x2 == NfftHeight || y2 == NfftWidth
35 | peak2 = peak1;
36 | end
37 |
38 | elseif s2ntype == 2 % PEAK-TO-MEAN VALUE RATIO:
39 | peak2 = mean2(abs(c));
40 | end % end of second peak search, both methods.
41 | end % end of if highest peak on the border
42 |
--------------------------------------------------------------------------------
/sub_pixel_velocity_rect.m:
--------------------------------------------------------------------------------
1 | function [peakx,peaky,s2n] = sub_pixel_velocity_rect(c,pixi,pixj,peak1,peak2,s2nl,ittWidth,ittHeight)
2 | % SUB_PIXEL_VELOCITY - Calculates Signal-To-Noise Ratio, fits Gaussian
3 | % bell, find sub-pixel displacement and scales it to the real velocity
4 | % according the the time interval and real-world-to-image-scale.
5 | %
6 | % Authors: Alex Liberzon & Roi Gurka
7 | % Date: Jul-20-99
8 | % Last Modified:
9 |
10 | % If peak2 equals to zero, it means that nothing was found,
11 | % and we'll divide by zero:
12 | if ~peak2
13 | s2n = Inf; % Just to protect from zero dividing.
14 | else
15 | s2n = peak1/peak2;
16 | end
17 |
18 | % If Signal-To-Noise ratio is lower than the limit, "mark" it:
19 | if s2n < s2nl
20 | peakx = ittHeight;
21 | peaky = ittWidth;
22 | else % otherwise, calculate the velocity
23 |
24 | % Sub-pixel displacement definition by means of
25 | % Gaussian bell.
26 |
27 | if pixi < 2 || pixi > size(c,1) - 2 || pixj < 2 || pixj > size(c,2) - 2
28 | peakx = ittHeight;
29 | peaky = ittWidth;
30 | return
31 | end
32 |
33 | try
34 | f0 = log(c(pixi,pixj));
35 | f1 = log(c(pixi-1,pixj));
36 | f2 = log(c(pixi+1,pixj));
37 | peakx = pixi + (f1-f2)/(2*f1-4*f0+2*f2);
38 | f0 = log(c(pixi,pixj));
39 | f1 = log(c(pixi,pixj-1));
40 | f2 = log(c(pixi,pixj+1));
41 | peaky = pixj+ (f1-f2)/(2*f1-4*f0+2*f2);
42 | catch
43 | peakx = ittHeight;
44 | peaky = ittWidth;
45 | end
46 |
47 | if ~isreal(peakx) || ~isreal(peaky)
48 | peakx = ittHeight;
49 | peaky = ittWidth;
50 | end
51 |
52 | end
53 |
54 |
55 | return
--------------------------------------------------------------------------------
/get_snr_for_piv.m:
--------------------------------------------------------------------------------
1 | function [F_sigma, sigma_A, sigma_n, SNR] = get_snr_for_piv(A)
2 | % MATLAB code for the estimation of PIV image noise
3 | % Author: Sven Scharnowski
4 | % Date: 25-May-2016
5 | % Copied by Alex Liberzon from the PDF of the article
6 | % in Exp Fluids (2016) 57:119
7 | % The input is a section of a PIV image with homogeneous noise "A"
8 | % (typically 128 x 128 px or larger)
9 | % the output is the loss-of-correlation due to image
10 | % noise "F_sigma", the standard deviation of the noise-free
11 | % image "sigma_A", the standard deviation of the image
12 | % noise "sigma_n" and the signal-to-noise ratio "SNR" ( = sigma_A/sigma_n)
13 | %
14 | % Pseudo Code:
15 | %
16 | % - computer normalized auto-correlation function
17 | % - select radius for fit function
18 | % - exclude center peak
19 | % - apply Gaussian 2D fit to extract F_sigma
20 | % - compute SNR, sigma_A and sigma_n
21 |
22 | R = normxcorr2_general(A,A);
23 |
24 | [xi,psi] = meshgrid(-size(A,2)+1:size(A,2)-1,...
25 | -size(A,1)+1:size(A,1)-1);
26 | fit_radius = 8;
27 | a = find(abs(xi)<=fit_radius & ...
28 | abs(psi)<=fit_radius & ~(xi == 0 & psi == 0));
29 |
30 | ft = fittype('F_s*exp( - ((xi/D)^2 + (psi/D)^2)*4)',...
31 | 'indep',{'xi','psi'},'depend','z');
32 |
33 | opts = fitoptions (ft);
34 | opts.MaxFunEvals = 1000;
35 | opts.MaxIter = 1000;
36 | opts.Tolx = 1e-8;
37 | opts.Lower = [0 0];
38 | opts.Upper = [2*fit_radius 2];
39 | opts.StartPoint = [3 1];
40 | fitresult = fit( [xi(a) psi(a)], R(a), ft, opts);
41 |
42 | F_sigma = min(1,fitresult.F_s);
43 | SNR = (1/F_sigma-1)^(-0.5);
44 | sigma_A = std(double(A(:)))*sqrt(F_sigma);
45 | sigma_n = std(double(A(:)))*sqrt(1-F_sigma);
46 |
47 |
--------------------------------------------------------------------------------
/write_openpiv_vec.m:
--------------------------------------------------------------------------------
1 | function success = write_openpiv_vec(filename,data,xUnits,tUnits,numrows,numcols)
2 | % success = write_openpiv_txt(filename,data,,xUnits,uUnits)
3 | % originally it was just
4 | % fid = fopen(fullfile(handles.path,[handles.files{fileind}(1:end-4),'.txt']),'w');
5 | % fprintf(fid,'%3d %3d %7.4f %7.4f %7.4f\n',res');
6 | % fclose(fid);
7 |
8 | % minimal implementation
9 | % filename is a full path
10 | % fullfile(handles.path,[handles.files{fileind}(1:end-4),'.txt'])
11 | fid = fopen(filename,'w');
12 |
13 | % data is called res in OpenPIV and it shall be N rows x 5 cols
14 | % in print, it's rotated to 5 rows x N cols
15 | if size(data,2) == 5
16 | data = data';
17 | elseif size(data,1) ~= 5
18 | error('Wrong number of columns');
19 | end
20 |
21 | % print the header
22 | % example of the VEC header
23 | % TITLE="E:\2CM_FP500_5%G_68K\C001H001S0015CC\Soapfilmone\Analysis\Run00000
24 | % 1.T000.D000.P000.H001.L.vec" VARIABLES="X mm", "Y mm", "U m/s", "V m/s",
25 | % "CHC", DATASETAUXDATA Application="PIV" DATASETAUXDATA
26 | % SourceImageWidth="1024" DATASETAUXDATA SourceImageHeight="1024"
27 | % DATASETAUXDATA MicrometersPerPixelX="19.530001" DATASETAUXDATA
28 | % MicrometersPerPixelY="19.530001" DATASETAUXDATA LengthUnit="mm"
29 | % DATASETAUXDATA OriginInImageX="0.000000" DATASETAUXDATA
30 | % OriginInImageY="0.000000" DATASETAUXDATA
31 | % MicrosecondsPerDeltaT="2000.000000" DATASETAUXDATA TimeUnit="ms"
32 | % DATASETAUXDATA SecondaryPeakNumber="0" DATASETAUXDATA
33 | % DewarpedImageSource="0" ZONE I=63, J=63, F=POINT
34 |
35 | zone = sprintf('ZONE I=%d, J=%d',numrows,numcols);
36 | header = sprintf('VARIABLES= "X %s", "Y %s", "U %s/%s", "V %s/%s", "CHC", %s\n',...
37 | xUnits,xUnits,xUnits,tUnits,xUnits,tUnits,zone);
38 |
39 | % "CHC"
40 |
41 | fprintf(fid,'%s',header);
42 | % print the data
43 | fprintf(fid,'%3d %3d %7.4f %7.4f %7.4f\n',data);
44 | fclose(fid);
45 |
46 | if fid ~= -1, success = true; else success = false; end
--------------------------------------------------------------------------------
/openpiv_filter.m:
--------------------------------------------------------------------------------
1 | function [res, filt_res] = openpiv_filter(res,numcols,numrows,outl)
2 | % openpiv_filter(res)
3 | % filters the results of the openpiv processing
4 | % of two images using the 1) global filter, 2) median filter
5 | % and also stores the data in several files
6 | % VEC file with the filtered and interpolated data
7 | % TXT files with the raw, not filtered and not interpolated data
8 | % Last modified: Feb 24, 2016
9 | % Author: Alex Liberzon alex dot liberzon at gmail dot com
10 | %
11 |
12 |
13 | % Reshape U and V matrices in two-dimensional grid and produce
14 | % velocity vector in U + i*V form (real and imaginary parts):
15 |
16 |
17 | u = reshape(res(:,3), numcols,numrows);
18 | v = reshape(res(:,4), numcols,numrows);
19 | vector = u + sqrt(-1)*v;
20 |
21 | vector(isnan(vector)) = 0;
22 |
23 | % vector = fill_holes(vector);
24 |
25 | % Remove outlayers - GLOBAL FILTERING
26 | vector(abs(vector)>mean(abs(vector(vector~=0)))*outl) = 0;
27 | % vector = fill_holes(vector);
28 |
29 | u = real(vector);
30 | v = imag(vector);
31 |
32 | % Adaptive Local Median filtering
33 |
34 | kernel = [-1 -1 -1; -1 8 -1; -1 -1 -1];
35 | tmpv = abs(conv2(v,kernel,'same'));
36 | tmpu = abs(conv2(u,kernel,'same'));
37 |
38 | % WE HAVE TO DECIDE WHICH LIMIT TO USE:
39 | % 1. Mean + 3*STD for each one separately OR
40 | % 2. For velocity vector length (and angle)
41 | % 3. OR OTHER.
42 |
43 | lmtv = mean(tmpv(tmpv~=0)) + 3*std(tmpv(tmpv~=0));
44 | lmtu = mean(tmpu(tmpu~=0)) + 3*std(tmpu(tmpu~=0));
45 |
46 | u_out = find(tmpu>lmtu);
47 | v_out = find(tmpv>lmtv);
48 |
49 | % Let's throw the outlayers out:
50 | u(u_out) = 0; u(v_out) = 0;
51 | v(v_out) = 0; v(u_out) = 0;
52 | vector = u + sqrt(-1)*v;
53 |
54 | res(:,3) = reshape(real(vector),numrows*numcols,1);
55 | res(:,4) = reshape(imag(vector),numrows*numcols,1);
56 |
57 | % Filtered results will be stored in '.._flt.txt' file
58 | filt_res = res;
59 |
60 | vector = fill_holes(vector);
61 | res(:,3) = reshape(real(vector),numrows*numcols,1);
62 | res(:,4) = reshape(imag(vector),numrows*numcols,1);
63 |
64 | % draw a bit nicer quiver with two colors
65 |
66 |
67 |
68 |
69 | % Results visualization
70 | % Only for final, filtered and interpolated data
71 | % imshow(a,[]);
72 | % hold on
73 | % quiverm(res,2,'g','LineWidth',1);
74 | % drawnow
75 | % F(:,fileind) = getframe;
76 |
--------------------------------------------------------------------------------
/quiverm.m:
--------------------------------------------------------------------------------
1 | function quiverm(x,varargin)
2 | % QUIVERM - plots quiver plot of matrix,
3 | % assuming first column as X, second as Y
4 | % third as U, and forth as V.
5 | %
6 | % QUIVERM(A,'r') - plots quiver plot
7 | % of matrix A.
8 | % Used by QUIVERTXT function.
9 | %
10 | %
11 | %
12 | % Author: Alex Liberzon
13 | % Modified at 23.06.05, to show only 'normal' vectors,
14 | % without outliers.
15 | % on IHW_Video
16 | % Modified on Jan 8, 2013, to avoild the unneccesary toolbox
17 | % added very useful prctile function (GPL)
18 | % see below - the user doesn't need the Stats toolbox anymore
19 | %
20 |
21 | if isstr(x)
22 | x = eval(x);
23 | end
24 |
25 | x(abs(x(:,3)) > prctile(abs(x(:,3)),99),3) = NaN;
26 | x(abs(x(:,4)) > prctile(abs(x(:,4)),99),4) = NaN;
27 | quiver(x(:,1),x(:,2),x(:,3),x(:,4),varargin{1:end});
28 |
29 | % quiver(x(:,1),x(:,2),x(:,3),x(:,4),varargin{:});
30 | return
31 | end
32 |
33 |
34 | function a = prctile(x, p)
35 |
36 | %{
37 | ## Copyright (C) 2001 Paul Kienzle
38 | ##
39 | ## This program is free software; you can redistribute it and/or modify
40 | ## it under the terms of the GNU General Public License as published by
41 | ## the Free Software Foundation; either version 2 of the License, or
42 | ## (at your option) any later version.
43 | ##
44 | ## This program is distributed in the hope that it will be useful,
45 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of
46 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47 | ## GNU General Public License for more details.
48 | ##
49 | ## You should have received a copy of the GNU General Public License
50 | ## along with this program; if not, write to the Free Software
51 | ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
52 |
53 | ## A = prctile(X,p)
54 | ##
55 | ## Computes the value associated with the p-th percentile of X. If X is
56 | ## a matrix, computes p for each column of X. If p is a vector, the
57 | ## returned value is a matrix with one row for each element of p and one
58 | ## column for each column of X.
59 | ##
60 | ## The first and last values are pegged at 0 percent and 100 percent
61 | ## respectively, and the rest of the values are uniformly spaced between
62 | ## them, with linear interpolation between the points. This is
63 | ## consistent with the definition of quantile given in the R statistics
64 | ## package, but inconsistent with that of the statistics toolbox from
65 | ## Matlab.
66 | %}
67 |
68 | y = sort(x);
69 | if size (y,1) == 1, y = y.'; end
70 | trim = 1 + (size(y,1)-1)*p(:)*0.01;
71 | delta = (trim - floor(trim))*ones(1,size(y,2));
72 | a = y(floor(trim), :) .* delta + y(ceil(trim), :) .* (1-delta);
73 |
74 | end
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OpenPIV
2 |
3 | ## OpenPIV - what is it for?
4 |
5 | OpenPIV is an initiative of scientists to develop a software, algorithms and methods for the state-of-the-art experimental tool of Particle Image Velocimetry (PIV) which are free, open source, and easy to operate.
6 | OpenPIV is the successor of the well known URAPIV software - it is faster, more friendly and much more flexible.
7 | OpenPIV is provided using Matlab, Python or 32bit Windows executable (based on C++ and Qt source).
8 |
9 | ## Webinar, July 2020
10 | [](http://www.youtube.com/watch?v=ci98mLhYEeg)
11 |
12 |
13 | ### How to cite this work
14 |
15 | Please cite our paper:
16 |
17 |
18 | Ben-Gida, H., Gurka, R. and Liberzon, A. (2020) OpenPIV-Matlab - An open-source software for particle image velocimetry; test case: birds' aerodynamics, SoftwareX, 12, p. 100585. doi: https://doi.org/10.1016/j.softx.2020.100585.
19 |
20 | and the code itself:
21 |
22 | Liberzon, Alex; Gurka, Roi; Ben-Gida, Hadar (2020): OpenPIV - Matlab. figshare. Software. https://doi.org/10.6084/m9.figshare.12330536
23 |
24 |
25 | ### How to download the software
26 | Please note that there are two versions of the GUI:
27 | 1. older Matlab version, before 2014b: https://github.com/OpenPIV/openpiv-matlab/releases/tag/v1.1
28 | 2. Newer Matlab versions, use https://github.com/OpenPIV/openpiv-matlab/archive/master.zip or clone this repository
29 |
30 | ### How to contribute ?
31 |
32 | 1. Open Github account
33 | 2. Visit our Git repositories through https://github.com/OpenPIV
34 | 3. Fork your favorite repository
35 | 4. Fix, commit, push to your repository and send us a pull request.
36 | 5. register on openpiv-develop mailing list through https://groups.google.com/forum/#!forum/openpiv-users
37 |
38 |
39 |
40 | ### Getting started tutorials
41 | 1. Matlab - see the screencast http://youtu.be/yg-LjAt-v3Q
42 | 2. Read the [Tutorial](https://github.com/OpenPIV/openpiv-matlab/raw/master/docs/Tutorial_OpenPIV/Tutorial_OpenPIV.pdf) by Sergio Bengoechea Lozano, TU Berlin
43 |
44 | 3. Python - http://www.openpiv.net/openpiv-python/
45 | 4. C++ - not ready yet
46 | 5. Spatial and Temporal Analysis Toolbox http://www.openpiv.net/openpiv-spatial-analysis-toolbox/
47 | 6. Pressure from PIV http://www.openpiv.net/openpiv-pressure
48 |
49 |
50 | ### Support and documentation
51 | How to get support? Where to ask questions? Use one of the following:
52 | 1. Google group https://groups.google.com/forum/#!forum/openpiv-users
53 | 2. e-mail to openpiv2008@gmail.com
54 | 3. Comment using Github page
55 |
56 | ### Frequently asked questions
57 | 1. [About OpenPIV](https://github.com/OpenPIV/openpiv.github.com/wiki/Frequently-Asked-Questions-about-OpenPIV)
58 | 2. [About PIV parameters](https://github.com/OpenPIV/openpiv.github.com/wiki/Frequently-Asked-Questions-about-PIV-parameters)
59 |
--------------------------------------------------------------------------------
/loadopenpivtxtdir.m:
--------------------------------------------------------------------------------
1 | function [v] = loadopenpivtxtdir(dirname,type)
2 |
3 | % default inputs
4 | if ~nargin
5 | dirname = '.';
6 | type = 'txt';
7 | end
8 |
9 | % default type input
10 | if nargin < 2 | isempty(type)
11 | type = 'txt';
12 | end
13 |
14 | if exist(dirname,'file') == 2
15 | fileList = {dirname};
16 | else
17 | % get the fileList
18 | fileList = listTXTfiles(dirname,type);
19 | end
20 | [v] = loadtopivmatstructure(dirname,fileList)
21 |
22 | % % make quiver of the files
23 | % for i = 1:numel(onlyTxtFiles)
24 | % data = load(onlyTxtFiles{i});
25 | % quiver(data(:,1),data(:,2),data(:,3),data(:,4));
26 | % end
27 |
28 | % % if in a single file, the data is like this:
29 | % plot(data(:,3).^2 + data(:,4).^2)
30 | end
31 |
32 | function [v] = loadtopivmatstructure(dirname,fileList)
33 |
34 | v = repmat(struct('x','y','vx','vy','choice','unitx','unity','namex','namey',...
35 | 'unitvx','unitvy','namevx','namevy','pivmat_version','ysign','Attributes',...
36 | 'name','setname','history','source'),1,length(fileList));
37 |
38 | tmp = load(fullfile(dirname,fileList{1}));
39 | x = tmp(:,1);
40 | y = tmp(:,2);
41 |
42 | lx = length(unique(x));
43 | ly = length(unique(y));
44 |
45 |
46 | for i = 1:length(fileList)
47 |
48 | % Import the file
49 | tmp = load(fullfile(dirname,fileList{i}));
50 |
51 | % convert into PIVMAT structure
52 |
53 | v(i).x = unique(tmp(:,1)).'; % reshape(tmp.data(:,2),lx,ly);
54 | v(i).y = unique(tmp(:,2)).'; % reshape(tmp.data(:,3),lx,ly);
55 | v(i).vx = reshape(tmp(:,3),lx,ly);
56 | v(i).vy = reshape(tmp(:,4),lx,ly);
57 | v(i).history = {['load_dpiv(',fileList{i},')']};
58 | v(i).unitx = 'mm';
59 | v(i).unitx = 'mm';
60 | v(i).unitvx = 'm/s';
61 | v(i).unitvx = 'm/s';
62 | v(i).namex = 'x';
63 | v(i).namey = 'y';
64 | v(i).namevx = 'u_x';
65 | v(i).namevy = 'u_y';
66 | v(i).setname = 'tmp';
67 | v(i).ysign = 'Y axis downward';
68 | v(i).pivmat_version = '1.90';
69 | end
70 |
71 |
72 | end
73 |
74 | function [fileList] = listTXTfiles(dirname,type)
75 | % reading the files from the directory of the TYPE only
76 | % TYPE: 'txt' or 'final'
77 | % 'noflt' or 'raw'
78 | % 'flt' or 'filtered'
79 | wd = cd;
80 | cd(dirname);
81 | fileList = dir('*.txt'); % list all files
82 | fltFileList = dir('*_flt.txt'); % only filtered (before interpolation)
83 | noFltFileList = dir('*_noflt.txt'); % only raw files (before filtering and interpolation)
84 | % list only final files, after filtering and interpolation
85 | switch type
86 | case{'txt','final'}
87 | fileList = setdiff(setdiff({fileList.name},{fltFileList.name}),{noFltFileList.name});
88 | case{'noflt','raw'}
89 | fileList = {noFltFileList.name};
90 | case{'flt','filtered'}
91 | fileList = {fltFileList.name};
92 | end
93 | cd(wd);
94 | end
95 |
--------------------------------------------------------------------------------
/readURAPIVdata.m:
--------------------------------------------------------------------------------
1 | function readURAPIVdata(dirname)
2 | % READURAPIVDATA reads the directory of the experiment,
3 | % where URAPIV saves the output and converts it to the
4 | % 3D matrix of U,V and 2D matrices of X,Y. The files
5 | % would be read and saved: *_flt.txt, *_noflt.txt, *.txt
6 | %
7 | % READURAPIVDATA('Y:\UraPIV\images','flt')
8 | %
9 | % Author: Alex Liberzon
10 | % Copyright (c) 2004, IHW, ETH Zurich
11 | % Last modified: April 23, 2004
12 | %
13 | %
14 |
15 | if ~nargin % debug run
16 | % dirname = 'Y:\UraPIV\images'
17 | disp('Usage: readURAPIVdata(''E:\aneurism\piv23apr_C001S0003'')');
18 | return
19 | end
20 |
21 | wd = cd;
22 |
23 | try
24 | cd(dirname);
25 |
26 |
27 | direcflt = dir(fullfile(dirname,'*_flt.txt'));
28 | direcnoflt = dir(fullfile(dirname,'*_noflt.txt'));
29 | direc = dir(fullfile(dirname,'*.txt'));
30 | filenames = {};
31 | filenamesflt = {};
32 | filenamesnoflt = {};
33 | [filenames{1:length(direc),1}] = deal(direc.name);
34 | [filenamesflt{1:length(direcflt),1}] = deal(direcflt.name);
35 | [filenamesnoflt{1:length(direcnoflt),1}] = deal(direcnoflt.name);
36 | [junk,i,j1] = intersect(filenamesflt,filenames);
37 | [junk2,i,j2] = intersect(filenamesnoflt,filenames);
38 | ind = 1:length(filenames);
39 | ind = setdiff(setdiff(ind,j1),j2);
40 | filenames = filenames(ind);
41 |
42 | filenames = sortrows(filenames);
43 | filenamesflt = sortrows(filenamesflt);
44 | filenamesnoflt = sortrows(filenamesnoflt);
45 |
46 |
47 |
48 | i = 1;
49 | data = load(filenames{i});
50 | x = data(:,1); y = data(:,2);
51 | u = repmat(0,[length(data),length(filenames)]);
52 | v = u;
53 | u(:,i) = data(:,3);
54 | v(:,i) = data(:,4);
55 |
56 | for i = 2:length(filenames)
57 | data = load(filenames{i});
58 | u(:,i) = data(:,3);
59 | v(:,i) = data(:,4);
60 | end
61 |
62 | cols = length(unique(x))-1; % notice the directions
63 | rows = length(unique(y))-1;
64 |
65 | x = reshape(x,[rows cols]);
66 | y = reshape(y,[rows cols]);
67 | u = reshape(u,[rows cols length(filenames)]);
68 | v = reshape(v,[rows cols length(filenames)]);
69 |
70 | save([filenames{1,1}(1:end-14)],'x','y','u','v');
71 |
72 | u = repmat(0,[length(data),length(filenamesflt)]);
73 | v = u;
74 | for i = 1:length(filenamesflt)
75 | data = load(filenamesflt{i});
76 | u(:,i) = data(:,3);
77 | v(:,i) = data(:,4);
78 | end
79 | u = reshape(u,[rows cols length(filenamesflt)]);
80 | v = reshape(v,[rows cols length(filenamesflt)]);
81 | save([filenames{1,1}(1:end-14),'_flt'],'x','y','u','v');
82 |
83 |
84 | u = repmat(0,[length(data),length(filenamesnoflt)]);
85 | v = u;
86 |
87 | for i = 1:length(filenamesnoflt)
88 | data = load(filenamesnoflt{i});
89 | u(:,i) = data(:,3);
90 | v(:,i) = data(:,4);
91 | end
92 | u = reshape(u,[rows cols length(filenamesnoflt)]);
93 | v = reshape(v,[rows cols length(filenamesnoflt)]);
94 | save([filenames{1,1}(1:end-14),'_noflt'],'x','y','u','v');
95 |
96 | cd(wd);
97 |
98 | catch
99 | cd(wd);
100 | error('Something wrong')
101 | end
102 |
103 |
104 |
--------------------------------------------------------------------------------
/read_pair_of_images_rect.m:
--------------------------------------------------------------------------------
1 | function [A,B,A1,B1,origin] = read_pair_of_images_rect(image1,image2,cropvec,ittWidth,ittHeight,ovlapHor,ovlapVer)
2 | % READ_PAIR_OF_IMAGES - reads two images (image1,image2) as BMP files
3 | % and crops them according to 'cropvec'
4 | % Inputs:
5 | % image1,image2 - BMP file names (string)
6 | % cropvec - 4 x 1 vector of follwoing values:
7 | % [left,top,right,bottom] - each value is a number of lines
8 | % of interrogation areas (ittWidthITT pixels)
9 | % which should be removed before the analysis.
10 | % itt - interrogation area size in pixels
11 | % spc - grid spacing (overlapping) size in pixels
12 | %
13 | % Authors: Alex Liberzon & Roi Gurka
14 | % Date: 20-Jul-99
15 | % Last modified:
16 | % Copyright(c) 1999, Alex Liberzon
17 |
18 | % A = double(imread(image1,'bmp'))/255;
19 | % B = double(imread(image2,'bmp'))/255;
20 | origin = [0,0];
21 |
22 | % image1 = fullfile(handles.path,handles.files{fileind});
23 | %image2 = fullfile(handles.path,handles.files{fileind+jump});
24 |
25 | % try
26 | A = openpiv_imread(image1);
27 | B = openpiv_imread(image2);
28 | % catch
29 | % warning off
30 | % tmp = tiffread2(image1);
31 | % A = im2double(tmp.data);
32 | % tmp = tiffread2(image2);
33 | % B = im2double(tmp.data);
34 | % end
35 | % if ndims(A) == 3
36 | % A = rgb2gray(A);
37 | % B = rgb2gray(B);
38 | % elseif ndims(A) == 2
39 | % A = double(A)/255;
40 | % B = double(B)/255;
41 | % end
42 |
43 |
44 |
45 | % Crop the images to the desired size and
46 | % cut the last couple of pixels, so we'll get the
47 | % integer number of interrogation areas
48 | %
49 | % ---- t ---
50 | % | |
51 | % | |
52 | % l r
53 | % | |
54 | % | |
55 | % --- b ----
56 | %
57 | %
58 |
59 | [verSizeA,horSizeA] = size(A);
60 | [verSizeB,horSizeB]=size(B);
61 | % A & B matrices HAVE to be of the same size, we take smallest:
62 | verSize = min(verSizeA,verSizeB); horSize = min(horSizeA,horSizeB);
63 | if any(cropvec)
64 | % A = imcrop(A,cropvec);
65 | % B = imcrop(B,cropvec);
66 | top = max([0,round(cropvec(2)/ittHeight)]); % top side of the image
67 | left = max([0,round(cropvec(1)/ittWidth)]); % left side of the image
68 | bottom = max([0,floor((verSize - cropvec(2) - cropvec(4))/ittHeight)]); % bottom side of the image
69 | right = max([0,floor((horSize - cropvec(1) - cropvec(3))/ittWidth)]); % right of the image
70 |
71 | A1 = A(1 + top*ittHeight:ovlapVer*floor(verSize/ovlapVer) - bottom*ittHeight,...
72 | 1+left*ittWidth:ovlapHor*floor(horSize/ovlapHor) - right*ittWidth);
73 | B1 = B(1 + top*ittHeight:ovlapVer*floor(verSize/ovlapVer) - bottom*ittHeight, ...
74 | 1+left*ittWidth:ovlapHor*floor(horSize/ovlapHor) - right*ittWidth);
75 | else
76 | A1 = A;
77 | B1 = B;
78 | left = 0;
79 | top = 0;
80 | end
81 |
82 | % [rows,cols]=size(A);
83 |
84 | if min(size(A1)) < 1
85 | error('Zero image or too large interrogation windows');
86 | end
87 | origin = [left*ittWidth,top*ittHeight];
88 |
89 | return
90 |
--------------------------------------------------------------------------------
/txt2mat.m:
--------------------------------------------------------------------------------
1 | function txt2mat(dirname,data,varargin)
2 | % TXT2MAT
3 | % dirname = 'F:\ftproot\Chris\1-ED26_jump10';
4 | % select if you want to process:
5 | % data = '_noflt.txt' % a) raw
6 | % data = '_flt.txt' % b) filtered, no interpolated or
7 | % data = 'txt' % c)filtered and interpolated.
8 |
9 | if ~nargin
10 | dirname = uigetdir;
11 | data = 'txt';
12 | end
13 |
14 |
15 | filenames = ReadTXTDir(dirname,data);
16 | if length([filenames{:}]) < 1, error('Files are not found'), return, end
17 |
18 | N = length(filenames);
19 |
20 | d = load(fullfile(dirname,filenames{1}));
21 | d = repmat(d,[1 1 N]);
22 | for i = 2:N
23 | d(:,:,i) = load(fullfile(dirname,filenames{i}));
24 | end
25 |
26 | x = d(:,1,:);
27 | x = x(x~=0);
28 | unX = unique(x);
29 |
30 | minX = min(unX);
31 | maxX = max(unX);
32 | dX = ceil((maxX-minX)/(length(unX)-1));
33 |
34 | y = d(:,2,:);
35 | y = y(y~=0);
36 | unY = unique(y);
37 |
38 | minY = min(unY);
39 | maxY = max(unY);
40 | dY = ceil((maxY-minY)/(length(unY)-1));
41 |
42 | [X,Y] = meshgrid(minX:dX:maxX,minY:dY:maxY);
43 | [r,c] = size(X);
44 |
45 | [U,V,dudx,dudy,dvdx,dvdy] = deal(zeros(r,c,N));
46 |
47 | for i = 1:N
48 | x = d(:,1,i);
49 | tmp = d(x~=0,:,i);
50 | y = tmp(:,2);
51 | x = tmp(:,1);
52 | for j = 1:length(x)
53 | [m,n] = find(X == x(j) & Y == y(j));
54 | U(m,n,i) = tmp(j,3);
55 | V(m,n,i) = tmp(j,4);
56 | end
57 | end
58 |
59 | if nargin < 3 | isempty(varargin{:})
60 | save(fullfile(dirname,'coordinates.mat'), 'X','Y');
61 | save(fullfile(dirname,'velocity.mat'), 'U', 'V');
62 | % zip(fullfile(dirname,'results.zip'),'*.txt');
63 | delete([dirname,filesep,'*.txt']);
64 | else
65 | save(fullfile(dirname,['coordinates',varargin{1},'.mat']), 'X','Y');
66 | save(fullfile(dirname,['velocity', varargin{1},'.mat']), 'U', 'V');
67 | zip(fullfile(dirname,['results', varargin{1},'.zip']),'*.txt',dirname);
68 | delete([dirname,filesep,'*.txt']);
69 | end
70 | disp('MAT files saved successfully, TXT is zipped')
71 | end
72 |
73 |
74 | function [filenames] = ReadTXTDir(dirname,data)
75 | if nargin < 2
76 | data = 'txt';
77 | end
78 |
79 | switch data
80 | case{'_noflt.txt'} % a)
81 | direc = dir([dirname,filesep,'*_noflt.txt']);
82 | case{'_flt.txt'} %b)
83 | direc = dir([dirname,filesep,'*_flt.txt']);
84 | case{'txt'} % c)
85 | direc = dir([dirname,filesep,'*.txt']);
86 | tmp = struct('name',[]);
87 | k = 0;
88 | for i=1:length(direc)
89 | if length(findstr(direc(i).name,'_')) < 2
90 | k = k + 1;
91 | tmp(k).name = direc(i).name;
92 | end
93 | end
94 | direc = tmp;
95 | end
96 |
97 | if ~isempty(direc(1).name) && ~isempty(str2num(direc(1).name(1:length(direc(1).name)-4)))
98 | for i = 1:length(direc)
99 | n(i) = str2num(direc(i).name(1:length(direc(i).name)-4));
100 | end
101 | [junk,j] = sort(n);
102 | direc = direc(j);
103 | end
104 |
105 | filenames={};
106 | [filenames{1:length(direc),1}] = deal(direc.name);
107 | % filenames = sortrows(filenames);
108 | end
109 |
110 |
--------------------------------------------------------------------------------
/loadopenpivtxt.m:
--------------------------------------------------------------------------------
1 | function [v] = loadopenpivtxt(dirname,type)
2 | %LOADOPENPIVTXT Loads vector fields created by OpenPIV (www.openpiv.net)
3 | % software.
4 | %
5 | % F = LOADOPENPIVTXT(FILENAME) loads the vector fields matching FILENAME
6 | % into the structure array F.
7 | %
8 | % The resulting structure array F can be displayed using SHOWVEC or
9 | % SHOWSCAL. For multi-frame images, only the first frame is loaded. Use
10 | % VEC2SCAL to compute scalar fields from vector fields.
11 | %
12 | % F = LOADOPENPIVTXT(DIRNAME,TYPE) loads all the vector fields matching TYPE
13 | % in the directory DIRNAME into the structure array F.
14 | % TYPE: 'raw' (or 'noflt')
15 | % 'filtered' (or 'flt')
16 | % 'final' (or 'txt') <- default
17 | %
18 | % Examples:
19 | % v = loadopenpivtxt('hipivdata') % reads all TXT files by default
20 | % v = loadopenpivtxt('.','raw')
21 | % v = loadopenpivtxt('.','txt')
22 | % v = loadopenpivtxt('hipivdata','raw')
23 | % v = loadopenpivtxt('hipivdata/00020359.txt') % single file
24 | %
25 | % Note: When used with DaVis files, LOADVEC works only under Windows
26 | % 32-bits edition. See VEC2MAT to convert DaVis files into Mat-files in
27 | % order to load them on other plateforms (Windows 64-bits, Linux, Mac...)
28 | %
29 | % See also LOADVEC, SHOWVEC
30 |
31 | % A. Liberzon, alexlib_at_eng.tau.ac.il
32 | % Revision: x.xx, Date: July 26, 2009
33 |
34 |
35 | % default inputs
36 | if ~nargin
37 | dirname = '.';
38 | type = 'txt';
39 | end
40 |
41 | % default type input
42 | if nargin < 2 | isempty(type)
43 | type = 'txt';
44 | end
45 |
46 | if exist(dirname,'file') == 2
47 | fileList = {dirname};
48 | dirname = '.';
49 | else
50 | % get the fileList
51 | fileList = listTXTfiles(dirname,type);
52 | end
53 | [v] = loadtopivmatstructure(dirname,fileList);
54 |
55 | % % make quiver of the files
56 | % for i = 1:numel(onlyTxtFiles)
57 | % data = load(onlyTxtFiles{i});
58 | % quiver(data(:,1),data(:,2),data(:,3),data(:,4));
59 | % end
60 |
61 | % % if in a single file, the data is like this:
62 | % plot(data(:,3).^2 + data(:,4).^2)
63 | end
64 |
65 | function [v] = loadtopivmatstructure(dirname,fileList)
66 | wd = cd;
67 | cd(dirname);
68 |
69 | v = repmat(struct('x','y','vx','vy','choice','unitx','unity','namex','namey',...
70 | 'unitvx','unitvy','namevx','namevy','pivmat_version','ysign','Attributes',...
71 | 'name','setname','history','source'),1,length(fileList));
72 |
73 | tmp = load(fileList{1});
74 | x = tmp(:,1);
75 | y = tmp(:,2);
76 |
77 | lx = length(unique(x));
78 | ly = length(unique(y));
79 |
80 |
81 | for i = 1:length(fileList)
82 |
83 | % Import the file
84 | tmp = load(fileList{i});
85 |
86 | % convert into PIVMAT structure
87 |
88 | v(i).x = unique(tmp(:,1)).'; % reshape(tmp.data(:,2),lx,ly);
89 | v(i).y = unique(tmp(:,2)).'; % reshape(tmp.data(:,3),lx,ly);
90 | v(i).vx = reshape(tmp(:,3),lx,ly);
91 | v(i).vy = reshape(tmp(:,4),lx,ly);
92 | v(i).history = {['load_dpiv(',fileList{i},')']};
93 | v(i).unitx = 'mm';
94 | v(i).unitx = 'mm';
95 | v(i).unitvx = 'm/s';
96 | v(i).unitvx = 'm/s';
97 | v(i).namex = 'x';
98 | v(i).namey = 'y';
99 | v(i).namevx = 'u_x';
100 | v(i).namevy = 'u_y';
101 | v(i).setname = 'tmp';
102 | v(i).ysign = 'Y axis upward';
103 | v(i).pivmat_version = '1.80';
104 | end
105 | cd(wd);
106 |
107 | end
108 |
109 | function [fileList] = listTXTfiles(dirname,type)
110 | % reading the files from the directory of the TYPE only
111 | % TYPE: 'txt' or 'final'
112 | % 'noflt' or 'raw'
113 | % 'flt' or 'filtered'
114 | wd = cd;
115 | cd(dirname);
116 | fileList = dir('*.txt'); % list all files
117 | fltFileList = dir('*_flt.txt'); % only filtered (before interpolation)
118 | noFltFileList = dir('*_noflt.txt'); % only raw files (before filtering and interpolation)
119 | % list only final files, after filtering and interpolation
120 | switch type
121 | case{'txt','final'}
122 | fileList = setdiff(setdiff({fileList.name},{fltFileList.name}),{noFltFileList.name});
123 | case{'noflt','raw'}
124 | fileList = {noFltFileList.name};
125 | case{'flt','filtered'}
126 | fileList = {fltFileList.name};
127 | end
128 | cd(wd);
129 | end
130 |
--------------------------------------------------------------------------------
/openpiv.m:
--------------------------------------------------------------------------------
1 | function openpiv(directory, image_ext, cropvec, ittWidth, ittHeight, ...
2 | ovlapHor, ovlapVer, pairs, jump, s2ntype, s2nl, outl)
3 |
4 | if ~nargin
5 | directory = 'test2';
6 | % image_ext = {'jpg','bmp','jpeg','tif','tiff','png'}; % all types
7 | image_ext = {'bmp'};
8 | cropvec = [0,0,0,0];
9 | ittWidth = 32;
10 | ittHeight = 32;
11 | ovlapHor = 16;
12 | ovlapVer = 16;
13 | pairs = 0; % if pairs _b, _a, then true, otehrwise (sequence) is false
14 | jump = 1; % if sequence we can process 1-2, 2-3 or 1-3, 2-4 and so on
15 | % change jump from 1 to any number which is smaller than the
16 | % number of files
17 | s2ntype = 1;
18 | s2nl = 100;
19 | outl = 10;
20 |
21 | end
22 |
23 |
24 | for i = 1:length(image_ext)
25 | images_list = dir(fullfile(directory, ['*.',image_ext{i}]));
26 | end
27 |
28 | % if crop_vec_flag
29 | % cropvec = rect;
30 | % else
31 | % cropvec = [0 0 0 0];
32 | % end
33 |
34 | % if jump_flag
35 | % if jump == -1
36 | % jump = 0;
37 | % end
38 | % end
39 |
40 | % prepare the list of pairs of images to process
41 | % depending on the sequence or pairs type of the list
42 | %
43 | if pairs % pairs, _a,_b or _b,_c or _LA, _LB, etc.
44 | A_list = 1:2:length(images_list)-jump;
45 | B_list = 2:2:length(images_list);
46 | else % sequence
47 | A_list = 1:length(images_list)-jump;
48 | B_list = 1+jump:length(images_list);
49 | end
50 |
51 | for i = 1:length(A_list)
52 |
53 | disp([A_list(i),B_list(i)])
54 |
55 | image1 = fullfile(directory,images_list(A_list(i)).name);
56 | image2 = fullfile(directory,images_list(B_list(i)).name);
57 |
58 | [a,b,a1,b1,origin] = read_pair_of_images_rect(image1,image2,cropvec,ittWidth,ittHeight,ovlapHor,ovlapVer);
59 | if isempty(a) || isempty(b)
60 | error('Something wrong with your images')
61 | end
62 | if isempty(a1) || isempty(b1)
63 | disp('Something is wrong with the cropped images');
64 | end
65 |
66 |
67 | % a1 = prepfun(a1);
68 | % b1 = prepfun(b1);
69 |
70 | [verSize,horSize]= size(a1);
71 |
72 | % Prepare the results storage;
73 |
74 | rows = 1:ovlapVer:verSize - ittHeight + 1;
75 | cols = 1:ovlapHor:horSize - ittWidth + 1;
76 |
77 | numcols = length(rows);
78 | numrows = length(cols);
79 |
80 | res = zeros(numcols*numrows,5);
81 | resind = 0;
82 |
83 | % a2 = zeros(ittHeight,ittWidth);
84 | % b2 = zeros(ittHeight,ittWidth);
85 | NfftWidth = 2*ittWidth;
86 | NfftHeight = 2*ittHeight;
87 |
88 | figure, hold on
89 | % imshow(imadjust(a),[]);
90 | imshow(a,[]);
91 | % hold on
92 | % h1 = animatedline('Color','y');
93 | % h2 = animatedline('Color','y');
94 |
95 | for m = rows % vertically
96 | for k = cols % horizontally
97 |
98 | a2 = a1(m:m+ittHeight-1,k:k+ittWidth-1);
99 | b2 = b1(m:m+ittHeight-1,k:k+ittWidth-1);
100 |
101 |
102 | c = cross_correlate_rect(a2,b2,NfftHeight,NfftWidth);
103 | % c = cross_correlate_rect(a2,b2,Nfftx,Nffty);
104 | if ~any(c(:)) % completely "black"
105 | u = 0;
106 | v = 0;
107 | y = origin(2) + m + ittHeight/2 - 1;
108 | x = origin(1) + k + ittWidth/2 - 1;
109 | continue
110 | end
111 |
112 | [peak1,peak2,pixi,pixj] = find_displacement_rect(c,s2ntype);
113 |
114 | [peakVer,peakHor,s2n] = sub_pixel_velocity_rect(c,pixi,pixj,peak1,peak2,s2nl,ittWidth,ittHeight);
115 |
116 | % Scale the pixel displacement to the velocity
117 | u = (ittWidth-peakHor);
118 | v = (ittHeight-peakVer);
119 | y = origin(2) + m + ittHeight/2-1;
120 | x = origin(1) + k + ittWidth/2-1;
121 |
122 | resind = resind + 1;
123 | res(resind,:) = [x y u v s2n];
124 |
125 | end
126 | end
127 |
128 | no_filt_res = res;
129 |
130 | [res, filt_res] = openpiv_filter(res,numcols,numrows,outl);
131 |
132 | % imshow(prepfun(a),[]);
133 | % imshow(a,[]);
134 | % hold on
135 | % clearpoints(h1);
136 | % clearpoints(h2);
137 | % for i = 1:length(res)
138 | % plotarrow(h1,h2,res(i,1),res(i,2),res(i,3),res(i,4));
139 | % end
140 | quiverm(res,'color','g','AutoScaleFactor',2);
141 | ind = (filt_res(:,3) ~= no_filt_res(:,3) | filt_res(:,4) ~= no_filt_res(:,4));
142 | if ~any(ind)
143 | quiverm(no_filt_res(ind,:),'color','r','AutoScaleFactor',1.25);
144 | end
145 | % for i = 1:length(res)
146 | % plotarrow(h1,h2,res(i,1),res(i,2),res(i,3),res(i,4));
147 | % end
148 | % drawnow
149 |
150 | basename = image1(1:end-4);
151 | baseext = '.vec';
152 |
153 | openpiv_output(res,no_filt_res,filt_res,dt,sclt,numrows, numcols, ...
154 | path,basename,baseext);
155 |
156 | end
157 |
158 |
--------------------------------------------------------------------------------
/test1/exp1_001_b.vec:
--------------------------------------------------------------------------------
1 | VARIABLES= "X pix", "Y pix", "U pix/dt", "V pix/dt", "CHC", ZONE I=11, J=15
2 | 16 16 -0.1636 5.1686 51.1181
3 | 48 16 -0.4586 5.7992 55.6021
4 | 80 16 -0.2630 6.1598 65.8990
5 | 112 16 -0.2679 6.0351 58.2946
6 | 144 16 -0.0622 5.7204 34.5564
7 | 176 16 0.6786 6.0622 47.7402
8 | 208 16 0.7675 5.8869 65.0185
9 | 240 16 0.7577 5.5986 35.6282
10 | 272 16 0.1492 5.0652 45.3810
11 | 304 16 -0.0227 6.1563 52.7018
12 | 336 16 0.4930 0.0000 84.4970
13 | 368 16 -0.2476 5.5832 77.3720
14 | 400 16 -0.2147 5.8245 64.0071
15 | 432 16 -0.1431 5.1407 76.1815
16 | 464 16 -0.0477 5.8587 47.8998
17 | 16 48 -0.4655 5.2019 58.2460
18 | 48 48 -0.2977 5.9401 46.8446
19 | 80 48 0.0786 6.2294 59.7890
20 | 112 48 0.1668 6.0707 69.0342
21 | 144 48 0.3254 5.7814 62.7016
22 | 176 48 0.6210 5.8875 52.3961
23 | 208 48 0.5715 6.1286 30.8576
24 | 240 48 -0.2729 5.2728 39.1695
25 | 272 48 -0.6022 4.8062 55.6717
26 | 304 48 -0.2287 5.2272 67.2784
27 | 336 48 -0.0420 5.6569 61.3309
28 | 368 48 -0.0731 5.8903 86.0525
29 | 400 48 -0.2899 5.5411 50.8946
30 | 432 48 -0.3299 5.2054 67.9761
31 | 464 48 -0.1488 6.7661 37.6503
32 | 16 80 0.0709 5.1342 69.9682
33 | 48 80 -0.8699 5.8676 69.5896
34 | 80 80 -0.0378 5.4531 50.1021
35 | 112 80 0.2746 5.6289 65.3885
36 | 144 80 0.7461 5.2295 54.0916
37 | 176 80 0.7769 5.2617 50.0544
38 | 208 80 -0.6664 5.7750 43.1688
39 | 240 80 -0.1018 5.3874 55.2668
40 | 272 80 -0.4082 4.9106 48.8141
41 | 304 80 -0.4223 5.0897 57.4123
42 | 336 80 -0.4578 5.5731 53.1943
43 | 368 80 -0.2372 5.9677 64.4187
44 | 400 80 -0.3613 5.9959 55.0152
45 | 432 80 -0.1776 5.2281 61.7613
46 | 464 80 -0.6098 6.2219 47.8443
47 | 16 112 0.0422 4.9986 52.8963
48 | 48 112 -0.1273 5.5896 49.1123
49 | 80 112 0.5504 5.1496 41.7486
50 | 112 112 0.8148 5.3060 50.0394
51 | 144 112 0.4240 5.0620 56.5876
52 | 176 112 0.0494 6.2009 58.3323
53 | 208 112 -0.1044 5.9932 49.4238
54 | 240 112 -0.1755 5.6541 63.7128
55 | 272 112 -0.2851 4.8089 50.9113
56 | 304 112 -0.2678 4.7911 48.2611
57 | 336 112 -0.7162 5.4427 64.8990
58 | 368 112 -0.7979 5.6964 53.7576
59 | 400 112 -0.2262 4.9300 50.7459
60 | 432 112 -0.6834 5.5993 47.8077
61 | 464 112 -0.2503 5.6618 60.5462
62 | 16 144 -0.6770 5.1447 39.6429
63 | 48 144 0.0989 5.9948 62.7155
64 | 80 144 -0.0208 5.5039 44.3911
65 | 112 144 0.0345 5.5074 45.0069
66 | 144 144 -0.0975 5.7869 58.4125
67 | 176 144 -0.8534 6.2139 69.1094
68 | 208 144 -0.0590 6.0081 79.9533
69 | 240 144 0.2949 5.7268 64.5413
70 | 272 144 0.1805 4.6946 45.0206
71 | 304 144 -0.6585 4.7478 65.4530
72 | 336 144 -0.5227 4.7978 50.1696
73 | 368 144 -0.4382 5.4220 42.9269
74 | 400 144 -0.2793 5.5809 52.9775
75 | 432 144 0.0258 5.0589 47.1058
76 | 464 144 -0.2023 5.0517 67.7849
77 | 16 176 -1.0731 4.7265 39.3656
78 | 48 176 -0.2206 5.4612 49.6006
79 | 80 176 0.2357 5.1468 61.6475
80 | 112 176 0.0735 5.3594 56.4787
81 | 144 176 -0.2689 5.8685 67.4252
82 | 176 176 0.0937 5.5931 48.1617
83 | 208 176 0.1743 5.5158 49.1661
84 | 240 176 0.3467 5.6808 48.6333
85 | 272 176 -0.0889 4.9699 55.9956
86 | 304 176 -0.8719 4.8771 70.8287
87 | 336 176 -0.8075 4.6278 61.1485
88 | 368 176 -0.6430 4.5734 60.4824
89 | 400 176 -0.5551 4.9505 62.1056
90 | 432 176 -0.0517 5.1283 72.8003
91 | 464 176 0.1011 4.8870 79.8012
92 | 16 208 -0.6859 4.6013 34.6090
93 | 48 208 -0.5754 5.1140 57.3562
94 | 80 208 -0.8088 4.9475 39.7291
95 | 112 208 -0.7497 5.7620 59.5666
96 | 144 208 -0.3788 5.6982 48.1300
97 | 176 208 -0.2081 5.4753 50.4366
98 | 208 208 0.0518 5.3449 45.4584
99 | 240 208 -0.3026 5.5178 58.4484
100 | 272 208 -0.1739 4.9957 54.0236
101 | 304 208 -0.4185 4.6619 53.2879
102 | 336 208 -0.7071 5.2125 54.7770
103 | 368 208 -0.7992 5.0371 62.2521
104 | 400 208 -0.6036 4.8993 54.6402
105 | 432 208 -0.0500 4.9806 73.0756
106 | 464 208 0.0606 4.8844 56.0320
107 | 16 240 -0.1193 0.0000 49.2493
108 | 48 240 -0.0911 5.1633 51.3906
109 | 80 240 -0.4567 5.4113 31.1567
110 | 112 240 -0.1954 5.0745 39.4395
111 | 144 240 0.1217 4.7177 44.5506
112 | 176 240 0.2902 5.5620 41.5339
113 | 208 240 0.1837 5.1260 52.1479
114 | 240 240 0.1645 5.3380 59.3534
115 | 272 240 0.2630 4.1851 55.4257
116 | 304 240 0.1397 4.6236 48.6988
117 | 336 240 0.0001 5.0994 69.2723
118 | 368 240 -0.3475 5.0426 57.7417
119 | 400 240 -0.2992 5.0590 51.1451
120 | 432 240 -0.2783 5.2730 75.0144
121 | 464 240 -0.1582 5.2556 66.8552
122 | 16 272 -0.2142 0.0000 52.2339
123 | 48 272 0.6402 5.5312 60.3927
124 | 80 272 0.6677 5.1054 49.1493
125 | 112 272 0.8406 4.6705 67.1575
126 | 144 272 0.7654 4.7352 62.2809
127 | 176 272 0.1432 5.0413 63.3973
128 | 208 272 -0.3590 5.0053 50.6115
129 | 240 272 -0.5591 5.1373 68.0656
130 | 272 272 -0.4618 4.6174 58.4653
131 | 304 272 -0.5373 4.6528 45.9647
132 | 336 272 -0.5339 5.1415 55.9344
133 | 368 272 -0.5926 5.0226 59.1168
134 | 400 272 -0.3731 5.0280 56.6566
135 | 432 272 -0.0042 4.8795 86.2875
136 | 464 272 -0.1551 4.9126 76.7173
137 | 16 304 0.2704 0.0000 37.3625
138 | 48 304 0.7590 5.3123 41.9720
139 | 80 304 0.7329 4.8422 38.9633
140 | 112 304 0.1429 4.9219 65.4833
141 | 144 304 0.0575 4.7817 66.0999
142 | 176 304 0.0442 4.5447 45.3353
143 | 208 304 0.1757 4.6214 51.1958
144 | 240 304 0.1643 5.2446 59.3918
145 | 272 304 0.0294 5.0045 63.8814
146 | 304 304 -0.2750 4.7873 55.9384
147 | 336 304 -0.3801 4.8281 75.4647
148 | 368 304 -0.5142 5.2192 63.7760
149 | 400 304 -0.3511 4.9611 74.0519
150 | 432 304 -0.2370 4.7709 63.4332
151 | 464 304 0.2142 4.6024 61.4815
152 | 16 336 1.0734 5.3234 38.9827
153 | 48 336 0.0881 4.8763 49.2116
154 | 80 336 0.7332 5.1582 56.3783
155 | 112 336 0.2676 5.1219 66.1471
156 | 144 336 -0.0829 4.9741 84.3262
157 | 176 336 0.1783 4.2114 58.5704
158 | 208 336 0.5715 4.7207 65.2604
159 | 240 336 -0.0646 4.5986 52.1476
160 | 272 336 -0.0453 4.9274 74.2459
161 | 304 336 -0.4401 4.8206 50.8114
162 | 336 336 -0.3862 5.0728 76.0751
163 | 368 336 -0.2971 5.0987 70.3864
164 | 400 336 -0.3135 5.3965 54.2405
165 | 432 336 -0.1244 5.2028 62.6046
166 | 464 336 0.2388 5.1166 76.2977
167 |
--------------------------------------------------------------------------------
/docs/Tutorial_OpenPIV/PIVbib.bib:
--------------------------------------------------------------------------------
1 | %% This BibTeX bibliography file was created using BibDesk.
2 | %% http://bibdesk.sourceforge.net/
3 |
4 |
5 | %% Created for Alex Liberzon at 2018-04-25 00:24:47 +0300
6 |
7 |
8 | %% Saved with string encoding Unicode (UTF-8)
9 |
10 |
11 |
12 | @article{Carr:2009,
13 | Author = {Z.R. Carr; K.A. Ahmed and D.J. Forliti},
14 | Journal = {Experiments in Fluids},
15 | Pages = {95-106},
16 | Title = {{Spatially correlated precision error in digital particle image velocimetry measurements of turbulent flows}},
17 | Volume = {47},
18 | Year = 2009}
19 |
20 | @article{Guezennec:1990,
21 | Author = {Y. G. Guezennec and N. Kiritsis},
22 | Journal = {Experiments in Fluids},
23 | Pages = {138-146},
24 | Title = {{Statistical investigation of errors in particle image velocimetry}},
25 | Volume = {10},
26 | Year = 1990}
27 |
28 | @article{Hart:1998,
29 | Address = {Lisbon, Portugal},
30 | Author = {Douglas P. Hart},
31 | Journal = {9th International Symposium on Applications of Laser Techniques to Fluid Mechanics},
32 | Month = {July},
33 | Title = {{The Elimination of Correlation Errors in PIV Processing}},
34 | Year = 1998}
35 |
36 | @article{Huang:1997,
37 | Address = {UK},
38 | Author = {H. Huang; D. Dabiri and M. Gharib},
39 | Journal = {Measurement Science and Technology},
40 | Month = {September},
41 | Pages = {1427-1440},
42 | Title = {{On errors of digital particle image velocimetry}},
43 | Volume = {8},
44 | Year = 1997}
45 |
46 | @article{Lebaek:2010,
47 | Author = {Jesper {Leb\ae{}k}; Marcin Blazniak Andreasen; Henrik Assenholm Andresen; Mads Bang and {S\o{}ren} Knudsen {K\ae{}r}},
48 | Journal = {Journal of Fuel Cell Science and Technology},
49 | Month = {June},
50 | Pages = {031001-1 to 031001-10},
51 | Title = {{Particle Image Velocimetry and Computational Fluid Dynamics Analysis of Fuel Cell Manifold}},
52 | Volume = {7},
53 | Year = 2010}
54 |
55 | @article{Piirto:2005,
56 | Author = {M. Piirto; H. Eloranta; P. Saarenrinne and R. Karvinen},
57 | Journal = {Experiments in Fluids},
58 | Pages = {571-588},
59 | Title = {{A comparative study of five different PIV interrogation algorithms}},
60 | Volume = {39},
61 | Year = 2005}
62 |
63 | @article{Prasad:2000,
64 | Author = {Ajay K. Prasad},
65 | Journal = {CURRENT SCIENCE},
66 | Month = {July},
67 | Number = {1},
68 | Pages = {51-60},
69 | Title = {{Particle image velocimetry}},
70 | Volume = {79},
71 | Year = 2000}
72 |
73 | @article{Reuss:2002,
74 | Address = {UK},
75 | Author = {David L. Reuss; Marcus Megerle and Volker Sick},
76 | Journal = {Measurement Science and Technology},
77 | Pages = {1029-1035},
78 | Title = {{Particle-image velocimetry measurement errors when imaging through a transparent engine cylinder}},
79 | Volume = {13},
80 | Year = 2002}
81 |
82 | @book{Westerweel:1993,
83 | Author = {Jerry Westerweel},
84 | Note = {Thesis Technische Universiteit Delft},
85 | Publisher = {Delft University Press},
86 | Title = {{Digital Particle Image Velocimetry: theory and application}},
87 | Year = 1993}
88 |
89 | @article{Westerweel:1997,
90 | Address = {UK},
91 | Author = {J. Westerweel},
92 | Journal = {Measurement Science and Technology},
93 | Month = {August},
94 | Pages = {1379-1392},
95 | Title = {{Fundamentals of digital particle image velocimetry}},
96 | Volume = {8},
97 | Year = 1997}
98 |
99 | @misc{carlier_2005,
100 | Author = {J. Carlier},
101 | Howpublished = {European Project 'Fluid image analisys and description' (FLUID) -- http://www.fluid.irisa.fr/},
102 | Title = {Second set of fluid mechanics image sequences},
103 | Year = {2005}}
104 |
105 | @article{deKat:2012,
106 | Author = {R. de Kat, B. W. van Oudheusden},
107 | Journal = {Experiments in Fluids},
108 | Pages = {1089-1106},
109 | Title = {{Instantaneous planar pressure determination from PIV in turbulent flow}},
110 | Volume = {52},
111 | Year = 2012}
112 |
113 | @article{vanOudheusden:2008,
114 | Author = {B W. van Oudheusden, F. Scarano, N.P. van Hinsberg, E.W.M. Roosenboom},
115 | Journal = {Journal of Wind Engineering and Industrial Aerodynamics},
116 | Pages = {913--922},
117 | Title = {{Quantitative visualization of the flow around a square-section cylinder at incidence}},
118 | Volume = {96},
119 | Year = 2008}
120 |
121 | @article{Taylor:2010,
122 | Author = {Taylor, Z.J. and Gurka, R. and Kopp, G.A. and Liberzon, A. },
123 | Date-Modified = {2018-04-24 21:24:41 +0000},
124 | Journal = {Instrumentation and Measurement, IEEE Transactions on},
125 | Month = {Dec.},
126 | Note = {\url{http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=5464317&isnumber=5609237}},
127 | Number = {12},
128 | Pages = {3262-3269},
129 | Title = {{Long-Duration Time-Resolved PIV to Study Unsteady Aerodynamics}},
130 | Volume = {59},
131 | Year = 2010}
132 |
133 | @misc{Liberzon:2009,
134 | Author = {A. Liberzon, R. Gurka, and Z. Taylor},
135 | Howpublished = {\url{http://www.openpiv.net}},
136 | Title = {{OpenPIV Home Page}},
137 | Year = 2009}
138 |
139 | @article{Choo:2010,
140 | Author = {Yeon Jun Choo, Chul-Hwa Song},
141 | Journal = {Nuclear Engineering and Design},
142 | Pages = {2215-2224},
143 | Title = {{PIV measurements of turbulent jet and pool mixing produced by a steam jet discharge in a subcooled water pool}},
144 | Volume = {240},
145 | Year = 2010}
146 |
147 | @article{Gono:2012,
148 | Author = {T. Gono, T. Syuto, T. Yamagata, N. Fujisawa},
149 | Journal = {Journal of Visualization},
150 | Pages = {231-240},
151 | Title = {{Time-resolved scanning stereo PIV measurement of three-dimensional velocity field of highly buoyant jet}},
152 | Volume = {15},
153 | Year = 2012}
154 |
155 | @article{Hui:2002,
156 | Address = {New York},
157 | Author = {Hui Hu, Tetsuo Saga, Toshio Kobayashi, Nobuyuki Taniguchi},
158 | Journal = {Ann. N.Y. Acad. Sci.},
159 | Pages = {254-259},
160 | Title = {{Simultaneous Velocity and Concentration Measurements of a Turbulent Jet Mixing Flow}},
161 | Volume = {972},
162 | Year = 2002}
163 |
164 | @article{Mi:2007,
165 | Author = {J. Mi, P. Kalt, G. J. Nathan, C. Y. Wong},
166 | Journal = {Experiments in Fluids},
167 | Pages = {625-637},
168 | Title = {{PIV measurements of a turbulent jet issuing from round sharp-edged plate}},
169 | Volume = {42},
170 | Year = 2007}
171 |
172 | @article{Schmid:2009,
173 | Address = {Melbourne, Victoria, Australia},
174 | Author = {P. J. Schmid, O. Pust},
175 | Journal = {8TH INTERNATIONAL SYMPOSIUM ON PARTICLE IMAGE VELOCIMETRY - PIV09},
176 | Month = {August 25-28},
177 | Title = {{PIV- and image-based flow analysis of a steady and pulsed jet using Dynamic Mode Decomposition }},
178 | Year = 2009}
179 |
--------------------------------------------------------------------------------
/docs/Tutorial_OpenPIV/Contents/Contents.tex:
--------------------------------------------------------------------------------
1 | %!TEX root=../Tutorial_OpenPIV.tex
2 | \section{Introduction}\label{Intro}
3 |
4 | \emph{OpenPIV} is an open source Particle Image Velocimetry (PIV) analysis software written in
5 | Python, MATLAB and C++. The aim of this document is to deliver a fast overview of the Matlab version of \emph{OpenPIV} only. For Python and C++ see in the respective repositories.
6 |
7 | The next sections will refer to the main parameters, the output files and other features
8 | of \emph{OpenPIV}. Some basics of the PIV technique will be mentioned as well. All the distributions of \emph{OpenPIV} and other related material can be found at \cite{Liberzon:2009,Taylor:2010}.
9 |
10 |
11 | This tutorial runs \emph{OpenPIV} on MATLAB, nevertheless similar set of parameters and output files applies for other distributions of \emph{OpenPIV}. The PIV-Data used as example in this tutorial was extracted from \cite{carlier_2005}.
12 |
13 | \section{Graphical User Interface GUI}\label{GUI}
14 |
15 | The Matlab version of OpenPIV has a graphical user interface (GUI). The program starts from the command window using:
16 |
17 |
18 |
19 | \begin{lstlisting}
20 | openpivgui
21 | \end{lstlisting}
22 |
23 |
24 |
25 | The following window is opened:
26 | \begin{figure}[H]
27 | \centering
28 | \includegraphics[width=\textwidth]{Images/open_window.png}
29 | \caption{First window of the OpenPIV}
30 | \label{fig:open_window}
31 | \end{figure}
32 |
33 | Figure \ref{fig:GUI} depicts the Graphical User Interface (GUI) of \emph{OpenPIV} after loading
34 | some example data.
35 |
36 | The first step before to run the PIV-Analysis is to load the PIV-Data. On the top left the menu bar is located. Under the drop-down menu ``File" the option ``Load" is available, either this option or its shortcut Ctrl+L opens a window where to select the data to be loaded. Once the PIV-Images are loaded the buttons $\ll$ and $\gg$ at the bottom jump between the loaded images, the indicator at the right-bottom displays the number of the currently shown image.
37 |
38 |
39 | \begin{figure}[H]
40 | \centering
41 | \includegraphics[width=\textwidth]{Images/User_Interface.png}
42 | \caption{OpenPIV Matlab GUI}
43 | \label{fig:GUI}
44 | \end{figure}
45 |
46 | \section{Load Data}\label{Load}
47 |
48 | Note that at least two PIV-Images are needed for a PIV-Analysis.
49 |
50 | \section{Analysis parameters}\label{parameters}
51 | In this section the parameters on the right side of the GUI are described.
52 |
53 | \begin{figure}[H]
54 | \centering
55 | \includegraphics[width=.35\textwidth]{Images/parameters.png}
56 | \caption{OpenPIV Matlab GUI}
57 | \label{fig:GUI}
58 | \end{figure}
59 |
60 | \subsection{Interrogation window size}\label{Interrogation_Window}
61 | The PIV-Image will be divided in interrogation windows. The width and the height control the size
62 | in pixels of the interrogation windows. Since the analysis is based on statistical a large
63 | interrogation windows are more robust against background noise and outlier vectors.
64 |
65 | \subsection{Spacing/Overlap}\label{Spacing}
66 | The horizontal and vertical parameters control the size of the correlation windows and set the
67 | resolution of the two components of the velocity field $u_{x}$ $u_{y}$. In figure \ref{fig:Iwindow}
68 | is depicted an example.
69 |
70 | \begin{figure}[H]
71 | \centering
72 | \includegraphics[width=0.4\textwidth]{Images/IntWindow.png}
73 | \caption{Image of 256x256 pixels divided by 32x32 interrogation window. Space/Overlap:
74 | red 16x16, green 32x32, blue 64x64 and yellow 128x128}
75 | \label{fig:Iwindow}
76 | \end{figure}
77 |
78 | \subsection{Signal-to-Noise ratio and filters}\label{S/N}
79 | In \emph{OpenPIV} are implemented two types of Signal-to-Noise ratio (S/N): \textbf{peak to the mean} and
80 | \textbf{peak to the second peak}. In the drop-down menu 1 corresponds to peak to the mean and 2 to peak
81 | to the second peak, option 1 is faster.
82 |
83 |
84 | The parameter S/N value is the threshold between the correct/wrong vectors according to the S/N type. There are no default values, a try-out has to be perform in order to find out the best
85 | value.
86 |
87 |
88 | \emph{OpenPIV} applies global and local filtering. By global filtering the obvious outlier vectors
89 | will be removed, i.e. the vectors which length is \textbf{larger than the mean of the flow
90 | field plus 3 times its standard deviation}. These are global outliers in the statistical sense.
91 |
92 |
93 | In order to find local vector outliers, i.e. vectors that are dissimilar from the close neighbors,
94 | a local filtering is performed on small neighborhoods of vectors, $3 \times 3$. Typically
95 | there are about 5 \% of erroneous vectors, these are removed and later the missing
96 | values are interpolated from the neighbor vector values.
97 |
98 | \subsection{Scale}\label{Scale}
99 |
100 | The scale value is a factor that will multiply the resulting vectors and the distances between the vectors. It helps with the visualization of the vectors but it has to be taken into account when the units are transform to physical units. if the value is null, the scaling is not used. The results will be in pixels.
101 |
102 | \subsection{Time interval}\label{dt}
103 |
104 | The time interval is a factor that will convert the displacement (in pixels or meters, if scale is applied) to the speed units (m/sec). the resulting vectors and the distances between the vectors. It helps with the visualization of the vectors but it has to be taken into account when the units are transform to physical units. If the value is null, then dt = 1 and the speed will remain as displacement, e.g. pix/dt
105 |
106 | \subsection{Outlier filter}\label{Outlier}
107 |
108 | The outlier filter value is the threshold of the global outlier filter and indicates \textbf{how many times the standard deviation of the whole vector field} is exceeded before the vector is considered as outlier.
109 |
110 | \subsection{Jump}\label{Jump}
111 |
112 | The jump value indicates how many PIV-Images are evaluated in the analysis. The count starts at
113 | the next image from the current one, i.e. if jump is equal to \emph{n} then \emph{OpenPIV} takes
114 | the current image plus the next \emph{n} PIV-Images for one analysis. Note that at least two
115 | PIV-Images are needed for the analysis, what makes jump values less than one pointless.
116 |
117 | \subsection{Select and reset Region Of Interest(ROI)}\label{ROI}
118 | The option Select ROI provides the possibility of evaluate only part of the whole PIV-Image. The
119 | option Reset ROI release the selected region. In figure \ref{fig:ROI} one example is shown.
120 |
121 | \begin{figure}[H]
122 | \centering
123 | \includegraphics[width=\textwidth]{Images/ROI.png}
124 | \caption{Results for a selected region}
125 | \label{fig:ROI}
126 | \end{figure}
127 |
128 | \subsection{Pre-processing}\label{Preprocessing}
129 | The pre-processing option applies transformation-image function to the PIV-Images. The current MATLAB version uses the function \emph{adapthisteq} which enhances the contrast of images. For more details see MATLAB help. The user can develop any image processing algorithm to run on each of the images before the FFT-based cross-correlation algorithm is applied to get PIV data.
130 |
131 | \section{Start and stop}\label{Start}
132 | The start and stop buttons either start or stop the analyze process.
133 |
134 | \section{Output files}\label{Output files}
135 |
136 | The first vectors results are depicted on the PIV-Images in the GUI, as figure \ref{fig:ROI} and
137 | \ref{fig:Out} illustrate. In the folder containing the PIV-Data \emph{OpenPIV} saves three lists
138 | of files: no filtered results \emph{dataName\_noflt.vec}, filtered results after global and local
139 | filters \emph{dataName\_flt.vec} and final results after filtering and interpolation
140 | \emph{dataName.vec}.
141 |
142 | The output file has a \textbf{header} that defines the variables and the units of the \textbf{5 columns} of data, i.e. $x$ $y$ $u_{x}$ $u_{y}$ $S/N$, and the size of the PIV field.
143 |
144 |
145 |
146 | \begin{lstlisting}
147 | VARIABLES= "X m", "Y m", "U m/s", "V m/s", "CHC", ZONE I=32, J=32
148 | \end{lstlisting}
149 |
150 |
151 | Possible units are `pix' or `m' and the velocity can be `pix/dt' or `m/s' (or `pix/s'). The first two columns correspond to the coordinates, the third and fourth to the two velocity vector components and the fifth column is the S/N ration. Note that the value is different if the user chose peak to second peak or peak to mean ratio as S/N type. The value of peak to second peak or peak to mean ratio is stored for further processing.
152 |
153 |
154 |
155 | The number of output files will be the number of loaded PIV-Images minus the selected jump value.
156 | \begin{figure}[H]
157 | \centering
158 | \includegraphics[width=\textwidth]{Images/output.png}
159 | \caption{Output results}
160 | \label{fig:Out}
161 | \end{figure}
162 |
163 |
164 | \clearpage
165 | \appendix
166 | \section*{Appendix: Units convert}\label{Units}
167 |
168 | Sometimes it makes more sense to leave the scale and time interval as default and transform the units of the results manually. In this case the velocity vector units of $u_{x}$ and $u_{y}$ are stored as displacements. \emph{OpenPIV} results are delivered in $[scale\times(pixels/\Delta t)]$,
169 | with $scale$ as the selected scale value and $\Delta t$ as the time interval between two images.
170 | In order to convert the units to $[m/s]$ is needed:
171 |
172 | \begin{itemize}
173 | \item the vector components $u_{x}$, $u_{y}$ in $[scale\times(pixels/\Delta t)]$
174 | \item the $\Delta t$ value in $s$
175 | \item the dimensionless scale value
176 | \item the relation between $meters$ and $pixels$ in that image $[m/pixels]$, i.e. the
177 | image size and the number of pixels.
178 | \end{itemize}
179 |
180 | The following example demonstrates a particular case of unit conversion.
181 |
182 | \begin{itemize}
183 | \item $u_{x}$ = 5, $u_{y}$ = 0 in $[scale\times(pixels/\Delta t)]$
184 | \item the $\Delta t$ = 0.5 in $s$
185 | \item scale value = 2
186 | \item image size 0.25 x 0.25 $m$ and 256 x 256 $pixels$, i.e. the relation between
187 | $meters$ and $pixels$ is 0.25/256 $[m/pixels]$.
188 | \item the conversion of $u_{x}$ from $[scale\times(pixels/\Delta t)]$ to $[m/s]$:
189 | \[
190 | \frac{u_{x}}{scale\times\Delta t}\times rel.\frac{m}{pixels}=\frac{5}{2\times0.5}\times
191 | \frac{0.25}{256}=0.0049 m/s
192 | \]
193 | \end{itemize}
194 |
--------------------------------------------------------------------------------
/readImDir.m:
--------------------------------------------------------------------------------
1 | function varargout = readImDir(varargin)
2 |
3 |
4 |
5 | gui_Singleton = 1;
6 | gui_State = struct('gui_Name', mfilename, ...
7 | 'gui_Singleton', gui_Singleton, ...
8 | 'gui_OpeningFcn', @readImDir_OpeningFcn, ...
9 | 'gui_OutputFcn', @readImDir_OutputFcn, ...
10 | 'gui_LayoutFcn', [] , ...
11 | 'gui_Callback', []);
12 | if nargin && ischar(varargin{1})%#ok
13 | % str2func(varargin{1})
14 | gui_State.gui_Callback = str2func(varargin{1});
15 | end
16 |
17 | if nargout
18 | [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
19 | else
20 | gui_mainfcn(gui_State, varargin{:});
21 | end
22 |
23 |
24 | % --- Executes just before readImDir is made visible.
25 | function readImDir_OpeningFcn(hObject, eventdata, handles, varargin)
26 |
27 | % This function has no output args, see OutputFcn.
28 | % hObject handle to figure
29 | % eventdata reserved - to be defined in a future version of MATLAB
30 | % handles structure with handles and user data (see GUIDATA)
31 | % varargin command line arguments to readImDir (see VARARGIN)
32 |
33 | % Choose default command line output for readImDir
34 |
35 | handles = guihandles;
36 | handles.output = hObject;
37 |
38 | if exist('lastpath.mat','file')
39 | load('lastpath.mat');
40 | if exist('lastpath','var') && exist(lastpath,'dir')
41 | handles.path = lastpath;
42 | else
43 | handles.path = pwd;
44 | end
45 | else
46 | handles.path = pwd;
47 | end
48 |
49 | handles.state3d = 0;
50 |
51 | % Update handles structure
52 | guidata(hObject, handles);
53 | update_gui(hObject,[],handles);
54 | % %
55 | % % % UIWAIT makes readImDir wait for user response (see %uiresume)
56 | uiwait(handles.fig);
57 |
58 |
59 | % --- Outputs from this function are returned to the command line.
60 | function varargout = readImDir_OutputFcn(hObject, eventdata, handles)
61 | % varargout cell array for returning output args (see VARARGOUT);
62 | % hObject handle to figure
63 | % eventdata reserved - to be defined in a future version of MATLAB
64 | % handles structure with handles and user data (see GUIDATA)
65 |
66 | % Get default command line output from handles structure
67 | % if nargout
68 | if isfield(handles,'filenames')
69 | varargout{1} = handles.filenames;
70 | varargout{2} = handles.path;
71 | % varargout{3} = handles.dT*handles.step;
72 | % varargout{4} = handles.scale;
73 | % varargout{5} = handles.state3d;
74 |
75 | else
76 | varargout{1} = {};
77 | varargout{2} = {};
78 | end
79 | close(handles.fig);
80 |
81 |
82 | % --- Executes on button press in pushbutton_load.
83 | function pushbutton_load_Callback(hObject, eventdata, handles)
84 | % hObject handle to pushbutton_load (see GCBO)
85 | % eventdata reserved - to be defined in a future version of MATLAB
86 | % handles structure with handles and user data (see GUIDATA)
87 |
88 | % Returns the names of the selected files
89 | handles.list_entries = get(handles.listbox_files,'String');
90 | handles.index_selected = get(handles.listbox_files,'Value');
91 | % jump = int32(str2num(get(handles.jump,'String')));
92 | jump = 1;
93 | if isempty(handles.index_selected) | min(handles.index_selected) < 3
94 | errordlg('Wrong selection','Incorrect Selection','modal')
95 | else
96 |
97 | switch length(handles.index_selected)
98 | case {1} % only the first file is selected,
99 | index = handles.index_selected;
100 | handles.filenames = handles.list_entries(index(1:jump:end));
101 | case {2}
102 | index = handles.index_selected; %
103 | handles.filenames = handles.list_entries(index(1:jump:end));
104 |
105 | otherwise
106 | handles.filenames = handles.list_entries(handles.index_selected(1:jump:end));
107 |
108 | end
109 |
110 | try
111 | lastpath = handles.path;
112 |
113 | save('lastpath.mat','lastpath');
114 | catch
115 | ;
116 | end
117 |
118 | guidata(hObject,handles);
119 | uiresume(handles.fig);
120 | end
121 |
122 |
123 |
124 |
125 | % --- Executes on button press in pushbutton_cancel.
126 | function pushbutton_cancel_Callback(hObject, eventdata, handles)
127 | % hObject handle to pushbutton_cancel (see GCBO)
128 | % eventdata reserved - to be defined in a future version of MATLAB
129 | % handles structure with handles and user data (see GUIDATA)
130 | uiresume(handles.fig);
131 |
132 |
133 | % --- Executes during object creation, after setting all properties.
134 | function listbox_files_CreateFcn(hObject, eventdata, handles)
135 |
136 |
137 | % --- Executes on selection change in listbox_files.
138 | function listbox_files_Callback(hObject, eventdata, handles)
139 |
140 | if strcmp(get(handles.fig,'SelectionType'),'open') % If double click
141 | index_selected = get(handles.listbox_files,'Value');
142 | file_list = get(handles.listbox_files,'String');
143 | filename = file_list{index_selected}; % Item selected in list box
144 | % keyboard
145 | if isdir([handles.path,filesep,filename]) % If directory
146 | if index_selected == 2
147 | handles.path = handles.path(1:max(findstr(handles.path,filesep)-1));
148 | elseif index_selected > 2
149 | handles.path = [handles.path,filesep,filename];
150 | end
151 | guidata(handles.fig,handles);
152 | update_gui(handles.fig,[],handles);
153 | end
154 | end
155 |
156 |
157 |
158 |
159 | % --- Executes during object creation, after setting all properties.
160 | function edit_path_CreateFcn(hObject, eventdata, handles)
161 | % hObject handle to edit_path (see GCBO)
162 | % eventdata reserved - to be defined in a future version of MATLAB
163 | % handles empty - handles not created until after all CreateFcns called
164 |
165 | % Hint: edit controls usually have a white background on Windows.
166 | % See ISPC and COMPUTER.
167 | if ispc
168 | set(hObject,'BackgroundColor','white');
169 | else
170 | set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
171 | end
172 | handles = guihandles;
173 | if ~isfield(handles,'path')
174 | handles.path = cd;
175 | end
176 | set(hObject,'String',handles.path);
177 | guidata(hObject,handles);
178 |
179 |
180 |
181 | function edit_path_Callback(hObject, eventdata, handles)
182 | % hObject handle to edit_path (see GCBO)
183 | % eventdata reserved - to be defined in a future version of MATLAB
184 | % handles structure with handles and user data (see GUIDATA)
185 |
186 | % Hints: get(hObject,'String') returns contents of edit_path as text
187 | % str2double(get(hObject,'String')) returns contents of edit_path as a double
188 |
189 | tmp = get(hObject,'String');
190 | if isdir(tmp)
191 | handles.path = tmp;
192 | else
193 | set(hObject,'String',handles.path);
194 | end
195 | guidata(hObject,handles);
196 | update_gui(hObject, [], handles);
197 |
198 | % --- Executes on button press in pushbutton_cd.
199 | function pushbutton_cd_Callback(hObject, eventdata, handles)
200 | % hObject handle to pushbutton_cd (see GCBO)
201 | % eventdata reserved - to be defined in a future version of MATLAB
202 | % handles structure with handles and user data (see GUIDATA)
203 | tmp = uigetdir(handles.path);
204 | if tmp > 0 & isdir(tmp), handles.path = tmp; end
205 | set(handles.edit_path,'String',handles.path);
206 | guidata(hObject, handles);
207 | update_gui(hObject, [], handles);
208 |
209 |
210 | function edit_scale_Callback(hObject, eventdata, handles)
211 | % hObject handle to edit_scale (see GCBO) eventdata reserved - to be
212 | % defined in a future version of MATLAB handles structure with handles
213 | % and user data (see GUIDATA)
214 |
215 | % Hints: get(hObject,'String') returns contents of edit_scale as text
216 | % str2double(get(hObject,'String')) returns contents of edit_scale
217 | % as a double
218 | if isnan(str2double(get(hObject,'String')))
219 | set(hObject,'String','1');
220 | end
221 | handles.scale = str2double(get(hObject,'String'));
222 | guidata(hObject,handles);
223 |
224 |
225 | % --- Executes during object creation, after setting all properties.
226 | function fig_CreateFcn(hObject, eventdata, handles)
227 | % hObject handle to fig (see GCBO)
228 | % eventdata reserved - to be defined in a future version of MATLAB
229 | % handles empty - handles not created until after all CreateFcns called
230 |
231 | handles = guihandles(hObject);
232 | movegui(hObject,'northwest')
233 |
234 |
235 | % --- Executes on button press in pushbutton_updir.
236 | function pushbutton_updir_Callback(hObject, eventdata, handles)
237 | % hObject handle to pushbutton_updir (see GCBO)
238 | % eventdata reserved - to be defined in a future version of MATLAB
239 | % handles structure with handles and user data (see GUIDATA)
240 |
241 | s = handles.path;
242 | s = s(1:max(3,max(findstr(s,filesep))-1));
243 | if exist(s,'dir')
244 | handles.path = s;
245 | end
246 | guidata(hObject,handles);
247 | update_gui(hObject,[],handles);
248 |
249 | function update_gui(hObject, eventdata, handles)
250 | % Self made UPDATE GUI function
251 | image_files = {'jpg','bmp','jpeg','tif','tiff','png'};
252 | if ~isdir(handles.path)
253 | handles.path = cd;
254 | end
255 |
256 | set(handles.edit_path,'String',handles.path);
257 | list = dir(handles.path);
258 | handles.files = {};
259 | for i = 1:length(list)
260 | if ismember(lower(getext(list(i).name)),image_files)
261 | handles.files = cat(1,handles.files,list(i).name);
262 | end
263 | end
264 | % handles.files = dir(fullfile(handles.path,'*.bmp'));
265 | % handles.files = cat(1,handles.files,dir(fullfile(handles.path,'*.jpg')));
266 | % handles.files = cat(1,handles.files,dir(fullfile(handles.path,'*.jpeg')));
267 | % handles.files = cat(1,handles.files,dir(fullfile(handles.path,'*.tif')));
268 | % handles.files = cat(1,handles.files,dir(fullfile(handles.path,'*.tiff')));
269 | % handles.files = cat(1,handles.files,dir(fullfile(handles.path,'*.png')));
270 |
271 | % list = dir(handles.path);
272 | ind = find(cat(1,list.isdir));
273 | set(handles.fig,'SelectionType','normal');
274 | set(handles.listbox_files,'String',{list(ind).name,handles.files{:}},'Value',1);
275 | guidata(handles.fig, handles);
276 |
277 |
278 |
279 |
280 | function jump_Callback(hObject, eventdata, handles)
281 | % hObject handle to jump (see GCBO)
282 | % eventdata reserved - to be defined in a future version of MATLAB
283 | % handles structure with handles and user data (see GUIDATA)
284 |
285 | % Hints: get(hObject,'String') returns contents of jump as text
286 | % str2double(get(hObject,'String')) returns contents of jump as a double
287 |
288 |
289 | % --- Executes during object creation, after setting all properties.
290 | function jump_CreateFcn(hObject, eventdata, handles)
291 | % hObject handle to jump (see GCBO)
292 | % eventdata reserved - to be defined in a future version of MATLAB
293 | % handles empty - handles not created until after all CreateFcns called
294 |
295 | % Hint: edit controls usually have a white background on Windows.
296 | % See ISPC and COMPUTER.
297 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
298 | set(hObject,'BackgroundColor','white');
299 | end
300 |
301 |
302 |
--------------------------------------------------------------------------------
/normxcorr2_general.m:
--------------------------------------------------------------------------------
1 | function [C,numberOfOverlapPixels] = normxcorr2_general(varargin)
2 | %NORMXCORR2_GENERAL Normalized two-dimensional cross-correlation.
3 | % [C,numberOfOverlapPixels] = NORMXCORR2_GENERAL(TEMPLATE,A) computes the
4 | % normalized cross-correlation of matrices TEMPLATE and A. The resulting
5 | % matrix C contains correlation coefficients and its values may range
6 | % from -1.0 to 1.0.
7 | %
8 | % [C,numberOfOverlapPixels] =
9 | % NORMXCORR2_GENERAL(TEMPLATE,A,requiredNumberOfOverlapPixels) sets to 0
10 | % all locations in C computed from positions where A and T overlap less
11 | % than requiredNumberOfOverlapPixels.
12 | % Larger values of requiredNumberOfOverlapPixels zero-out pixels on a
13 | % larger border around C.
14 | % Thus, larger values remove less stable computations but also limit the
15 | % capture range.
16 | % If the template is smaller than the image and it is desired that the
17 | % computation only be carried out when the template is fully overlapping
18 | % the image, requiredNumberOfOverlapPixels should be set to
19 | % numel(template).
20 | % The default is set to 0, meaning no modifications to C.
21 | %
22 | % Limitations of normxcorr2:
23 | % The documentation of normxcorr2 states that, "The matrix A must be
24 | % larger than the matrix TEMPLATE for the normalization to be
25 | % meaningful." It is implemented following the details of the paper "Fast
26 | % Normalized Cross-Correlation", by J. P. Lewis, Industrial Light &
27 | % Magic. This approach assumes the template is small relative to the
28 | % image and proceeds to calculate the normalization across the entire
29 | % template. This leads to correct computations wherever the template is
30 | % wholly overlapping with the image, but the computation is incorrect in
31 | % the borders of the output (the border size is proportional to the
32 | % template size). This problem is therefore worse for larger templates
33 | % to the point that, when the template is the same size as the image, the
34 | % only correct value is at the center pixel (where the images are fully
35 | % overlapping). Thus, if normxcorr2 is used for such things as
36 | % registering images of the same size, the result will be incorrect.
37 | %
38 | % The new normxcorr2_general:
39 | % normxcorr2_general is more general than normxcorr2 in that it gives
40 | % correct results everywhere regardless of the relative size of A and
41 | % TEMPLATE. It accomplishes this by computing the normalized correlation
42 | % only in the overlap regions between the two matrices. Thus, the result
43 | % is correct for all locations of correlation. The result is the same as
44 | % if the NCC were carried out in the spatial domain (which would take a
45 | % long time to compute for large matrices).
46 | %
47 | % Class Support
48 | % -------------
49 | % The input matrices can be numeric. The output matrix C is double.
50 | %
51 | % Example
52 | % -------
53 | % This example correlates an input with itself using normxcorr2 (the
54 | % built-in Matlab version) and normxcorr2_general (the general version).
55 | % Because the template is not small compared with the input image (they
56 | % are the same size in this case), the output of normxcorr2.m is
57 | % incorrect for most pixels. On the other hand, the general version is
58 | % correct at all locations, which can be easily verified analytically or
59 | % visually.
60 | %
61 | % Note that the image processing toolbox (IPT) is needed to run this
62 | % example since normxcorr2 is part of that toolbox. However,
63 | % normxcorr2_general does not require the IPT.
64 | %
65 | % input = repmat([1:6 5:-1:1],11,1);
66 | % normxcorr2_output = normxcorr2(input,input);
67 | % normxcorr2_general_output = normxcorr2_general(input,input);
68 | % figure;
69 | % subplot(2,2,1), imagesc(input); title('Input pattern');
70 | % subplot(2,2,3), imagesc(normxcorr2_output); title('Output of Matlab built-in normxcorr2');
71 | % subplot(2,2,4), imagesc(normxcorr2_general_output); title('Output of normxcorr2\_general');
72 | %
73 | % See also NORMXCORR2.
74 | %
75 | % References: Dirk Padfield. "Masked FFT registration". In Proc. Computer
76 | % Vision and Pattern Recognition, 2010.
77 | %
78 | % Author: Dirk Padfield, GE Global Research, padfield@research.ge.com
79 | %
80 |
81 | % Input-output specs
82 | % ------------------
83 | % T: 2-D, real, full matrix
84 | % logical, uint8, uint16, or double
85 | % no NaNs, no Infs
86 | % prod(size(T)) >= 2
87 | %
88 | % A: 2-D, real, full matrix
89 | % logical, uint8, uint16, or double
90 | % no NaNs, no Infs
91 | % prod(size(A)) >= 2
92 | %
93 | % C: double
94 |
95 | [T, A, requiredNumberOfOverlapPixels] = ParseInputs(varargin{:});
96 |
97 | sizeA = size(A);
98 | sizeT = size(T);
99 |
100 | % Find the number of pixels used for the calculation as the two images are
101 | % correlated. The size of this image will be the same as the correlation
102 | % image.
103 | numberOfOverlapPixels = local_sum(ones(sizeA),sizeT(1),sizeT(2));
104 |
105 | local_sum_A = local_sum(A,sizeT(1),sizeT(2));
106 | local_sum_A2 = local_sum(A.*A,sizeT(1),sizeT(2));
107 |
108 | % Note: diff_local_sums should be nonnegative, but it may have negative
109 | % values due to round off errors. Below, we use max to ensure the radicand
110 | % is nonnegative.
111 | diff_local_sums_A = ( local_sum_A2 - (local_sum_A.^2)./ numberOfOverlapPixels );
112 | clear local_sum_A2;
113 | denom_A = max(diff_local_sums_A,0);
114 | clear diff_local_sums_A;
115 |
116 | % Flip T in both dimensions so that its correlation can be more easily
117 | % handled.
118 | rotatedT = rot90(T,2);
119 | local_sum_T = local_sum(rotatedT,sizeA(1),sizeA(2));
120 | local_sum_T2 = local_sum(rotatedT.*rotatedT,sizeA(1),sizeA(2));
121 | clear rotatedT;
122 |
123 | diff_local_sums_T = ( local_sum_T2 - (local_sum_T.^2)./ numberOfOverlapPixels );
124 | clear local_sum_T2;
125 | denom_T = max(diff_local_sums_T,0);
126 | clear diff_local_sums_T;
127 |
128 | denom = sqrt(denom_T .* denom_A);
129 | clear denom_T denom_A;
130 |
131 | xcorr_TA = xcorr2_fast(T,A);
132 | clear A T;
133 | numerator = xcorr_TA - local_sum_A .* local_sum_T ./ numberOfOverlapPixels;
134 | clear xcorr_TA local_sum_A local_sum_T;
135 |
136 | % denom is the sqrt of the product of positive numbers so it must be
137 | % positive or zero. Therefore, the only danger in dividing the numerator
138 | % by the denominator is when dividing by zero. We know denom_T~=0 from
139 | % input parsing; so denom is only zero where denom_A is zero, and in these
140 | % locations, C is also zero.
141 | C = zeros(size(numerator));
142 | tol = 1000*eps( max(abs(denom(:))) );
143 | i_nonzero = find(denom > tol);
144 | C(i_nonzero) = numerator(i_nonzero) ./ denom(i_nonzero);
145 | clear numerator denom;
146 |
147 | % Remove the border values since they result from calculations using very
148 | % few pixels and are thus statistically unstable.
149 | % By default, requiredNumberOfOverlapPixels = 0, so C is not modified.
150 | if( requiredNumberOfOverlapPixels > max(numberOfOverlapPixels(:)) )
151 | error(['ERROR: requiredNumberOfOverlapPixels ' num2str(requiredNumberOfOverlapPixels) ...
152 | ' must not be greater than the maximum number of overlap pixels ' ...
153 | num2str(max(numberOfOverlapPixels(:))) '.']);
154 | end
155 | C(numberOfOverlapPixels < requiredNumberOfOverlapPixels) = 0;
156 |
157 |
158 | %-------------------------------
159 | % Function local_sum
160 | %
161 | function local_sum_A = local_sum(A,m,n)
162 |
163 | % This algorithm depends on precomputing running sums.
164 |
165 | % If m,n are equal to the size of A, a faster method can be used for
166 | % calculating the local sum. Otherwise, the slower but more general method
167 | % can be used. The faster method is more than twice as fast and is also
168 | % less memory intensive.
169 | if( m == size(A,1) && n == size(A,2) )
170 | s = cumsum(A,1);
171 | c = [s; repmat(s(end,:),m-1,1) - s(1:end-1,:)];
172 | s = cumsum(c,2);
173 | clear c;
174 | local_sum_A = [s, repmat(s(:,end),1,n-1) - s(:,1:end-1)];
175 | else
176 | % Break the padding into parts to save on memory.
177 | B = zeros(size(A,1)+2*m,size(A,2));
178 | B(m+1:m+size(A,1),:) = A;
179 | s = cumsum(B,1);
180 | c = s(1+m:end-1,:)-s(1:end-m-1,:);
181 | d = zeros(size(c,1),size(c,2)+2*n);
182 | d(:,n+1:n+size(c,2)) = c;
183 | s = cumsum(d,2);
184 | local_sum_A = s(:,1+n:end-1)-s(:,1:end-n-1);
185 | end
186 |
187 |
188 | %-------------------------------
189 | % Function xcorr2_fast
190 | %
191 | function cross_corr = xcorr2_fast(T,A)
192 |
193 | T_size = size(T);
194 | A_size = size(A);
195 | outsize = A_size + T_size - 1;
196 |
197 | % Figure out when to use spatial domain vs. freq domain
198 | conv_time = time_conv2(T_size,A_size); % 1 conv2
199 | fft_time = 3*time_fft2(outsize); % 2 fft2 + 1 ifft2
200 |
201 | if (conv_time < fft_time)
202 | cross_corr = conv2(rot90(T,2),A);
203 | else
204 | cross_corr = freqxcorr(T,A,outsize);
205 | end
206 |
207 |
208 | %-------------------------------
209 | % Function freqxcorr
210 | %
211 | function xcorr_ab = freqxcorr(a,b,outsize)
212 |
213 | % Find the next largest size that is a multiple of a combination of 2, 3,
214 | % and/or 5. This makes the FFT calculation much faster.
215 | optimalSize(1) = FindClosestValidDimension(outsize(1));
216 | optimalSize(2) = FindClosestValidDimension(outsize(2));
217 |
218 | % Calculate correlation in frequency domain
219 | Fa = fft2(rot90(a,2),optimalSize(1),optimalSize(2));
220 | Fb = fft2(b,optimalSize(1),optimalSize(2));
221 | xcorr_ab = real(ifft2(Fa .* Fb));
222 |
223 | xcorr_ab = xcorr_ab(1:outsize(1),1:outsize(2));
224 |
225 |
226 | %-------------------------------
227 | % Function time_conv2
228 | %
229 | function time = time_conv2(obssize,refsize)
230 |
231 | % time a spatial domain convolution for 10-by-10 x 20-by-20 matrices
232 |
233 | % a = ones(10);
234 | % b = ones(20);
235 | % mintime = 0.1;
236 |
237 | % t1 = cputime;
238 | % t2 = t1;
239 | % k = 0;
240 | % while (t2-t1) 3 )
289 | error('ERROR: The number of arguments must be either 2 or 3. Please see the documentation for details.');
290 | end
291 |
292 | T = varargin{1};
293 | A = varargin{2};
294 |
295 | if( nargin == 3 )
296 | requiredNumberOfOverlapPixels = varargin{3};
297 | else
298 | requiredNumberOfOverlapPixels = 0;
299 | end
300 |
301 | % The following requires the image processing toolbox, so it is commented
302 | % out here for generality.
303 | %iptcheckinput(T,{'logical','numeric'},{'real','nonsparse','2d','finite'},mfilename,'T',1)
304 | %iptcheckinput(A,{'logical','numeric'},{'real','nonsparse','2d','finite'},mfilename,'A',2)
305 |
306 | checkSizesTandA(T,A)
307 |
308 | % See geck 342320. If either A or T has a minimum value which is negative, we
309 | % need to shift the array so all values are positive to ensure numerically
310 | % robust results for the normalized cross-correlation.
311 | A = shiftData(A);
312 | T = shiftData(T);
313 |
314 | checkIfFlat(T);
315 |
316 | %-----------------------------------------------------------------------------
317 | function B = shiftData(A)
318 |
319 | B = double(A);
320 |
321 | is_unsigned = isa(A,'uint8') || isa(A,'uint16') || isa(A,'uint32');
322 | if ~is_unsigned
323 |
324 | min_B = min(B(:));
325 |
326 | if min_B < 0
327 | B = B - min_B;
328 | end
329 |
330 | end
331 |
332 | %-----------------------------------------------------------------------------
333 | function checkSizesTandA(T,A)
334 |
335 | if numel(T) < 2
336 | eid = sprintf('Images:%s:invalidTemplate',mfilename);
337 | msg = 'TEMPLATE must contain at least 2 elements.';
338 | error(eid,'%s',msg);
339 | end
340 |
341 | %-----------------------------------------------------------------------------
342 | function checkIfFlat(T)
343 |
344 | if std(T(:)) == 0
345 | eid = sprintf('Images:%s:sameElementsInTemplate',mfilename);
346 | msg = 'The values of TEMPLATE cannot all be the same.';
347 | error(eid,'%s',msg);
348 | end
349 |
350 | %-----------------------------------------------------------------------------
351 | function [newNumber] = FindClosestValidDimension(n)
352 |
353 | % Find the closest valid dimension above the desired dimension. This
354 | % will be a combination of 2s, 3s, and 5s.
355 |
356 | % Incrementally add 1 to the size until
357 | % we reach a size that can be properly factored.
358 | newNumber = n;
359 | result = 0;
360 | newNumber = newNumber - 1;
361 | while( result ~= 1 )
362 | newNumber = newNumber + 1;
363 | result = FactorizeNumber(newNumber);
364 | end
365 |
366 | %-----------------------------------------------------------------------------
367 | function [n] = FactorizeNumber(n)
368 |
369 | for ifac = [2 3 5]
370 | while( rem(n,ifac) == 0 )
371 | n = n/ifac;
372 | end
373 | end
--------------------------------------------------------------------------------
/inpaint_nans.m:
--------------------------------------------------------------------------------
1 | function B=inpaint_nans(A,method)
% INPAINT_NANS: in-paints over nans in an array
% usage: B=INPAINT_NANS(A) % default method
% usage: B=INPAINT_NANS(A,method) % specify method used
%
% Solves approximation to one of several pdes to
% interpolate and extrapolate holes in an array
%
% arguments (input):
% A - nxm array with some NaNs to be filled in
%
% method - (OPTIONAL) scalar numeric flag - specifies
% which approach (or physical metaphor to use
% for the interpolation.) All methods are capable
% of extrapolation, some are better than others.
% There are also speed differences, as well as
% accuracy differences for smooth surfaces.
%
% methods {0,1,2} use a simple plate metaphor.
% method 3 uses a better plate equation,
% but may be much slower and uses
% more memory.
% method 4 uses a spring metaphor.
% method 5 is an 8 neighbor average, with no
% rationale behind it compared to the
% other methods. I do not recommend
% its use.
%
% method == 0 --> (DEFAULT) see method 1, but
% this method does not build as large of a
% linear system in the case of only a few
% NaNs in a large array.
% Extrapolation behavior is linear.
%
% method == 1 --> simple approach, applies del^2
% over the entire array, then drops those parts
% of the array which do not have any contact with
% NaNs. Uses a least squares approach, but it
% does not modify known values.
% In the case of small arrays, this method is
% quite fast as it does very little extra work.
% Extrapolation behavior is linear.
%
% method == 2 --> uses del^2, but solving a direct
% linear system of equations for nan elements.
% This method will be the fastest possible for
% large systems since it uses the sparsest
% possible system of equations. Not a least
% squares approach, so it may be least robust
% to noise on the boundaries of any holes.
% This method will also be least able to
% interpolate accurately for smooth surfaces.
% Extrapolation behavior is linear.
%
% method == 3 --+ See method 0, but uses del^4 for
% the interpolating operator. This may result
% in more accurate interpolations, at some cost
% in speed.
%
% method == 4 --+ Uses a spring metaphor. Assumes
% springs (with a nominal length of zero)
% connect each node with every neighbor
% (horizontally, vertically and diagonally)
% Since each node tries to be like its neighbors,
% extrapolation is as a constant function where
% this is consistent with the neighboring nodes.
%
% method == 5 --+ See method 2, but use an average
% of the 8 nearest neighbors to any element.
% This method is NOT recommended for use.
%
%
% arguments (output):
% B - nxm array with NaNs replaced
%
%
% Example:
% [x,y] = meshgrid(0:.01:1);
% z0 = exp(x+y);
% znan = z0;
% znan(20:50,40:70) = NaN;
% znan(30:90,5:10) = NaN;
% znan(70:75,40:90) = NaN;
%
% z = inpaint_nans(znan);
%
%
% See also: griddata, interp1
%
% Author: John D'Errico
% e-mail address: woodchips@rochester.rr.com
% Release: 2
% Release date: 4/15/06
%{
Copyright (c) 2009, John D'Errico
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
%}
% I always need to know which elements are NaN,
% and what size the array is for any method
[n,m]=size(A);
A=A(:);
nm=n*m;
k=isnan(A(:));
% list the nodes which are known, and which will
% be interpolated
nan_list=find(k);
known_list=find(~k);
% how many nans overall
nan_count=length(nan_list);
% convert NaN indices to (r,c) form
% nan_list==find(k) are the unrolled (linear) indices
% (row,column) form
[nr,nc]=ind2sub([n,m],nan_list);
% both forms of index in one array:
% column 1 == unrolled index
% column 2 == row index
% column 3 == column index
nan_list=[nan_list,nr,nc];
% supply default method
if (nargin<2) || isempty(method)
method = 0;
elseif ~ismember(method,0:5)
error 'If supplied, method must be one of: {0,1,2,3,4,5}.'
end
% for different methods
switch method
case 0
% The same as method == 1, except only work on those
% elements which are NaN, or at least touch a NaN.
% horizontal and vertical neighbors only
talks_to = [-1 0;0 -1;1 0;0 1];
neighbors_list=identify_neighbors(n,m,nan_list,talks_to);
% list of all nodes we have identified
all_list=[nan_list;neighbors_list];
% generate sparse array with second partials on row
% variable for each element in either list, but only
% for those nodes which have a row index > 1 or < n
L = find((all_list(:,2) > 1) & (all_list(:,2) < n));
nl=length(L);
if nl>0
fda=sparse(repmat(all_list(L,1),1,3), ...
repmat(all_list(L,1),1,3)+repmat([-1 0 1],nl,1), ...
repmat([1 -2 1],nl,1),nm,nm);
else
fda=spalloc(n*m,n*m,size(all_list,1)*5);
end
% 2nd partials on column index
L = find((all_list(:,3) > 1) & (all_list(:,3) < m));
nl=length(L);
if nl>0
fda=fda+sparse(repmat(all_list(L,1),1,3), ...
repmat(all_list(L,1),1,3)+repmat([-n 0 n],nl,1), ...
repmat([1 -2 1],nl,1),nm,nm);
end
% eliminate knowns
rhs=-fda(:,known_list)*A(known_list);
k=find(any(fda(:,nan_list(:,1)),2));
% and solve...
B=A;
B(nan_list(:,1))=fda(k,nan_list(:,1))\rhs(k);
case 1
% least squares approach with del^2. Build system
% for every array element as an unknown, and then
% eliminate those which are knowns.
% Build sparse matrix approximating del^2 for
% every element in A.
% Compute finite difference for second partials
% on row variable first
[i,j]=ndgrid(2:(n-1),1:m);
ind=i(:)+(j(:)-1)*n;
np=(n-2)*m;
fda=sparse(repmat(ind,1,3),[ind-1,ind,ind+1], ...
repmat([1 -2 1],np,1),n*m,n*m);
% now second partials on column variable
[i,j]=ndgrid(1:n,2:(m-1));
ind=i(:)+(j(:)-1)*n;
np=n*(m-2);
fda=fda+sparse(repmat(ind,1,3),[ind-n,ind,ind+n], ...
repmat([1 -2 1],np,1),nm,nm);
% eliminate knowns
rhs=-fda(:,known_list)*A(known_list);
k=find(any(fda(:,nan_list),2));
% and solve...
B=A;
B(nan_list(:,1))=fda(k,nan_list(:,1))\rhs(k);
case 2
% Direct solve for del^2 BVP across holes
% generate sparse array with second partials on row
% variable for each nan element, only for those nodes
% which have a row index > 1 or < n
L = find((nan_list(:,2) > 1) & (nan_list(:,2) < n));
nl=length(L);
if nl>0
fda=sparse(repmat(nan_list(L,1),1,3), ...
repmat(nan_list(L,1),1,3)+repmat([-1 0 1],nl,1), ...
repmat([1 -2 1],nl,1),n*m,n*m);
else
fda=spalloc(n*m,n*m,size(nan_list,1)*5);
end
% 2nd partials on column index
L = find((nan_list(:,3) > 1) & (nan_list(:,3) < m));
nl=length(L);
if nl>0
fda=fda+sparse(repmat(nan_list(L,1),1,3), ...
repmat(nan_list(L,1),1,3)+repmat([-n 0 n],nl,1), ...
repmat([1 -2 1],nl,1),n*m,n*m);
end
% fix boundary conditions at extreme corners
% of the array in case there were nans there
if ismember(1,nan_list(:,1))
fda(1,[1 2 n+1])=[-2 1 1];
end
if ismember(n,nan_list(:,1))
fda(n,[n, n-1,n+n])=[-2 1 1];
end
if ismember(nm-n+1,nan_list(:,1))
fda(nm-n+1,[nm-n+1,nm-n+2,nm-n])=[-2 1 1];
end
if ismember(nm,nan_list(:,1))
fda(nm,[nm,nm-1,nm-n])=[-2 1 1];
end
% eliminate knowns
rhs=-fda(:,known_list)*A(known_list);
% and solve...
B=A;
k=nan_list(:,1);
B(k)=fda(k,k)\rhs(k);
case 3
% The same as method == 0, except uses del^4 as the
% interpolating operator.
% del^4 template of neighbors
talks_to = [-2 0;-1 -1;-1 0;-1 1;0 -2;0 -1; ...
0 1;0 2;1 -1;1 0;1 1;2 0];
neighbors_list=identify_neighbors(n,m,nan_list,talks_to);
% list of all nodes we have identified
all_list=[nan_list;neighbors_list];
% generate sparse array with del^4, but only
% for those nodes which have a row & column index
% >= 3 or <= n-2
L = find( (all_list(:,2) >= 3) & ...
(all_list(:,2) <= (n-2)) & ...
(all_list(:,3) >= 3) & ...
(all_list(:,3) <= (m-2)));
nl=length(L);
if nl>0
% do the entire template at once
fda=sparse(repmat(all_list(L,1),1,13), ...
repmat(all_list(L,1),1,13) + ...
repmat([-2*n,-n-1,-n,-n+1,-2,-1,0,1,2,n-1,n,n+1,2*n],nl,1), ...
repmat([1 2 -8 2 1 -8 20 -8 1 2 -8 2 1],nl,1),nm,nm);
else
fda=spalloc(n*m,n*m,size(all_list,1)*5);
end
% on the boundaries, reduce the order around the edges
L = find((((all_list(:,2) == 2) | ...
(all_list(:,2) == (n-1))) & ...
(all_list(:,3) >= 2) & ...
(all_list(:,3) <= (m-1))) | ...
(((all_list(:,3) == 2) | ...
(all_list(:,3) == (m-1))) & ...
(all_list(:,2) >= 2) & ...
(all_list(:,2) <= (n-1))));
nl=length(L);
if nl>0
fda=fda+sparse(repmat(all_list(L,1),1,5), ...
repmat(all_list(L,1),1,5) + ...
repmat([-n,-1,0,+1,n],nl,1), ...
repmat([1 1 -4 1 1],nl,1),nm,nm);
end
L = find( ((all_list(:,2) == 1) | ...
(all_list(:,2) == n)) & ...
(all_list(:,3) >= 2) & ...
(all_list(:,3) <= (m-1)));
nl=length(L);
if nl>0
fda=fda+sparse(repmat(all_list(L,1),1,3), ...
repmat(all_list(L,1),1,3) + ...
repmat([-n,0,n],nl,1), ...
repmat([1 -2 1],nl,1),nm,nm);
end
L = find( ((all_list(:,3) == 1) | ...
(all_list(:,3) == m)) & ...
(all_list(:,2) >= 2) & ...
(all_list(:,2) <= (n-1)));
nl=length(L);
if nl>0
fda=fda+sparse(repmat(all_list(L,1),1,3), ...
repmat(all_list(L,1),1,3) + ...
repmat([-1,0,1],nl,1), ...
repmat([1 -2 1],nl,1),nm,nm);
end
% eliminate knowns
rhs=-fda(:,known_list)*A(known_list);
k=find(any(fda(:,nan_list(:,1)),2));
% and solve...
B=A;
B(nan_list(:,1))=fda(k,nan_list(:,1))\rhs(k);
case 4
% Spring analogy
% interpolating operator.
% list of all springs between a node and a horizontal
% or vertical neighbor
hv_list=[-1 -1 0;1 1 0;-n 0 -1;n 0 1];
hv_springs=[];
for i=1:4
hvs=nan_list+repmat(hv_list(i,:),nan_count,1);
k=(hvs(:,2)>=1) & (hvs(:,2)<=n) & (hvs(:,3)>=1) & (hvs(:,3)<=m);
hv_springs=[hv_springs;[nan_list(k,1),hvs(k,1)]];
end
% delete replicate springs
hv_springs=unique(sort(hv_springs,2),'rows');
% build sparse matrix of connections, springs
% connecting diagonal neighbors are weaker than
% the horizontal and vertical springs
nhv=size(hv_springs,1);
springs=sparse(repmat((1:nhv)',1,2),hv_springs, ...
repmat([1 -1],nhv,1),nhv,nm);
% eliminate knowns
rhs=-springs(:,known_list)*A(known_list);
% and solve...
B=A;
B(nan_list(:,1))=springs(:,nan_list(:,1))\rhs;
case 5
% Average of 8 nearest neighbors
% generate sparse array to average 8 nearest neighbors
% for each nan element, be careful around edges
fda=spalloc(n*m,n*m,size(nan_list,1)*9);
% -1,-1
L = find((nan_list(:,2) > 1) & (nan_list(:,3) > 1));
nl=length(L);
if nl>0
fda=fda+sparse(repmat(nan_list(L,1),1,2), ...
repmat(nan_list(L,1),1,2)+repmat([-n-1, 0],nl,1), ...
repmat([1 -1],nl,1),n*m,n*m);
end
% 0,-1
L = find(nan_list(:,3) > 1);
nl=length(L);
if nl>0
fda=fda+sparse(repmat(nan_list(L,1),1,2), ...
repmat(nan_list(L,1),1,2)+repmat([-n, 0],nl,1), ...
repmat([1 -1],nl,1),n*m,n*m);
end
% +1,-1
L = find((nan_list(:,2) < n) & (nan_list(:,3) > 1));
nl=length(L);
if nl>0
fda=fda+sparse(repmat(nan_list(L,1),1,2), ...
repmat(nan_list(L,1),1,2)+repmat([-n+1, 0],nl,1), ...
repmat([1 -1],nl,1),n*m,n*m);
end
% -1,0
L = find(nan_list(:,2) > 1);
nl=length(L);
if nl>0
fda=fda+sparse(repmat(nan_list(L,1),1,2), ...
repmat(nan_list(L,1),1,2)+repmat([-1, 0],nl,1), ...
repmat([1 -1],nl,1),n*m,n*m);
end
% +1,0
L = find(nan_list(:,2) < n);
nl=length(L);
if nl>0
fda=fda+sparse(repmat(nan_list(L,1),1,2), ...
repmat(nan_list(L,1),1,2)+repmat([1, 0],nl,1), ...
repmat([1 -1],nl,1),n*m,n*m);
end
% -1,+1
L = find((nan_list(:,2) > 1) & (nan_list(:,3) < m));
nl=length(L);
if nl>0
fda=fda+sparse(repmat(nan_list(L,1),1,2), ...
repmat(nan_list(L,1),1,2)+repmat([n-1, 0],nl,1), ...
repmat([1 -1],nl,1),n*m,n*m);
end
% 0,+1
L = find(nan_list(:,3) < m);
nl=length(L);
if nl>0
fda=fda+sparse(repmat(nan_list(L,1),1,2), ...
repmat(nan_list(L,1),1,2)+repmat([n, 0],nl,1), ...
repmat([1 -1],nl,1),n*m,n*m);
end
% +1,+1
L = find((nan_list(:,2) < n) & (nan_list(:,3) < m));
nl=length(L);
if nl>0
fda=fda+sparse(repmat(nan_list(L,1),1,2), ...
repmat(nan_list(L,1),1,2)+repmat([n+1, 0],nl,1), ...
repmat([1 -1],nl,1),n*m,n*m);
end
% eliminate knowns
rhs=-fda(:,known_list)*A(known_list);
% and solve...
B=A;
k=nan_list(:,1);
B(k)=fda(k,k)\rhs(k);
end
% all done, make sure that B is the same shape as
% A was when we came in.
B=reshape(B,n,m);
% ====================================================
% end of main function
% ====================================================
% ====================================================
% begin subfunctions
% ====================================================
function neighbors_list=identify_neighbors(n,m,nan_list,talks_to)
% identify_neighbors: identifies all the neighbors of
% those nodes in nan_list, not including the nans
% themselves
%
% arguments (input):
% n,m - scalar - [n,m]=size(A), where A is the
% array to be interpolated
% nan_list - array - list of every nan element in A
% nan_list(i,1) == linear index of i'th nan element
% nan_list(i,2) == row index of i'th nan element
% nan_list(i,3) == column index of i'th nan element
% talks_to - px2 array - defines which nodes communicate
% with each other, i.e., which nodes are neighbors.
%
% talks_to(i,1) - defines the offset in the row
% dimension of a neighbor
% talks_to(i,2) - defines the offset in the column
% dimension of a neighbor
%
% For example, talks_to = [-1 0;0 -1;1 0;0 1]
% means that each node talks only to its immediate
% neighbors horizontally and vertically.
%
% arguments(output):
% neighbors_list - array - list of all neighbors of
% all the nodes in nan_list
if ~isempty(nan_list)
% use the definition of a neighbor in talks_to
nan_count=size(nan_list,1);
talk_count=size(talks_to,1);
nn=zeros(nan_count*talk_count,2);
j=[1,nan_count];
for i=1:talk_count
nn(j(1):j(2),:)=nan_list(:,2:3) + ...
repmat(talks_to(i,:),nan_count,1);
j=j+nan_count;
end
% drop those nodes which fall outside the bounds of the
% original array
L = (nn(:,1)<1)|(nn(:,1)>n)|(nn(:,2)<1)|(nn(:,2)>m);
nn(L,:)=[];
% form the same format 3 column array as nan_list
neighbors_list=[sub2ind([n,m],nn(:,1),nn(:,2)),nn];
% delete replicates in the neighbors list
neighbors_list=unique(neighbors_list,'rows');
% and delete those which are also in the list of NaNs.
neighbors_list=setdiff(neighbors_list,nan_list,'rows');
else
neighbors_list=[];
end
--------------------------------------------------------------------------------
/tiffread2.m:
--------------------------------------------------------------------------------
1 | function [stack, img_read] = tiffread(filename, img_first, img_last)
2 | % tiffread, version 2.5 December 21 2007
3 | %
4 | % [stack, nbImages] = tiffread;
5 | % [stack, nbImages] = tiffread(filename);
6 | % [stack, nbImages] = tiffread(filename, imageIndex);
7 | % [stack, nbImages] = tiffread(filename, firstImageIndex, lastImageIndex);
8 | %
9 | % Reads 8,16,32 bits uncompressed grayscale and (some) color tiff files,
10 | % as well as stacks or multiple tiff images, for example those produced
11 | % by metamorph or NIH-image. The entire TIFF standard is not supported,
12 | % but you may extend it by editing this file. If you do so, it would be
13 | % nice to return your modification to F. Nedelec, so that it can be
14 | % included in future releases
15 | %
16 | % The function can be called with a file name in the current directory,
17 | % or without argument, in which case it pop up a file openning dialog
18 | % to allow manual selection of the file.
19 | % If the stacks contains multiples images, loading can be restricted by
20 | % specifying the first and last images to read, or just one image to read.
21 | %
22 | % At return, nbimages contains the number of images read, and S is a vector
23 | % containing the different images with some additional informations. The
24 | % image pixels values are stored in the field .data for gray level images,
25 | % or in the fields .red, .green and .blue (in the order in which they are
26 | % stored in the file, which does not correspond necessarily to these colors)
27 | %
28 | % The pixels values are returned in the native (integer) format,
29 | % and must be converted to be used in most matlab functions.
30 | %
31 | % Example:
32 | % im = tiffread('spindle.stk');
33 | % imshow( double(im(5).data) );
34 | %
35 | % Francois Nedelec, EMBL, Copyright 1999-2007.
36 | % rewriten July 7th, 2004 at Woods Hole during the physiology course.
37 | % last modified December 21, 2007.
38 | % With contributions from:
39 | % Kendra Burbank for the waitbar
40 | % Hidenao Iwai for the code to read floating point images,
41 | % Stephen Lang to be more compliant with PlanarConfiguration
42 | % Jan-Ulrich Kreft for Zeiss LSM support
43 | % Elias Beauchanp and David Kolin for additional Metamorph support
44 | %
45 | % Please, help us improve this software: send us feedback/bugs/suggestions
46 | % This software is provided at no cost by a public research institution.
47 | %
48 | % Francois Nedelec
49 | % nedelec (at) embl.de
50 | % Cell Biology and Biophysics, EMBL; Meyerhofstrasse 1; 69117 Heidelberg; Germany
51 | % http://www.embl.org
52 | % http://www.cytosim.org
53 |
54 |
55 |
56 |
57 | %Optimization: join adjacent TIF strips: this results in faster reads
58 | consolidateStrips = 1;
59 |
60 | %if there is no argument, we ask the user to choose a file:
61 | if (nargin == 0)
62 | [filename, pathname] = uigetfile('*.tif;*.stk;*.lsm', 'select image file');
63 | filename = [ pathname, filename ];
64 | end
65 |
66 | if (nargin<=1); img_first = 1; img_last = 10000; end
67 | if (nargin==2); img_last = img_first; end
68 |
69 |
70 | % not all valid tiff tags have been included, as they are really a lot...
71 | % if needed, tags can easily be added to this code
72 | % See the official list of tags:
73 | % http://partners.adobe.com/asn/developer/pdfs/tn/TIFF6.pdf
74 | %
75 | % the structure IMG is returned to the user, while TIF is not.
76 | % so tags usefull to the user should be stored as fields in IMG, while
77 | % those used only internally can be stored in TIF.
78 |
79 | global TIF;
80 | TIF = [];
81 |
82 | %counters for the number of images read and skipped
83 | img_skip = 0;
84 | img_read = 0;
85 |
86 | % set defaults values :
87 | TIF.SampleFormat = 1;
88 | TIF.SamplesPerPixel = 1;
89 | TIF.BOS = 'ieee-le'; %byte order string
90 |
91 | if isempty(findstr(filename,'.'))
92 | filename = [filename,'.tif'];
93 | end
94 |
95 | TIF.file = fopen(filename,'r','l');
96 | if TIF.file == -1
97 | filename = strrep(filename, '.tif', '.stk');
98 | TIF.file = fopen(filename,'r','l');
99 | if TIF.file == -1
100 | error(['file <',filename,'> not found.']);
101 | end
102 | end
103 |
104 |
105 | % read header
106 | % read byte order: II = little endian, MM = big endian
107 | byte_order = fread(TIF.file, 2, '*char');
108 | if ( strcmp(byte_order', 'II') )
109 | TIF.BOS = 'ieee-le'; %normal PC format
110 | elseif ( strcmp(byte_order','MM') )
111 | TIF.BOS = 'ieee-be';
112 | else
113 | error('This is not a TIFF file (no MM or II).');
114 | end
115 |
116 |
117 | %----- read in a number which identifies file as TIFF format
118 | tiff_id = fread(TIF.file,1,'uint16', TIF.BOS);
119 | if (tiff_id ~= 42)
120 | error('This is not a TIFF file (missing 42).');
121 | end
122 |
123 | %----- read the byte offset for the first image file directory (IFD)
124 | TIF.img_pos = fread(TIF.file, 1, 'uint32', TIF.BOS);
125 |
126 | while (TIF.img_pos ~= 0)
127 |
128 | clear IMG;
129 | IMG.filename = fullfile( pwd, filename );
130 | % move in the file to the first IFD
131 | fseek(TIF.file, TIF.img_pos, -1);
132 | %disp(strcat('reading img at pos :',num2str(TIF.img_pos)));
133 |
134 | %read in the number of IFD entries
135 | num_entries = fread(TIF.file,1,'uint16', TIF.BOS);
136 | %disp(strcat('num_entries =', num2str(num_entries)));
137 |
138 | %read and process each IFD entry
139 | for i = 1:num_entries
140 |
141 | % save the current position in the file
142 | file_pos = ftell(TIF.file);
143 |
144 | % read entry tag
145 | TIF.entry_tag = fread(TIF.file, 1, 'uint16', TIF.BOS);
146 | entry = readIFDentry;
147 | %disp(strcat('reading entry <',num2str(TIF.entry_tag),'>'));
148 |
149 | switch TIF.entry_tag
150 | case 254
151 | TIF.NewSubfiletype = entry.val;
152 | case 256 % image width - number of column
153 | IMG.width = entry.val;
154 | case 257 % image height - number of row
155 | IMG.height = entry.val;
156 | TIF.ImageLength = entry.val;
157 | case 258 % BitsPerSample per sample
158 | TIF.BitsPerSample = entry.val;
159 | TIF.BytesPerSample = TIF.BitsPerSample / 8;
160 | IMG.bits = TIF.BitsPerSample(1);
161 | %fprintf(1,'BitsPerSample %i %i %i\n', entry.val);
162 | case 259 % compression
163 | if (entry.val ~= 1); error('Compression format not supported.'); end
164 | case 262 % photometric interpretation
165 | TIF.PhotometricInterpretation = entry.val;
166 | if ( TIF.PhotometricInterpretation == 3 )
167 | warning('Ignoring TIFF look-up table');
168 | end
169 | case 269
170 | IMG.document_name = entry.val;
171 | case 270 % comments:
172 | IMG.info = entry.val;
173 | case 271
174 | IMG.make = entry.val;
175 | case 273 % strip offset
176 | TIF.StripOffsets = entry.val;
177 | TIF.StripNumber = entry.cnt;
178 | %fprintf(1,'StripNumber = %i, size(StripOffsets) = %i %i\n', TIF.StripNumber, size(TIF.StripOffsets));
179 | case 277 % sample_per pixel
180 | TIF.SamplesPerPixel = entry.val;
181 | %fprintf(1,'Color image: sample_per_pixel=%i\n', TIF.SamplesPerPixel);
182 | case 278 % rows per strip
183 | TIF.RowsPerStrip = entry.val;
184 | case 279 % strip byte counts - number of bytes in each strip after any compressio
185 | TIF.StripByteCounts= entry.val;
186 | case 282 % X resolution
187 | IMG.x_resolution = entry.val;
188 | case 283 % Y resolution
189 | IMG.y_resolution = entry.val;
190 | case 284 %planar configuration describe the order of RGB
191 | TIF.PlanarConfiguration = entry.val;
192 | case 296 % resolution unit
193 | IMG.resolution_unit= entry.val;
194 | case 305 % software
195 | IMG.software = entry.val;
196 | case 306 % datetime
197 | IMG.datetime = entry.val;
198 | case 315
199 | IMG.artist = entry.val;
200 | case 317 %predictor for compression
201 | if (entry.val ~= 1); error('unsuported predictor value'); end
202 | case 320 % color map
203 | IMG.cmap = entry.val;
204 | IMG.colors = entry.cnt/3;
205 | case 339
206 | TIF.SampleFormat = entry.val;
207 | case 33628 %metamorph specific data
208 | IMG.MM_private1 = entry.val;
209 | case 33629 %this tag identify the image as a Metamorph stack!
210 | TIF.MM_stack = entry.val;
211 | TIF.MM_stackCnt = entry.cnt;
212 | if ( img_last > img_first )
213 | waitbar_handle = waitbar(0,'Please wait...','Name',['Reading ' filename]);
214 | end
215 | case 33630 %metamorph stack data: wavelength
216 | TIF.MM_wavelength = entry.val;
217 | case 33631 %metamorph stack data: gain/background?
218 | TIF.MM_private2 = entry.val;
219 | case 34412 % Zeiss LSM data
220 | IMG.lsm = entry.val;
221 | otherwise
222 | fprintf(1, 'Ignored TIFF entry with tag %i (cnt %i)\n', TIF.entry_tag, entry.cnt);
223 | end
224 | % move to next IFD entry in the file
225 | fseek(TIF.file, file_pos+12, -1);
226 | end
227 |
228 | %Planar configuration is not fully supported
229 | %Per tiff spec 6.0 PlanarConfiguration irrelevent if SamplesPerPixel==1
230 | %Contributed by Stephen Lang
231 | if ((TIF.SamplesPerPixel ~= 1) && (TIF.PlanarConfiguration == 1))
232 | error('PlanarConfiguration = %i not supported', TIF.PlanarConfiguration);
233 | end
234 |
235 | %total number of bytes per image:
236 | PlaneBytesCnt = IMG.width * IMG.height * TIF.BytesPerSample;
237 |
238 | if consolidateStrips
239 | %Try to consolidate the strips into a single one to speed-up reading:
240 | BytesCnt = TIF.StripByteCounts(1);
241 |
242 | if BytesCnt < PlaneBytesCnt
243 |
244 | ConsolidateCnt = 1;
245 | %Count how many Strip are needed to produce a plane
246 | while TIF.StripOffsets(1) + BytesCnt == TIF.StripOffsets(ConsolidateCnt+1)
247 | ConsolidateCnt = ConsolidateCnt + 1;
248 | BytesCnt = BytesCnt + TIF.StripByteCounts(ConsolidateCnt);
249 | if ( BytesCnt >= PlaneBytesCnt ); break; end
250 | end
251 |
252 | %Consolidate the Strips
253 | if ( BytesCnt <= PlaneBytesCnt(1) ) && ( ConsolidateCnt > 1 )
254 | %fprintf(1,'Consolidating %i stripes out of %i', ConsolidateCnt, TIF.StripNumber);
255 | TIF.StripByteCounts = [BytesCnt; TIF.StripByteCounts(ConsolidateCnt+1:TIF.StripNumber ) ];
256 | TIF.StripOffsets = TIF.StripOffsets( [1 , ConsolidateCnt+1:TIF.StripNumber] );
257 | TIF.StripNumber = 1 + TIF.StripNumber - ConsolidateCnt;
258 | end
259 | end
260 | end
261 |
262 | %read the next IFD address:
263 | TIF.img_pos = fread(TIF.file, 1, 'uint32', TIF.BOS);
264 | %if (TIF.img_pos) disp(['next ifd at', num2str(TIF.img_pos)]); end
265 |
266 | if isfield( TIF, 'MM_stack' )
267 |
268 | if ( img_last > TIF.MM_stackCnt )
269 | img_last = TIF.MM_stackCnt;
270 | end
271 |
272 | %this loop is to read metamorph stacks:
273 | for ii = img_first:img_last
274 |
275 | TIF.StripCnt = 1;
276 |
277 | %read the image
278 | fileOffset = PlaneBytesCnt * ( ii - 1 );
279 | %fileOffset = 0;
280 | %fileOffset = ftell(TIF.file) - TIF.StripOffsets(1);
281 |
282 | if ( TIF.SamplesPerPixel == 1 )
283 | IMG.data = read_plane(fileOffset, IMG.width, IMG.height, 1);
284 | else
285 | IMG.red = read_plane(fileOffset, IMG.width, IMG.height, 1);
286 | IMG.green = read_plane(fileOffset, IMG.width, IMG.height, 2);
287 | IMG.blue = read_plane(fileOffset, IMG.width, IMG.height, 3);
288 | end
289 |
290 | % print a text timer on the main window, or update the waitbar
291 | % fprintf(1,'img_read %i img_skip %i\n', img_read, img_skip);
292 | if exist('waitbar_handle', 'var')
293 | waitbar( img_read/TIF.MM_stackCnt, waitbar_handle);
294 | end
295 |
296 | [ IMG.MM_stack, IMG.MM_wavelength, IMG.MM_private2 ] = splitMetamorph(ii);
297 |
298 | img_read = img_read + 1;
299 | stack( img_read ) = IMG;
300 |
301 | end
302 | break;
303 |
304 | else
305 |
306 | %this part to read a normal TIFF stack:
307 |
308 | if ( img_skip + 1 >= img_first )
309 |
310 | TIF.StripCnt = 1;
311 | %read the image
312 | if ( TIF.SamplesPerPixel == 1 )
313 | IMG.data = read_plane(0, IMG.width, IMG.height, 1);
314 | else
315 | IMG.red = read_plane(0, IMG.width, IMG.height, 1);
316 | IMG.green = read_plane(0, IMG.width, IMG.height, 2);
317 | IMG.blue = read_plane(0, IMG.width, IMG.height, 3);
318 | end
319 |
320 | img_read = img_read + 1;
321 |
322 | try
323 | stack( img_read ) = IMG;
324 | catch
325 | fprintf(1, 'Aborted read after finding dissimilar image');
326 | break;
327 | end
328 | else
329 | img_skip = img_skip + 1;
330 | end
331 |
332 | if ( img_skip + img_read >= img_last )
333 | break;
334 | end
335 | end
336 | end
337 |
338 |
339 | if isfield( TIF, 'MM_stack' ) && ~isempty(IMG.info)
340 | MM = parseMetamorphInfo(IMG.info, TIF.MM_stackCnt);
341 | for i = 1: size(stack,2)
342 | [ stack(1,i).MM ] = MM(i);
343 | end
344 | end
345 |
346 |
347 | %clean-up
348 | fclose(TIF.file);
349 | if exist('waitbar_handle', 'var')
350 | delete( waitbar_handle );
351 | clear waitbar_handle;
352 | end
353 | drawnow;
354 | %return empty array if nothing was read
355 | if ~ exist( 'stack', 'var')
356 | stack = [];
357 | end
358 | return;
359 |
360 |
361 | %============================================================================
362 |
363 | function plane = read_plane(offset, width, height, planeCnt)
364 |
365 | global TIF;
366 |
367 | %return an empty array if the sample format has zero bits
368 | if ( TIF.BitsPerSample(planeCnt) == 0 )
369 | plane=[];
370 | return;
371 | end
372 |
373 | %fprintf(1,'reading plane %i size %i %i\n', planeCnt, width, height);
374 |
375 | %determine the type needed to store the pixel values:
376 | switch( TIF.SampleFormat )
377 | case 1
378 | classname = sprintf('uint%i', TIF.BitsPerSample(planeCnt));
379 | case 2
380 | classname = sprintf('int%i', TIF.BitsPerSample(planeCnt));
381 | case 3
382 | if ( TIF.BitsPerSample(planeCnt) == 32 )
383 | classname = 'single';
384 | else
385 | classname = 'double';
386 | end
387 | otherwise
388 | error('unsuported TIFF sample format %i', TIF.SampleFormat);
389 | end
390 |
391 | % Preallocate a matrix to hold the sample data:
392 | plane = zeros(width, height, classname);
393 |
394 | % Read the strips and concatenate them:
395 | line = 1;
396 | while ( TIF.StripCnt <= TIF.StripNumber )
397 |
398 | strip = read_strip(offset, width, planeCnt, TIF.StripCnt, classname);
399 | TIF.StripCnt = TIF.StripCnt + 1;
400 |
401 | % copy the strip onto the data
402 | plane(:, line:(line+size(strip,2)-1)) = strip;
403 |
404 | line = line + size(strip,2);
405 | if ( line > height )
406 | break;
407 | end
408 |
409 | end
410 |
411 | % Extract valid part of data if needed
412 | if ~all(size(plane) == [width height]),
413 | plane = plane(1:width, 1:height);
414 | warning('Cropping data: found more bytes than needed...');
415 | end
416 |
417 | % transpose the image (otherwise display is rotated in matlab)
418 | plane = plane';
419 |
420 | return;
421 |
422 |
423 | %=================== sub-functions to read a strip ===================
424 |
425 | function strip = read_strip(offset, width, planeCnt, stripCnt, classname)
426 |
427 | global TIF;
428 |
429 | %fprintf(1,'reading strip at position %i\n',TIF.StripOffsets(stripCnt) + offset);
430 | StripLength = TIF.StripByteCounts(stripCnt) ./ TIF.BytesPerSample(planeCnt);
431 |
432 | %fprintf(1, 'reading strip %i\n', stripCnt);
433 | fseek(TIF.file, TIF.StripOffsets(stripCnt) + offset, 'bof');
434 | bytes = fread( TIF.file, StripLength, classname, TIF.BOS );
435 |
436 | if any( length(bytes) ~= StripLength )
437 | error('End of file reached unexpectedly.');
438 | end
439 |
440 | strip = reshape(bytes, width, StripLength / width);
441 |
442 | return;
443 |
444 |
445 | %===================sub-functions that reads an IFD entry:===================
446 |
447 |
448 | function [nbBytes, matlabType] = convertType(tiffType)
449 | switch (tiffType)
450 | case 1
451 | nbBytes=1;
452 | matlabType='uint8';
453 | case 2
454 | nbBytes=1;
455 | matlabType='uchar';
456 | case 3
457 | nbBytes=2;
458 | matlabType='uint16';
459 | case 4
460 | nbBytes=4;
461 | matlabType='uint32';
462 | case 5
463 | nbBytes=8;
464 | matlabType='uint32';
465 | case 11
466 | nbBytes=4;
467 | matlabType='float32';
468 | case 12
469 | nbBytes=8;
470 | matlabType='float64';
471 | otherwise
472 | error('tiff type %i not supported', tiffType)
473 | end
474 | return;
475 |
476 | %===================sub-functions that reads an IFD entry:===================
477 |
478 | function entry = readIFDentry()
479 |
480 | global TIF;
481 | entry.tiffType = fread(TIF.file, 1, 'uint16', TIF.BOS);
482 | entry.cnt = fread(TIF.file, 1, 'uint32', TIF.BOS);
483 | %disp(['tiffType =', num2str(entry.tiffType),', cnt = ',num2str(entry.cnt)]);
484 |
485 | [ entry.nbBytes, entry.matlabType ] = convertType(entry.tiffType);
486 |
487 | if entry.nbBytes * entry.cnt > 4
488 | %next field contains an offset:
489 | offset = fread(TIF.file, 1, 'uint32', TIF.BOS);
490 | %disp(strcat('offset = ', num2str(offset)));
491 | fseek(TIF.file, offset, -1);
492 | end
493 |
494 | if TIF.entry_tag == 33629 % metamorph 'rationals'
495 | entry.val = fread(TIF.file, 6*entry.cnt, entry.matlabType, TIF.BOS);
496 | elseif TIF.entry_tag == 34412
497 | entry.val = readLSMinfo;
498 | else
499 | if entry.tiffType == 5
500 | entry.val = fread(TIF.file, 2*entry.cnt, entry.matlabType, TIF.BOS);
501 | else
502 | entry.val = fread(TIF.file, entry.cnt, entry.matlabType, TIF.BOS);
503 | end
504 | end
505 |
506 | if ( entry.tiffType == 2 );
507 | entry.val = char(entry.val');
508 | end
509 |
510 | return;
511 |
512 |
513 | %==============distribute the metamorph infos to each frame:
514 | function [MMstack, MMwavelength, MMprivate2] = splitMetamorph(imgCnt)
515 |
516 | global TIF;
517 |
518 | MMstack = [];
519 | MMwavelength = [];
520 | MMprivate2 = [];
521 |
522 | if TIF.MM_stackCnt == 1
523 | return;
524 | end
525 |
526 | left = imgCnt - 1;
527 |
528 | if isfield( TIF, 'MM_stack' )
529 | S = length(TIF.MM_stack) / TIF.MM_stackCnt;
530 | MMstack = TIF.MM_stack(S*left+1:S*left+S);
531 | end
532 |
533 | if isfield( TIF, 'MM_wavelength' )
534 | S = length(TIF.MM_wavelength) / TIF.MM_stackCnt;
535 | MMwavelength = TIF.MM_wavelength(S*left+1:S*left+S);
536 | end
537 |
538 | if isfield( TIF, 'MM_private2' )
539 | S = length(TIF.MM_private2) / TIF.MM_stackCnt;
540 | MMprivate2 = TIF.MM_private2(S*left+1:S*left+S);
541 | end
542 |
543 | return;
544 |
545 |
546 | %%%% Parse the Metamorph camera info tag into respective fields
547 | % EVBR 2/7/2005, FJN Dec. 2007
548 | function mm = parseMetamorphInfo(info, cnt)
549 |
550 | info = regexprep(info, '\r\n|\o0', '\n');
551 | parse = textscan(info, '%s %s', 'Delimiter', ':');
552 | tokens = parse{1};
553 | values = parse{2};
554 |
555 | k = 0;
556 | mm = struct('Exposure', zeros(cnt,1));
557 | for i=1:size(tokens,1)
558 | tok = char(tokens(i,1));
559 | val = char(values(i,1));
560 | %fprintf(1, '"%s" : "%s"\n', tok, val);
561 | if strcmp(tok, 'Exposure')
562 | k = k + 1;
563 | [v, c, e, pos] = sscanf(val, '%i');
564 | unit = val(pos:length(val));
565 | %return the exposure in milli-seconds
566 | switch( unit )
567 | case 'ms'
568 | mm(k).Exposure = v;
569 | case 's'
570 | mm(k).Exposure = v * 1000;
571 | otherwise
572 | warning(['Exposure unit "',unit,'" not recognized']);
573 | mm(k).Exposure = v;
574 | end
575 | else
576 | switch tok
577 | case 'Binning'
578 | % Binning: 1 x 1 -> [1 1]
579 | mm(k).Binning = sscanf(val, '%d x %d')';
580 | case 'Region'
581 | mm(k).Region = sscanf(val, '%d x %d, offset at (%d, %d)')';
582 | otherwise
583 | field = regexprep(tok, ' ', '');
584 | if strcmp(val, 'Off')
585 | eval(['mm(k).',field,'=0;']);
586 | elseif strcmp(val, 'On')
587 | eval(['mm(k).',field,'=1;']);
588 | elseif isstrprop(val,'digit')
589 | eval(['mm(k).',field,'=str2num(val)'';']);
590 | else
591 | eval(['mm(k).',field,'=val;']);
592 | end
593 | end
594 | end
595 | end
596 |
597 | return
598 |
599 | %==============parse LSM info:
600 |
601 | function R = readLSMinfo()
602 |
603 | % only the first table is read!
604 | % this provide only very partial information, since the offset indicate that
605 | % additional data is stored in the file
606 | global TIF;
607 |
608 | R.MagicNumber = sprintf('0x%x',fread(TIF.file, 1, 'uint32', TIF.BOS));
609 | StructureSize = fread(TIF.file, 1, 'int32', TIF.BOS);
610 | R.DimensionX = fread(TIF.file, 1, 'int32', TIF.BOS);
611 | R.DimensionY = fread(TIF.file, 1, 'int32', TIF.BOS);
612 | R.DimensionZ = fread(TIF.file, 1, 'int32', TIF.BOS);
613 | R.DimensionChannels = fread(TIF.file, 1, 'int32', TIF.BOS);
614 | R.DimensionTime = fread(TIF.file, 1, 'int32', TIF.BOS);
615 | R.DataType = fread(TIF.file, 1, 'int32', TIF.BOS);
616 | R.ThumbnailX = fread(TIF.file, 1, 'int32', TIF.BOS);
617 | R.ThumbnailY = fread(TIF.file, 1, 'int32', TIF.BOS);
618 | R.VoxelSizeX = fread(TIF.file, 1, 'float64', TIF.BOS);
619 | R.VoxelSizeY = fread(TIF.file, 1, 'float64', TIF.BOS);
620 | R.VoxelSizeZ = fread(TIF.file, 1, 'float64', TIF.BOS);
621 | R.ScanType = fread(TIF.file, 1, 'uint32', TIF.BOS);
622 | R.DataType = fread(TIF.file, 1, 'uint32', TIF.BOS);
623 | R.OffsetVectorOverlay = fread(TIF.file, 1, 'uint32', TIF.BOS);
624 | R.OffsetInputLut = fread(TIF.file, 1, 'uint32', TIF.BOS);
625 | R.OffsetOutputLut = fread(TIF.file, 1, 'uint32', TIF.BOS);
626 | R.OffsetChannelColors = fread(TIF.file, 1, 'uint32', TIF.BOS);
627 | R.TimeInterval = fread(TIF.file, 1, 'float64', TIF.BOS);
628 | R.OffsetChannelDataTypes = fread(TIF.file, 1, 'uint32', TIF.BOS);
629 | R.OffsetScanInformation = fread(TIF.file, 1, 'uint32', TIF.BOS);
630 | R.OffsetKsData = fread(TIF.file, 1, 'uint32', TIF.BOS);
631 | R.OffsetTimeStamps = fread(TIF.file, 1, 'uint32', TIF.BOS);
632 | R.OffsetEventList = fread(TIF.file, 1, 'uint32', TIF.BOS);
633 | R.OffsetRoi = fread(TIF.file, 1, 'uint32', TIF.BOS);
634 | R.OffsetBleachRoi = fread(TIF.file, 1, 'uint32', TIF.BOS);
635 | R.OffsetNextRecording = fread(TIF.file, 1, 'uint32', TIF.BOS);
636 | R.Reserved = fread(TIF.file, 1, 'uint32', TIF.BOS);
637 |
638 | return;
639 |
640 |
641 |
--------------------------------------------------------------------------------
/openpivgui.m:
--------------------------------------------------------------------------------
1 | function varargout = openpivgui(varargin)
2 | % OPENPIVGUI M-file for openpivgui.fig
3 | % OPENPIVGUI, by itself, creates a new OPENPIVGUI or raises the existing
4 | % singleton*.
5 | %re
6 | % H = OPENPIVGUI returns the handle to a new OPENPIVGUI or the handle to
7 | % the existing singleton*.
8 | %
9 | % OPENPIVGUI('CALLBACK',hObject,eventData,handles,...) calls the local
10 | % function named CALLBACK in OPENPIVGUI.M with the given input arguments.
11 | %
12 | % OPENPIVGUI('Property','Value',...) creates a new OPENPIVGUI or raises the
13 | % existing singleton*. Starting from the left, property value pairs are
14 | % applied to the GUI before openpivgui_OpeningFcn gets called. An
15 | % unrecognized property name or invalid value makes property application
16 | % stop. All inputs are passed to openpivgui_OpeningFcn via varargin.
17 | %
18 | % *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one
19 | % instance to run (singleton)".
20 | %
21 | % See also: GUIDE, GUIDATA, GUIHANDLES
22 |
23 | % Edit the above text to modify the response to help openpivgui
24 |
25 | % Last Modified by GUIDE v2.5 29-May-2015 14:08:25
26 |
27 | % Begin initialization code - DO NOT EDIT
28 | gui_Singleton = 1;
29 | gui_State = struct('gui_Name', mfilename, ...
30 | 'gui_Singleton', gui_Singleton, ...
31 | 'gui_OpeningFcn', @openpivgui_OpeningFcn, ...
32 | 'gui_OutputFcn', @openpivgui_OutputFcn, ...
33 | 'gui_LayoutFcn', [] , ...
34 | 'gui_Callback', []);
35 | if nargin && ischar(varargin{1})
36 | gui_State.gui_Callback = str2func(varargin{1});
37 | end
38 |
39 | if nargout
40 | [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
41 | else
42 | gui_mainfcn(gui_State, varargin{:});
43 | end
44 | % End initialization code - DO NOT EDIT
45 |
46 |
47 | % --- Executes just before openpivgui is made visible.
48 | function openpivgui_OpeningFcn(hObject, eventdata, handles, varargin)
49 | % This function has no output args, see OutputFcn.
50 | % hObject handle to figure
51 | % eventdata reserved - to be defined in a future version of MATLAB
52 | % handles structure with handles and user data (see GUIDATA)
53 | % varargin command line arguments to openpivgui (see VARARGIN)
54 |
55 | % Choose default command line output for openpivgui
56 | handles.output = hObject;
57 | movegui(hObject,'center');
58 | set(hObject,'Toolbar','None');
59 | % Update handles structure
60 | guidata(hObject, handles);
61 |
62 | % This sets up the initial plot - only do when we are invisible
63 | % so window can get raised using openpiv_gui.
64 | if strcmp(get(hObject,'Visible'),'off')
65 | im = load('openpiv_logo.mat');
66 | imshow(im.im,'Parent',findobj(hObject,'type','axes')); %handles.axes_main);
67 | % text(0.05,.1,'Matlab version of OpenPIV (originally URAPIV)','FontName','Times','Fontsize',20);
68 | % text(0.05,.05,'http://www.openpiv.net','FontName','Verdana','Fontsize',16,'Color','blue');
69 | end
70 | axis off
71 |
72 | % UIWAIT makes openpiv_gui wait for user response (see UIRESUME)
73 | % uiwait(handles.figure1);
74 |
75 |
76 | % --- Outputs from this function are returned to the command line.
77 | function varargout = openpivgui_OutputFcn(hObject, eventdata, handles)
78 | % varargout cell array for returning output args (see VARARGOUT);
79 | % hObject handle to figure
80 | % eventdata reserved - to be defined in a future version of MATLAB
81 | % handles structure with handles and user data (see GUIDATA)
82 |
83 | % Get default command line output from handles structure
84 | varargout{1} = handles.output;
85 |
86 |
87 | % --- Executes on button press in pushbutton1.
88 | function pushbutton1_Callback(hObject, eventdata, handles)
89 | % hObject handle to pushbutton1 (see GCBO)
90 | % eventdata reserved - to be defined in a future version of MATLAB
91 | % handles structure with handles and user data (see GUIDATA)
92 |
93 |
94 | % --- Executes on selection change in popupmenu1.
95 | function popupmenu1_Callback(hObject, eventdata, handles)
96 | % hObject handle to popupmenu1 (see GCBO)
97 | % eventdata reserved - to be defined in a future version of MATLAB
98 | % handles structure with handles and user data (see GUIDATA)
99 |
100 | % Hints: contents = cellstr(get(hObject,'String')) returns popupmenu1 contents as cell array
101 | % contents{get(hObject,'Value')} returns selected item from popupmenu1
102 |
103 |
104 | % --- Executes during object creation, after setting all properties.
105 | function popupmenu1_CreateFcn(hObject, eventdata, handles)
106 | % hObject handle to popupmenu1 (see GCBO)
107 | % eventdata reserved - to be defined in a future version of MATLAB
108 | % handles empty - handles not created until after all CreateFcns called
109 |
110 | % Hint: popupmenu controls usually have a white background on Windows.
111 | % See ISPC and COMPUTER.
112 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
113 | set(hObject,'BackgroundColor','white');
114 | end
115 |
116 |
117 | % --- Executes on selection change in popupmenu2.
118 | function popupmenu2_Callback(hObject, eventdata, handles)
119 | % hObject handle to popupmenu2 (see GCBO)
120 | % eventdata reserved - to be defined in a future version of MATLAB
121 | % handles structure with handles and user data (see GUIDATA)
122 |
123 | % Hints: contents = cellstr(get(hObject,'String')) returns popupmenu2 contents as cell array
124 | % contents{get(hObject,'Value')} returns selected item from popupmenu2
125 |
126 |
127 | % --- Executes during object creation, after setting all properties.
128 | function popupmenu2_CreateFcn(hObject, eventdata, handles)
129 | % hObject handle to popupmenu2 (see GCBO)
130 | % eventdata reserved - to be defined in a future version of MATLAB
131 | % handles empty - handles not created until after all CreateFcns called
132 |
133 | % Hint: popupmenu controls usually have a white background on Windows.
134 | % See ISPC and COMPUTER.
135 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
136 | set(hObject,'BackgroundColor','white');
137 | end
138 |
139 |
140 | % --- Executes on selection change in popupmenu3.
141 | function popupmenu3_Callback(hObject, eventdata, handles)
142 | % hObject handle to popupmenu3 (see GCBO)
143 | % eventdata reserved - to be defined in a future version of MATLAB
144 | % handles structure with handles and user data (see GUIDATA)
145 |
146 | % Hints: contents = cellstr(get(hObject,'String')) returns popupmenu3 contents as cell array
147 | % contents{get(hObject,'Value')} returns selected item from popupmenu3
148 |
149 |
150 | % --- Executes during object creation, after setting all properties.
151 | function popupmenu3_CreateFcn(hObject, eventdata, handles)
152 | % hObject handle to popupmenu3 (see GCBO)
153 | % eventdata reserved - to be defined in a future version of MATLAB
154 | % handles empty - handles not created until after all CreateFcns called
155 |
156 | % Hint: popupmenu controls usually have a white background on Windows.
157 | % See ISPC and COMPUTER.
158 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
159 | set(hObject,'BackgroundColor','white');
160 | end
161 |
162 |
163 |
164 | function edit1_Callback(hObject, eventdata, handles)
165 | % hObject handle to edit1 (see GCBO)
166 | % eventdata reserved - to be defined in a future version of MATLAB
167 | % handles structure with handles and user data (see GUIDATA)
168 |
169 | % Hints: get(hObject,'String') returns contents of edit1 as text
170 | % str2double(get(hObject,'String')) returns contents of edit1 as a double
171 |
172 |
173 | % --- Executes during object creation, after setting all properties.
174 | function edit1_CreateFcn(hObject, eventdata, handles)
175 | % hObject handle to edit1 (see GCBO)
176 | % eventdata reserved - to be defined in a future version of MATLAB
177 | % handles empty - handles not created until after all CreateFcns called
178 |
179 | % Hint: edit controls usually have a white background on Windows.
180 | % See ISPC and COMPUTER.
181 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
182 | set(hObject,'BackgroundColor','white');
183 | end
184 |
185 |
186 |
187 | function edit2_Callback(hObject, eventdata, handles)
188 | % hObject handle to edit2 (see GCBO)
189 | % eventdata reserved - to be defined in a future version of MATLAB
190 | % handles structure with handles and user data (see GUIDATA)
191 |
192 | % Hints: get(hObject,'String') returns contents of edit2 as text
193 | % str2double(get(hObject,'String')) returns contents of edit2 as a double
194 |
195 |
196 | % --- Executes during object creation, after setting all properties.
197 | function edit2_CreateFcn(hObject, eventdata, handles)
198 | % hObject handle to edit2 (see GCBO)
199 | % eventdata reserved - to be defined in a future version of MATLAB
200 | % handles empty - handles not created until after all CreateFcns called
201 |
202 | % Hint: edit controls usually have a white background on Windows.
203 | % See ISPC and COMPUTER.
204 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
205 | set(hObject,'BackgroundColor','white');
206 | end
207 |
208 |
209 |
210 | function edit3_Callback(hObject, eventdata, handles)
211 | % hObject handle to edit3 (see GCBO)
212 | % eventdata reserved - to be defined in a future version of MATLAB
213 | % handles structure with handles and user data (see GUIDATA)
214 |
215 | % Hints: get(hObject,'String') returns contents of edit3 as text
216 | % str2double(get(hObject,'String')) returns contents of edit3 as a double
217 |
218 |
219 | % --- Executes during object creation, after setting all properties.
220 | function edit3_CreateFcn(hObject, eventdata, handles)
221 | % hObject handle to edit3 (see GCBO)
222 | % eventdata reserved - to be defined in a future version of MATLAB
223 | % handles empty - handles not created until after all CreateFcns called
224 |
225 | % Hint: edit controls usually have a white background on Windows.
226 | % See ISPC and COMPUTER.
227 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
228 | set(hObject,'BackgroundColor','white');
229 | end
230 |
231 |
232 | % --- Executes on button press in pushbutton2.
233 | function pushbutton2_Callback(hObject, eventdata, handles)
234 | % hObject handle to pushbutton2 (see GCBO)
235 | % eventdata reserved - to be defined in a future version of MATLAB
236 | % handles structure with handles and user data (see GUIDATA)
237 |
238 |
239 |
240 | function edit4_Callback(hObject, eventdata, handles)
241 | % hObject handle to edit4 (see GCBO)
242 | % eventdata reserved - to be defined in a future version of MATLAB
243 | % handles structure with handles and user data (see GUIDATA)
244 |
245 | % Hints: get(hObject,'String') returns contents of edit4 as text
246 | % str2double(get(hObject,'String')) returns contents of edit4 as a double
247 |
248 |
249 | % --- Executes during object creation, after setting all properties.
250 | function edit4_CreateFcn(hObject, eventdata, handles)
251 | % hObject handle to edit4 (see GCBO)
252 | % eventdata reserved - to be defined in a future version of MATLAB
253 | % handles empty - handles not created until after all CreateFcns called
254 |
255 | % Hint: edit controls usually have a white background on Windows.
256 | % See ISPC and COMPUTER.
257 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
258 | set(hObject,'BackgroundColor','white');
259 | end
260 |
261 |
262 |
263 | function edit5_Callback(hObject, eventdata, handles)
264 | % hObject handle to edit5 (see GCBO)
265 | % eventdata reserved - to be defined in a future version of MATLAB
266 | % handles structure with handles and user data (see GUIDATA)
267 |
268 | % Hints: get(hObject,'String') returns contents of edit5 as text
269 | % str2double(get(hObject,'String')) returns contents of edit5 as a double
270 |
271 |
272 | % --- Executes during object creation, after setting all properties.
273 | function edit5_CreateFcn(hObject, eventdata, handles)
274 | % hObject handle to edit5 (see GCBO)
275 | % eventdata reserved - to be defined in a future version of MATLAB
276 | % handles empty - handles not created until after all CreateFcns called
277 |
278 | % Hint: edit controls usually have a white background on Windows.
279 | % See ISPC and COMPUTER.
280 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
281 | set(hObject,'BackgroundColor','white');
282 | end
283 |
284 |
285 | % --- Executes on button press in pushbutton3.
286 | function pushbutton3_Callback(hObject, eventdata, handles)
287 | % hObject handle to pushbutton3 (see GCBO)
288 | % eventdata reserved - to be defined in a future version of MATLAB
289 | % handles structure with handles and user data (see GUIDATA)
290 |
291 |
292 | % --- Executes on button press in pushbutton4.
293 | function pushbutton4_Callback(hObject, eventdata, handles)
294 | % hObject handle to pushbutton4 (see GCBO)
295 | % eventdata reserved - to be defined in a future version of MATLAB
296 | % handles structure with handles and user data (see GUIDATA)
297 |
298 |
299 | % --- Executes on button press in pushbutton5.
300 | function pushbutton5_Callback(hObject, eventdata, handles)
301 | % hObject handle to pushbutton5 (see GCBO)
302 | % eventdata reserved - to be defined in a future version of MATLAB
303 | % handles structure with handles and user data (see GUIDATA)
304 |
305 |
306 | % --- Executes on button press in pushbutton6.
307 | function pushbutton6_Callback(hObject, eventdata, handles)
308 | % hObject handle to pushbutton6 (see GCBO)
309 | % eventdata reserved - to be defined in a future version of MATLAB
310 | % handles structure with handles and user data (see GUIDATA)
311 |
312 |
313 | % --- Executes on selection change in popupmenu4.
314 | function popupmenu4_Callback(hObject, eventdata, handles)
315 | % hObject handle to popupmenu4 (see GCBO)
316 | % eventdata reserved - to be defined in a future version of MATLAB
317 | % handles structure with handles and user data (see GUIDATA)
318 |
319 | % Hints: contents = cellstr(get(hObject,'String')) returns popupmenu4 contents as cell array
320 | % contents{get(hObject,'Value')} returns selected item from popupmenu4
321 |
322 |
323 | % --- Executes during object creation, after setting all properties.
324 | function popupmenu4_CreateFcn(hObject, eventdata, handles)
325 | % hObject handle to popupmenu4 (see GCBO)
326 | % eventdata reserved - to be defined in a future version of MATLAB
327 | % handles empty - handles not created until after all CreateFcns called
328 |
329 | % Hint: popupmenu controls usually have a white background on Windows.
330 | % See ISPC and COMPUTER.
331 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
332 | set(hObject,'BackgroundColor','white');
333 | end
334 |
335 |
336 | % --- Executes on selection change in popupmenu5.
337 | function popupmenu5_Callback(hObject, eventdata, handles)
338 | % hObject handle to popupmenu5 (see GCBO)
339 | % eventdata reserved - to be defined in a future version of MATLAB
340 | % handles structure with handles and user data (see GUIDATA)
341 |
342 | % Hints: contents = cellstr(get(hObject,'String')) returns popupmenu5 contents as cell array
343 | % contents{get(hObject,'Value')} returns selected item from popupmenu5
344 |
345 |
346 | % --- Executes during object creation, after setting all properties.
347 | function popupmenu5_CreateFcn(hObject, eventdata, handles)
348 | % hObject handle to popupmenu5 (see GCBO)
349 | % eventdata reserved - to be defined in a future version of MATLAB
350 | % handles empty - handles not created until after all CreateFcns called
351 |
352 | % Hint: popupmenu controls usually have a white background on Windows.
353 | % See ISPC and COMPUTER.
354 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
355 | set(hObject,'BackgroundColor','white');
356 | end
357 |
358 |
359 | % --- Executes on button press in checkbox1.
360 | function checkbox1_Callback(hObject, eventdata, handles)
361 | % hObject handle to checkbox1 (see GCBO)
362 | % eventdata reserved - to be defined in a future version of MATLAB
363 | % handles structure with handles and user data (see GUIDATA)
364 |
365 | % Hint: get(hObject,'Value') returns toggle state of checkbox1
366 |
367 |
368 | % --- Executes on button press in pushbutton7.
369 | function pushbutton7_Callback(hObject, eventdata, handles)
370 | % hObject handle to pushbutton7 (see GCBO)
371 | % eventdata reserved - to be defined in a future version of MATLAB
372 | % handles structure with handles and user data (see GUIDATA)
373 |
374 |
375 | % --------------------------------------------------------------------
376 | function load_Callback(hObject, eventdata, handles)
377 | % hObject handle to load (see GCBO)
378 | % eventdata reserved - to be defined in a future version of MATLAB
379 | % handles structure with handles and user data (see GUIDATA)
380 | [handles.files,handles.path] = readImDir;
381 | % set(handles.edit_dir,'String',handles.path);
382 | axes(handles.axes1);
383 | set(handles.axes1,'visible','off');
384 | set(handles.axes1,'Units','pixels');
385 |
386 | % preprocess = get(handles.checkbox_preprocess,'Value');
387 | % if preprocess
388 | % prepfun = str2func(handles.preprocess);
389 | % else
390 | % prepfun = inline('imadjust(x)');
391 | % end
392 | %
393 | % try
394 | % % imshow(fullfile(handles.path,handles.files{1}));
395 | % tmp = imread(fullfile(handles.path,handles.files{1}));
396 | % if length(size(tmp)) == 3
397 | % tmp = rgb2gray(tmp);
398 | % end
399 | % imshow(prepfun(tmp));
400 | % catch
401 | % tmp = tiffread2(fullfile(handles.path,handles.files{1}));
402 | % tmp = im2double(tmp.data);
403 | % imshow(prepfun(tmp));
404 | % end
405 |
406 | filename = fullfile(handles.path,handles.files{1});
407 | im = openpiv_imread(filename);
408 | imshow(im);
409 | set(handles.prev_image,'Visible','On');
410 | set(handles.next_image,'Visible','On');
411 | handles = ReadImageDirectory(handles);
412 | % set(handles.edit_num,'string',sprintf('%d/%d',1,handles.amount));
413 | guidata(handles.figure1, handles);
414 |
415 |
416 | % --- Executes on button press in pushbutton_start.
417 | function pushbutton_start_Callback(hObject, eventdata, handles)
418 | % hObject handle to pushbutton_start (see GCBO)
419 | % eventdata reserved - to be defined in a future version of MATLAB
420 | % handles structure with handles and user data (see GUIDATA)
421 |
422 | set(handles.pushbutton_start,'UserData',1);
423 |
424 | contents = get(handles.popupmenu_ittWidth,'String');
425 | ittWidth = str2double(contents{get(handles.popupmenu_ittWidth,'Value')});
426 |
427 | contents = get(handles.popupmenu_ittHeight,'String');
428 | ittHeight = str2double(contents{get(handles.popupmenu_ittHeight,'Value')});
429 |
430 | contents = get(handles.popupmenu_ovlpHor,'String');
431 | ovlapHor = str2double(contents{get(handles.popupmenu_ovlpHor,'Value')});
432 |
433 | contents = get(handles.popupmenu_ovlpVer,'String');
434 | ovlapVer = str2double(contents{get(handles.popupmenu_ovlpVer,'Value')});
435 |
436 | s2ntype = get(handles.popupmenu_s2ntype,'value');
437 | s2nl = str2double(get(handles.edit_s2nl,'string'));
438 | sclt = str2double(get(handles.edit_scale,'string'));
439 | dt = str2double(get(handles.edit_dt,'string'));
440 | outl = str2double(get(handles.edit_outl,'string'));
441 |
442 | preprocess = get(handles.checkbox_preprocess,'Value');
443 | if preprocess
444 | if ~isfield(handles,'preprocess')
445 | prepfun = inline('x');
446 | else
447 | prepfun = str2func(handles.preprocess);
448 | end
449 | else
450 | prepfun = inline('x');
451 | end
452 |
453 | if isfield(handles,'rect') && ~isempty(handles.rect)
454 | cropvec = handles.rect;
455 | else
456 | cropvec = [0 0 0 0];
457 | end
458 | jump = str2double(get(handles.edit_jump,'string'));
459 | if jump == -1
460 | jump = 0;
461 | end
462 |
463 | % Main loop
464 | set(handles.figure1,'pointer','watch')
465 |
466 | %
467 | image1 = fullfile(handles.path,handles.files{1});
468 | image2 = fullfile(handles.path,handles.files{2});
469 |
470 | [a,b] = read_pair_of_images_rect(image1,image2,cropvec,ittWidth,ittHeight,ovlapHor,ovlapVer);
471 | if isempty(a) || isempty(b)
472 | errordlg('Something wrong with your images')
473 | end
474 |
475 | switch handles.filesType
476 | case{'sequence'}
477 | for fileind = 1:handles.amount-jump % main loop, for whole file list
478 | openpiv_main_loop(handles, fileind, jump, cropvec,ittWidth,...
479 | ittHeight,ovlapHor,ovlapVer, prepfun, s2ntype, s2nl, outl, sclt, dt)
480 | end
481 | case{'pairs'}
482 | for fileind = 1:2:handles.amount % main loop, for whole file list
483 | openpiv_main_loop(handles, fileind, 1, cropvec,ittWidth,...
484 | ittHeight,ovlapHor,ovlapVer, prepfun, s2ntype, s2nl, outl, sclt, dt)
485 | end
486 | otherwise
487 |
488 | end
489 | % end
490 | set(handles.figure1,'pointer','arrow')
491 | guidata(handles.figure1,handles);
492 |
493 |
494 | % --- Executes on selection change in popupmenu_ittWidth.
495 | function popupmenu_ittWidth_Callback(hObject, eventdata, handles)
496 | % hObject handle to popupmenu_ittWidth (see GCBO)
497 | % eventdata reserved - to be defined in a future version of MATLAB
498 | % handles structure with handles and user data (see GUIDATA)
499 |
500 | % Hints: contents = cellstr(get(hObject,'String')) returns popupmenu_ittWidth contents as cell array
501 | % contents{get(hObject,'Value')} returns selected item from popupmenu_ittWidth
502 |
503 | if ispc
504 | set(hObject,'BackgroundColor','white');
505 | else
506 | set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
507 | end
508 | % contents = get(hObject,'String');
509 | % handles.itt = str2double(contents{get(hObject,'Value')});
510 | % guidata(hObject,handles);
511 |
512 | % --- Executes during object creation, after setting all properties.
513 | function popupmenu_ittWidth_CreateFcn(hObject, eventdata, handles)
514 | % hObject handle to popupmenu_ittWidth (see GCBO)
515 | % eventdata reserved - to be defined in a future version of MATLAB
516 | % handles empty - handles not created until after all CreateFcns called
517 |
518 | % Hint: popupmenu controls usually have a white background on Windows.
519 | % See ISPC and COMPUTER.
520 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
521 | set(hObject,'BackgroundColor','white');
522 | end
523 |
524 | % contents = get(hObject,'String');
525 | % handles.itt = str2double(contents{get(hObject,'Value')});
526 | % guidata(hObject,handles);
527 |
528 |
529 | % --- Executes on selection change in popupmenu_ovlpHor.
530 | function popupmenu_ovlpHor_Callback(hObject, eventdata, handles)
531 | % hObject handle to popupmenu_ovlpHor (see GCBO)
532 | % eventdata reserved - to be defined in a future version of MATLAB
533 | % handles structure with handles and user data (see GUIDATA)
534 |
535 | % Hints: contents = cellstr(get(hObject,'String')) returns popupmenu_ovlpHor contents as cell array
536 | % contents{get(hObject,'Value')} returns selected item from popupmenu_ovlpHor
537 |
538 | % contents = get(hObject,'String');
539 | % handles.spc = str2double(contents{get(hObject,'Value')});
540 | % guidata(hObject,handles);
541 |
542 |
543 | % --- Executes during object creation, after setting all properties.
544 | function popupmenu_ovlpHor_CreateFcn(hObject, eventdata, handles)
545 | % hObject handle to popupmenu_ovlpHor (see GCBO)
546 | % eventdata reserved - to be defined in a future version of MATLAB
547 | % handles empty - handles not created until after all CreateFcns called
548 |
549 | % Hint: popupmenu controls usually have a white background on Windows.
550 | % See ISPC and COMPUTER.
551 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
552 | set(hObject,'BackgroundColor','white');
553 | end
554 |
555 |
556 |
557 | % --- Executes on selection change in popupmenu_s2ntype.
558 | function popupmenu_s2ntype_Callback(hObject, eventdata, handles)
559 | % hObject handle to popupmenu_s2ntype (see GCBO)
560 | % eventdata reserved - to be defined in a future version of MATLAB
561 | % handles structure with handles and user data (see GUIDATA)
562 |
563 | % Hints: contents = cellstr(get(hObject,'String')) returns popupmenu_s2ntype contents as cell array
564 | % contents{get(hObject,'Value')} returns selected item from popupmenu_s2ntype
565 |
566 | contents = get(hObject,'String');% returns popupmenu_s2ntype contents as cell array
567 | handles.s2ntype = str2double(contents{get(hObject,'Value')});% returns selected item from popupmenu_s2ntype
568 | guidata(hObject,handles);
569 |
570 |
571 | % --- Executes during object creation, after setting all properties.
572 | function popupmenu_s2ntype_CreateFcn(hObject, eventdata, handles)
573 | % hObject handle to popupmenu_s2ntype (see GCBO)
574 | % eventdata reserved - to be defined in a future version of MATLAB
575 | % handles empty - handles not created until after all CreateFcns called
576 |
577 | % Hint: popupmenu controls usually have a white background on Windows.
578 | % See ISPC and COMPUTER.
579 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
580 | set(hObject,'BackgroundColor','white');
581 | end
582 |
583 | contents = get(hObject,'String');% returns popupmenu_s2ntype contents as cell array
584 | handles.s2ntype = str2double(contents{get(hObject,'Value')});% returns selected item from popupmenu_s2ntype
585 | guidata(hObject,handles);
586 |
587 |
588 | function edit_s2nl_Callback(hObject, eventdata, handles)
589 | % hObject handle to edit_s2nl (see GCBO)
590 | % eventdata reserved - to be defined in a future version of MATLAB
591 | % handles structure with handles and user data (see GUIDATA)
592 |
593 | % Hints: get(hObject,'String') returns contents of edit_s2nl as text
594 | % str2double(get(hObject,'String')) returns contents of edit_s2nl as a double
595 |
596 |
597 | % --- Executes during object creation, after setting all properties.
598 | function edit_s2nl_CreateFcn(hObject, eventdata, handles)
599 | % hObject handle to edit_s2nl (see GCBO)
600 | % eventdata reserved - to be defined in a future version of MATLAB
601 | % handles empty - handles not created until after all CreateFcns called
602 |
603 | % Hint: edit controls usually have a white background on Windows.
604 | % See ISPC and COMPUTER.
605 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
606 | set(hObject,'BackgroundColor','white');
607 | end
608 | handles.s2nl = str2double(get(hObject,'String')); % returns contents of edit_s2nl as a double
609 | guidata(hObject,handles);
610 |
611 |
612 | function edit_scale_Callback(hObject, eventdata, handles)
613 | % hObject handle to edit_scale (see GCBO)
614 | % eventdata reserved - to be defined in a future version of MATLAB
615 | % handles structure with handles and user data (see GUIDATA)
616 |
617 | % Hints: get(hObject,'String') returns contents of edit_scale as text
618 | % str2double(get(hObject,'String')) returns contents of edit_scale as a double
619 |
620 | handles.scale = str2double(get(hObject,'String'));% returns contents of edit_scale as a double
621 | guidata(hObject,handles);
622 |
623 | % --- Executes during object creation, after setting all properties.
624 | function edit_scale_CreateFcn(hObject, eventdata, handles)
625 | % hObject handle to edit_scale (see GCBO)
626 | % eventdata reserved - to be defined in a future version of MATLAB
627 | % handles empty - handles not created until after all CreateFcns called
628 |
629 | % Hint: edit controls usually have a white background on Windows.
630 | % See ISPC and COMPUTER.
631 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
632 | set(hObject,'BackgroundColor','white');
633 | end
634 | handles.scale = str2double(get(hObject,'String'));% returns contents of edit_scale as a double
635 | guidata(hObject,handles);
636 |
637 |
638 | function edit_outl_Callback(hObject, eventdata, handles)
639 | % hObject handle to edit_outl (see GCBO)
640 | % eventdata reserved - to be defined in a future version of MATLAB
641 | % handles structure with handles and user data (see GUIDATA)
642 |
643 | % Hints: get(hObject,'String') returns contents of edit_outl as text
644 | % str2double(get(hObject,'String')) returns contents of edit_outl as a double
645 |
646 | handles.outl = str2double(get(hObject,'String')); % returns contents of edit_outl as a double
647 | guidata(hObject,handles);
648 |
649 |
650 | % --- Executes during object creation, after setting all properties.
651 | function edit_outl_CreateFcn(hObject, eventdata, handles)
652 | % hObject handle to edit_outl (see GCBO)
653 | % eventdata reserved - to be defined in a future version of MATLAB
654 | % handles empty - handles not created until after all CreateFcns called
655 |
656 | % Hint: edit controls usually have a white background on Windows.
657 | % See ISPC and COMPUTER.
658 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
659 | set(hObject,'BackgroundColor','white');
660 | end
661 |
662 | handles.outl = str2double(get(hObject,'String')); % returns contents of edit_outl as a double
663 | guidata(hObject,handles);
664 |
665 |
666 | % --- Executes on button press in pushbutton_stop.
667 | function pushbutton_stop_Callback(hObject, eventdata, handles)
668 | % hObject handle to pushbutton_stop (see GCBO)
669 | % eventdata reserved - to be defined in a future version of MATLAB
670 | % handles structure with handles and user data (see GUIDATA)
671 |
672 | selection = questdlg(['Stop ' get(handles.figure1,'Name') '?'],...
673 | ['Close ' get(handles.figure1,'Name') '...'],...
674 | 'Yes','No','Yes');
675 | if strcmp(selection,'No')
676 | return;
677 | elseif strcmp(selection,'Yes')
678 | set(handles.pushbutton_start,'UserData',0);
679 | set(handles.figure1,'pointer','arrow');
680 | end
681 | % delete(handles.figure1)
682 | guidata(hObject,handles);
683 |
684 |
685 | function edit_num_Callback(hObject, eventdata, handles)
686 | % hObject handle to edit_num (see GCBO)
687 | % eventdata reserved - to be defined in a future version of MATLAB
688 | % handles structure with handles and user data (see GUIDATA)
689 |
690 | % Hints: get(hObject,'String') returns contents of edit_num as text
691 | % str2double(get(hObject,'String')) returns contents of edit_num as a double
692 |
693 |
694 | % --- Executes during object creation, after setting all properties.
695 | function edit_num_CreateFcn(hObject, eventdata, handles)
696 | % hObject handle to edit_num (see GCBO)
697 | % eventdata reserved - to be defined in a future version of MATLAB
698 | % handles empty - handles not created until after all CreateFcns called
699 |
700 | % Hint: edit controls usually have a white background on Windows.
701 | % See ISPC and COMPUTER.
702 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
703 | set(hObject,'BackgroundColor','white');
704 | end
705 |
706 |
707 |
708 | function edit_jump_Callback(hObject, eventdata, handles)
709 | % hObject handle to edit_jump (see GCBO)
710 | % eventdata reserved - to be defined in a future version of MATLAB
711 | % handles structure with handles and user data (see GUIDATA)
712 |
713 | % Hints: get(hObject,'String') returns contents of edit_jump as text
714 | % str2double(get(hObject,'String')) returns contents of edit_jump as a double
715 | handles.jump = str2double(get(hObject,'String')); % returns contents of edit_jump as a double
716 | guidata(hObject,handles);
717 |
718 | % --- Executes during object creation, after setting all properties.
719 | function edit_jump_CreateFcn(hObject, eventdata, handles)
720 | % hObject handle to edit_jump (see GCBO)
721 | % eventdata reserved - to be defined in a future version of MATLAB
722 | % handles empty - handles not created until after all CreateFcns called
723 |
724 | % Hint: edit controls usually have a white background on Windows.
725 | % See ISPC and COMPUTER.
726 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
727 | set(hObject,'BackgroundColor','white');
728 | end
729 |
730 | handles.jump = str2double(get(hObject,'String')); % returns contents of edit_jump as a double
731 | guidata(hObject,handles);
732 |
733 | % --- Executes on button press in button_select.
734 | function button_select_Callback(hObject, eventdata, handles)
735 | % hObject handle to button_select (see GCBO)
736 | % eventdata reserved - to be defined in a future version of MATLAB
737 | % handles structure with handles and user data (see GUIDATA)
738 |
739 | axes(handles.axes1);
740 | handles.rect = getrect;
741 | rectangle('position',handles.rect,'Curvature',[0 0],'Edgecolor','yellow','Linestyle',':');
742 | guidata(handles.figure1,handles);
743 |
744 |
745 | % --- Executes on button press in button_reset_ROI.
746 | function button_reset_ROI_Callback(hObject, eventdata, handles)
747 | % hObject handle to button_reset_ROI (see GCBO)
748 | % eventdata reserved - to be defined in a future version of MATLAB
749 | % handles structure with handles and user data (see GUIDATA)
750 |
751 | if isfield(handles,'rect')
752 | handles.rect = [];
753 | delete(findobj(handles.axes1,'type','rectangle'))
754 | end
755 | guidata(handles.figure1,handles);
756 |
757 |
758 | % --- Executes on selection change in popupmenu_ittHeight.
759 | function popupmenu_ittHeight_Callback(hObject, eventdata, handles)
760 | % hObject handle to popupmenu_ittHeight (see GCBO)
761 | % eventdata reserved - to be defined in a future version of MATLAB
762 | % handles structure with handles and user data (see GUIDATA)
763 |
764 | % Hints: contents = cellstr(get(hObject,'String')) returns popupmenu_ittHeight contents as cell array
765 | % contents{get(hObject,'Value')} returns selected item from popupmenu_ittHeight
766 |
767 |
768 | % --- Executes during object creation, after setting all properties.
769 | function popupmenu_ittHeight_CreateFcn(hObject, eventdata, handles)
770 | % hObject handle to popupmenu_ittHeight (see GCBO)
771 | % eventdata reserved - to be defined in a future version of MATLAB
772 | % handles empty - handles not created until after all CreateFcns called
773 |
774 | % Hint: popupmenu controls usually have a white background on Windows.
775 | % See ISPC and COMPUTER.
776 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
777 | set(hObject,'BackgroundColor','white');
778 | end
779 |
780 |
781 | % --- Executes on selection change in popupmenu_ovlpVer.
782 | function popupmenu_ovlpVer_Callback(hObject, eventdata, handles)
783 | % hObject handle to popupmenu_ovlpVer (see GCBO)
784 | % eventdata reserved - to be defined in a future version of MATLAB
785 | % handles structure with handles and user data (see GUIDATA)
786 |
787 | % Hints: contents = cellstr(get(hObject,'String')) returns popupmenu_ovlpVer contents as cell array
788 | % contents{get(hObject,'Value')} returns selected item from popupmenu_ovlpVer
789 |
790 |
791 | % --- Executes during object creation, after setting all properties.
792 | function popupmenu_ovlpVer_CreateFcn(hObject, eventdata, handles)
793 | % hObject handle to popupmenu_ovlpVer (see GCBO)
794 | % eventdata reserved - to be defined in a future version of MATLAB
795 | % handles empty - handles not created until after all CreateFcns called
796 |
797 | % Hint: popupmenu controls usually have a white background on Windows.
798 | % See ISPC and COMPUTER.
799 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
800 | set(hObject,'BackgroundColor','white');
801 | end
802 |
803 |
804 | % --- Executes on button press in checkbox_preprocess.
805 | function checkbox_preprocess_Callback(hObject, eventdata, handles)
806 | % hObject handle to checkbox_preprocess (see GCBO)
807 | % eventdata reserved - to be defined in a future version of MATLAB
808 | % handles structure with handles and user data (see GUIDATA)
809 |
810 | % Hint: get(hObject,'Value') returns toggle state of checkbox_preprocess
811 |
812 | if get(hObject,'Value')
813 | % if checked
814 | set(handles.pushbutton_select_preprocessor,'Enable','on');
815 | else
816 | set(handles.pushbutton_select_preprocessor,'Enable','off');
817 | end
818 |
819 |
820 | % --- Executes on button press in pushbutton_select_preprocessor.
821 | function pushbutton_select_preprocessor_Callback(hObject, eventdata, handles)
822 | % hObject handle to pushbutton_select_preprocessor (see GCBO)
823 | % eventdata reserved - to be defined in a future version of MATLAB
824 | % handles structure with handles and user data (see GUIDATA)
825 | preprocess_mfile = uigetfile('*.m','Pick an M-file');
826 | handles.preprocess = preprocess_mfile(1:end-2);
827 | guidata(handles.figure1,handles);
828 |
829 |
830 | % --- Executes on button press in prev_image.
831 | function prev_image_Callback(hObject, eventdata, handles)
832 | % hObject handle to prev_image (see GCBO)
833 | % eventdata reserved - to be defined in a future version of MATLAB
834 | % handles structure with handles and user data (see GUIDATA)
835 | axes(handles.axes1);
836 | filenum = str2num(get(handles.edit_num,'String'));
837 | filenum = max(1,filenum - 1);
838 | set(handles.edit_num,'String',int2str(filenum));
839 | % imshow(fullfile(handles.path,handles.files{1}));
840 | imshow(openpiv_imread(fullfile(handles.path,handles.files{filenum})));
841 | guidata(hObject, handles);
842 |
843 |
844 |
845 | % --- Executes on button press in next_image.
846 | function next_image_Callback(hObject, eventdata, handles)
847 | % hObject handle to next_image (see GCBO)
848 | % eventdata reserved - to be defined in a future version of MATLAB
849 | % handles structure with handles and user data (see GUIDATA)
850 |
851 | axes(handles.axes1);
852 | filenum = str2num(get(handles.edit_num,'String'));
853 | filenum = min(filenum + 1,length(handles.files));
854 | set(handles.edit_num,'String',int2str(filenum));
855 | imshow(openpiv_imread(fullfile(handles.path,handles.files{filenum})));
856 | guidata(hObject, handles);
857 |
858 |
859 | % --------------------------------------------------------------------
860 | function exit_Callback(hObject, eventdata, handles)
861 | % hObject handle to exit (see GCBO)
862 | % eventdata reserved - to be defined in a future version of MATLAB
863 | % handles structure with handles and user data (see GUIDATA)
864 | selection = questdlg(['Close ' get(handles.figure1,'Name') '?'],...
865 | ['Close ' get(handles.figure1,'Name') '...'],...
866 | 'Yes','No','Yes');
867 | if strcmp(selection,'No')
868 | return;
869 | end
870 |
871 | delete(handles.figure1)
872 |
873 |
874 | % --------------------------------------------------------------------
875 | function file_Callback(hObject, eventdata, handles)
876 | % hObject handle to file (see GCBO)
877 | % eventdata reserved - to be defined in a future version of MATLAB
878 | % handles structure with handles and user data (see GUIDATA)
879 |
880 |
881 |
882 | % --------------------------------------------------------------------
883 |
884 |
885 | % --- Executes during object creation, after setting all properties.
886 | function pushbutton_start_CreateFcn(hObject, eventdata, handles)
887 | % hObject handle to pushbutton_start (see GCBO)
888 | % eventdata reserved - to be defined in a future version of MATLAB
889 | % handles empty - handles not created until after all CreateFcns called
890 | set(hObject,'UserData',1);
891 | guidata(hObject,handles);
892 |
893 |
894 | % --------------------------------------------------------------------
895 | %
896 |
897 | % --------------------------------------------------------------------
898 | function handles = ReadImageDirectory(handles)
899 | firstDif = find(handles.files{2}-handles.files{1},1,'first'); % how the first two files are different?
900 | handles.filebase = handles.files{1}(1:firstDif-1); % base file name, e.g. bird_b00100
901 | fileType = handles.files{1}(firstDif:end-4); % without extension
902 | switch lower(fileType)
903 | case{'a','_a','b','_b'}
904 | handles.amount = length(handles.files); % pairs
905 | handles.filesType = 'pairs';
906 | handles.step = 2;
907 | set(handles.edit_jump,'Enable','Off');
908 | set(handles.edit_jump,'String','-1');
909 | otherwise
910 | handles.amount = length(handles.files);
911 | handles.filesType = 'sequence';
912 | handles.step = 1;
913 | set(handles.edit_jump,'Enable','On');
914 | end
915 |
916 | % handles.filebase = handles.files{1}(1:max(findstr(handles.files{1},'_'))-1);
917 | guidata(handles.figure1,handles);
918 |
919 | % --------------------------------------------------------------------
920 |
921 |
922 |
923 | % --------------------------------------------------------------------
924 | function help_Callback(hObject, eventdata, handles)
925 | % hObject handle to help (see GCBO)
926 | % eventdata reserved - to be defined in a future version of MATLAB
927 | % handles structure with handles and user data (see GUIDATA)
928 |
929 |
930 | % --------------------------------------------------------------------
931 | function github_Callback(hObject, eventdata, handles)
932 | % hObject handle to github (see GCBO)
933 | % eventdata reserved - to be defined in a future version of MATLAB
934 | % handles structure with handles and user data (see GUIDATA)
935 | web('http://www.openpiv.net/openpiv-matlab/', '-new');
936 |
937 |
938 | % --------------------------------------------------------------------
939 | function wiki_Callback(hObject, eventdata, handles)
940 | % hObject handle to wiki (see GCBO)
941 | % eventdata reserved - to be defined in a future version of MATLAB
942 | % handles structure with handles and user data (see GUIDATA)
943 | web('http://www.openpiv.net/faq.html', '-new');
944 |
945 |
946 |
947 |
948 |
949 |
950 | function edit_dt_Callback(hObject, eventdata, handles)
951 | % hObject handle to edit_dt (see GCBO)
952 | % eventdata reserved - to be defined in a future version of MATLAB
953 | % handles structure with handles and user data (see GUIDATA)
954 |
955 | % Hints: get(hObject,'String') returns contents of edit_dt as text
956 | % str2double(get(hObject,'String')) returns contents of edit_dt as a double
957 |
958 |
959 | % --- Executes during object creation, after setting all properties.
960 | function edit_dt_CreateFcn(hObject, eventdata, handles)
961 | % hObject handle to edit_dt (see GCBO)
962 | % eventdata reserved - to be defined in a future version of MATLAB
963 | % handles empty - handles not created until after all CreateFcns called
964 |
965 | % Hint: edit controls usually have a white background on Windows.
966 | % See ISPC and COMPUTER.
967 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
968 | set(hObject,'BackgroundColor','white');
969 | end
970 |
971 |
972 |
973 |
974 |
975 |
976 | % -- Main loop --- %
977 | function openpiv_main_loop(handles, fileind, jump, cropvec,ittWidth,...
978 | ittHeight,ovlapHor,ovlapVer, prepfun, s2ntype, s2nl, outl, sclt, dt)
979 | % OPENPIV_MAIN_LOOP is the main PIV processing, post-processing and
980 | % plotting subroutines calls
981 |
982 | set(handles.edit_num,'string',sprintf('%d',fileind));
983 |
984 |
985 | image1 = fullfile(handles.path,handles.files{fileind});
986 | image2 = fullfile(handles.path,handles.files{fileind+jump});
987 |
988 | [a,~,a1,b1,origin] = read_pair_of_images_rect(image1,image2,cropvec,ittWidth,ittHeight,ovlapHor,ovlapVer);
989 |
990 | % a1 = prepfun(a1);
991 | % b1 = prepfun(b1);
992 |
993 | [verSize,horSize]= size(a1);
994 |
995 | % Prepare the results storage;
996 |
997 | rows = 1:ovlapVer:verSize - ittHeight + 1;
998 | cols = 1:ovlapHor:horSize - ittWidth + 1;
999 |
1000 | numcols = length(rows);
1001 | numrows = length(cols);
1002 |
1003 | res = zeros(numcols*numrows,5);
1004 | resind = 0;
1005 |
1006 | % a2 = zeros(ittHeight,ittWidth);
1007 | % b2 = zeros(ittHeight,ittWidth);
1008 | NfftWidth = 2*ittWidth;
1009 | NfftHeight = 2*ittHeight;
1010 |
1011 | axes(handles.axes1);
1012 | % imshow(imadjust(a),[]);
1013 | imshow(a,[]);
1014 | hold on
1015 | h1 = animatedline('Color','y');
1016 | h2 = animatedline('Color','y');
1017 |
1018 | for m = rows % vertically
1019 | for k = cols % horizontally
1020 | % if Stop button pressed:
1021 | if (get(handles.pushbutton_start,'UserData') == 0)
1022 | return;
1023 | end
1024 |
1025 | a2 = a1(m:m+ittHeight-1,k:k+ittWidth-1);
1026 | b2 = b1(m:m+ittHeight-1,k:k+ittWidth-1);
1027 |
1028 |
1029 | c = cross_correlate_rect(a2,b2,NfftHeight,NfftWidth);
1030 | % c = cross_correlate_rect(a2,b2,Nfftx,Nffty);
1031 | if ~any(c(:)), % completely "black"
1032 | u = 0;
1033 | v = 0;
1034 | y = origin(2) + m + ittHeight/2 - 1;
1035 | x = origin(1) + k + ittWidth/2 - 1;
1036 |
1037 | resind = resind + 1;
1038 | res(resind,:) = [x y 0.0 0.0 0.0];
1039 | continue
1040 | end
1041 |
1042 | [peak1,peak2,pixi,pixj] = find_displacement_rect(c,s2ntype);
1043 |
1044 | [peakVer,peakHor,s2n] = sub_pixel_velocity_rect(c,pixi,pixj,peak1,peak2,s2nl,ittWidth,ittHeight);
1045 |
1046 | % Scale the pixel displacement to the velocity
1047 | u = (ittWidth-peakHor);
1048 | v = (ittHeight-peakVer);
1049 | y = origin(2) + m + ittHeight/2-1;
1050 | x = origin(1) + k + ittWidth/2-1;
1051 |
1052 | resind = resind + 1;
1053 | res(resind,:) = [x y u v s2n];
1054 | % quiver(x+cropvec(1),y+cropvec(2),u,v,'y');
1055 | if u ~= 0 || v ~= 0
1056 | plotarrow(h1,h2,x,y,u,v,10);
1057 | end
1058 | end
1059 | end
1060 |
1061 | no_filt_res = res;
1062 |
1063 | [res, filt_res] = openpiv_filter(res,numcols,numrows,outl);
1064 |
1065 | % imshow(prepfun(a),[]);
1066 | imshow(a,[]);
1067 | hold on
1068 | clearpoints(h1);
1069 | clearpoints(h2);
1070 | % for i = 1:length(res)
1071 | % plotarrow(h1,h2,res(i,1),res(i,2),res(i,3),res(i,4));
1072 | % end
1073 | quiverm(res,'color','g','AutoScaleFactor',2);
1074 | ind = (filt_res(:,3) ~= no_filt_res(:,3) | filt_res(:,4) ~= no_filt_res(:,4));
1075 | if ~any(ind)
1076 | quiverm(no_filt_res(ind,:),'color','r','AutoScaleFactor',1.25);
1077 | end
1078 | % for i = 1:length(res)
1079 | % plotarrow(h1,h2,res(i,1),res(i,2),res(i,3),res(i,4));
1080 | % end
1081 | % drawnow
1082 |
1083 | basename = handles.files{fileind}(1:end-4);
1084 | baseext = '.vec';
1085 |
1086 | openpiv_output(res,no_filt_res,filt_res,dt,sclt,numrows, numcols, ...
1087 | handles.path,basename,baseext);
1088 |
1089 | hold off
1090 |
--------------------------------------------------------------------------------