├── 2D_vortices_1.tif ├── 2D_vortices_2.tif ├── Flow_Diagnostics_Run.asv ├── Flow_Diagnostics_Run.m ├── MIT License.pdf ├── Open_Optical_Flow_Paper_v1.pdf ├── OpticalFlowPhysics_fun.m ├── README.md ├── README.pdf ├── White_Oval_1.tif ├── White_Oval_2.tif ├── correction_illumination.m ├── generate_invmatrix.m ├── horn_schunk_estimator.m ├── invariant2_factor.m ├── laplacian.m ├── liu_shen_estimator.m ├── plots_set_1.m ├── plots_set_2.asv ├── plots_set_2.m ├── pre_processing_a.m ├── rescaling_intensity.m ├── shift_image_fun_refine_1.m ├── vis_flow.m ├── vortex_pair_particles_1.tif ├── vortex_pair_particles_2.tif ├── vorticity.m ├── vorticity_factor.m ├── wall_jet_1.tif └── wall_jet_2.tif /2D_vortices_1.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianshu-Liu/OpenOpticalFlow/d802f56299ead7ff34118dbc144a115272138fa2/2D_vortices_1.tif -------------------------------------------------------------------------------- /2D_vortices_2.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianshu-Liu/OpenOpticalFlow/d802f56299ead7ff34118dbc144a115272138fa2/2D_vortices_2.tif -------------------------------------------------------------------------------- /Flow_Diagnostics_Run.asv: -------------------------------------------------------------------------------- 1 | %% Tianshu Liu 2 | %% Department of Mechanical and Aerospace Engineering, 3 | %% Western Michigan University, Kalamazoo, MI, USA 4 | 5 | clear all; 6 | close all; 7 | 8 | 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | %% Read a pair of images 11 | Im1=imread('White_oval_1.tif'); 12 | Im2=imread('White_Oval_2.tif'); 13 | 14 | % Im1=imread('vortex_pair_particles_1.tif'); 15 | % Im2=imread('vortex_pair_particles_2.tif'); 16 | 17 | 18 | % Im1=imread('2D_vortices_1.tif'); 19 | % Im2=imread('2D_vortices_2.tif'); 20 | 21 | 22 | % Im1=imread('wall_jet_1.tif'); 23 | % Im2=imread('wall_jet_2.tif'); 24 | 25 | 26 | 27 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 28 | 29 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 30 | 31 | %% Set the Parameters for Optical Flow Computation 32 | 33 | %% Set the lagrange multipleirs in optical computation 34 | lambda_1=20; % the Horn_schunck estimator for initial field 35 | lambda_2=2000; % the Liu-Shen estimator for refined estimation 36 | 37 | %% Number of iterations in the coarse-to-fine iterative process from 38 | %% initial estimation, "0" means no iteration 39 | no_iteration=1; 40 | 41 | %% Initial coarse field estimation in the coarse-to-fine iterative process, 42 | %% scale_im is a scale factor for down-sizing of images 43 | scale_im=0.5; 44 | 45 | 46 | %% For Image Pre-Processing 47 | 48 | %% For local illumination intensity adjustment, To bypass it, set size_average = 0 49 | size_average=0; % in pixels 50 | 51 | %% Gausian filter size for removing random noise in images 52 | size_filter=4; % in pixels 53 | 54 | %% Selete a region for processing (index_region = 1) otherwise processing for the 55 | %% whole image (index_region = 0) 56 | index_region=0; 57 | 58 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 59 | 60 | 61 | 62 | %% Selete a region of interest for dognostics 63 | Im1=double(Im1); 64 | Im2=double(Im2); 65 | 66 | if (index_region == 1) 67 | imagesc(uint8(Im1)); 68 | colormap(gray); 69 | axis image; 70 | 71 | xy=ginput(2); 72 | x1=floor(min(xy(:,1))); 73 | x2=floor(max(xy(:,1))); 74 | y1=floor(min(xy(:,2))); 75 | y2=floor(max(xy(:,2))); 76 | I1=double(Im1(y1:y2,x1:x2)); 77 | I2=double(Im2(y1:y2,x1:x2)); 78 | elseif (index_region == 0) 79 | I1=Im1; 80 | I2=Im2; 81 | end 82 | 83 | I1_original=I1; 84 | I2_original=I2; 85 | 86 | 87 | %% correcting the global and local intensity change in images 88 | [m1,n1]=size(I1); 89 | window_shifting=[1;n1;1;m1]; % [x1,x2,y1,y2] deines a rectangular window for global correction 90 | [I1,I2]=correction_illumination(I1,I2,window_shifting,size_average); 91 | 92 | 93 | %% pre-processing for reducing random noise, 94 | %% and downsampling images if displacements are large 95 | [I1,I2] = pre_processing_a(I1,I2,scale_im,size_filter); 96 | 97 | I_region1=I1; 98 | I_region2=I2; 99 | 100 | 101 | %% initial optical flow calculation for a coarse-grained velocity field 102 | %% (ux0,uy0) 103 | [ux0,uy0,vor,ux_horn,uy_horn,error1]=OpticalFlowPhysics_fun(I_region1,I_region2,lambda_1,lambda_2); 104 | % ux is the velocity (pixels/unit time) in the image x-coordinate (from the left-up corner to right) 105 | % uy is the velocity (pixels/unit time) in the image y-coordinate (from the left-up corner to bottom) 106 | 107 | 108 | %% generate the shifted image from Im1 based on the initial coarse-grained velocity field (ux0, uy0), 109 | %% and then calculate velocity difference for iterative correction 110 | Im1=uint8(I1_original); 111 | Im2=uint8(I2_original); 112 | 113 | ux_corr=ux0; 114 | uy_corr=uy0; 115 | 116 | %% estimate the displacement vector and at 0th iteration 117 | 118 | k=1; 119 | while k<=no_iteration 120 | [Im1_shift,uxI,uyI]=shift_image_fun_refine_1(ux_corr,uy_corr,Im1,Im2); 121 | 122 | I1=double(Im1); 123 | I2=double(Im2); 124 | 125 | % calculation of correction of the optical flow 126 | [dux,duy,vor,dux_horn,duy_horn,error2]=OpticalFlowPhysics_fun(I1,I2,lambda_1,lambda_2); 127 | 128 | % refined optical flow 129 | ux_corr=uxI+dux; 130 | uy_corr=uyI+duy; 131 | 132 | 133 | k=k+1; 134 | end 135 | 136 | %% refined velocity field 137 | ux=ux_corr; %%%%% 138 | uy=uy_corr; %%%%% 139 | 140 | %% show the images and processed results 141 | %% plot the images, velocity vector, and streamlines in the initail and 142 | %% refined estimations 143 | plots_set_1; 144 | 145 | %% plot the fields of velocity magnitude, vorticity and Q 146 | plots_set_2; 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /Flow_Diagnostics_Run.m: -------------------------------------------------------------------------------- 1 | %% This is the main program for extraction of velocity field from a pair of 2 | %% flow visualization images 3 | %% Copyrights by Tianshu Liu 4 | %% Department of Mechanical and Aerospace Engineering, 5 | %% Western Michigan University, Kalamazoo, MI, USA 6 | 7 | clear all; 8 | close all; 9 | 10 | 11 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | %% Read a pair of images 13 | %% For 12, 14 and 14 bit images, they should be converted to 8 bit images 14 | %% befor optical flow computation 15 | 16 | Im1=imread('White_oval_1.tif'); 17 | Im2=imread('White_Oval_2.tif'); 18 | 19 | % Im1=imread('vortex_pair_particles_1.tif'); 20 | % Im2=imread('vortex_pair_particles_2.tif'); 21 | 22 | 23 | % Im1=imread('2D_vortices_1.tif'); 24 | % Im2=imread('2D_vortices_2.tif'); 25 | 26 | 27 | % Im1=imread('wall_jet_1.tif'); 28 | % Im2=imread('wall_jet_2.tif'); 29 | 30 | 31 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 32 | 33 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 34 | 35 | %% Set the Parameters for Optical Flow Computation 36 | 37 | %% Set the lagrange multipleirs in optical computation 38 | lambda_1=20; % the Horn_schunck estimator for initial field 39 | lambda_2=2000; % the Liu-Shen estimator for refined estimation 40 | 41 | %% Number of iterations in the coarse-to-fine iterative process from 42 | %% initial estimation, "0" means no iteration 43 | no_iteration=1; 44 | 45 | %% Initial coarse field estimation in the coarse-to-fine iterative process, 46 | %% scale_im is a scale factor for down-sizing of images 47 | scale_im=0.5; 48 | 49 | 50 | %% For Image Pre-Processing 51 | 52 | %% For local illumination intensity adjustment, To bypass it, set size_average = 0 53 | size_average=20; % in pixels 54 | 55 | %% Gausian filter size for removing random noise in images 56 | size_filter=4; % in pixels 57 | 58 | %% Selete a region for processing (index_region = 1) otherwise processing for the 59 | %% whole image (index_region = 0) 60 | index_region=1; 61 | 62 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 63 | 64 | 65 | 66 | %% Selete a region of interest for dognostics 67 | Im1=double(Im1); 68 | Im2=double(Im2); 69 | 70 | if (index_region == 1) 71 | imagesc(uint8(Im1)); 72 | colormap(gray); 73 | axis image; 74 | 75 | xy=ginput(2); 76 | x1=floor(min(xy(:,1))); 77 | x2=floor(max(xy(:,1))); 78 | y1=floor(min(xy(:,2))); 79 | y2=floor(max(xy(:,2))); 80 | I1=double(Im1(y1:y2,x1:x2)); 81 | I2=double(Im2(y1:y2,x1:x2)); 82 | elseif (index_region == 0) 83 | I1=Im1; 84 | I2=Im2; 85 | end 86 | 87 | I1_original=I1; 88 | I2_original=I2; 89 | 90 | 91 | %% correcting the global and local intensity change in images 92 | [m1,n1]=size(I1); 93 | window_shifting=[1;n1;1;m1]; % [x1,x2,y1,y2] deines a rectangular window for global correction 94 | [I1,I2]=correction_illumination(I1,I2,window_shifting,size_average); 95 | 96 | 97 | %% pre-processing for reducing random noise, 98 | %% and downsampling images if displacements are large 99 | [I1,I2] = pre_processing_a(I1,I2,scale_im,size_filter); 100 | 101 | I_region1=I1; 102 | I_region2=I2; 103 | 104 | 105 | %% initial optical flow calculation for a coarse-grained velocity field 106 | %% (ux0,uy0) 107 | [ux0,uy0,vor,ux_horn,uy_horn,error1]=OpticalFlowPhysics_fun(I_region1,I_region2,lambda_1,lambda_2); 108 | % ux is the velocity (pixels/unit time) in the image x-coordinate (from the left-up corner to right) 109 | % uy is the velocity (pixels/unit time) in the image y-coordinate (from the left-up corner to bottom) 110 | 111 | 112 | %% generate the shifted image from Im1 based on the initial coarse-grained velocity field (ux0, uy0), 113 | %% and then calculate velocity difference for iterative correction 114 | Im1=uint8(I1_original); 115 | Im2=uint8(I2_original); 116 | 117 | ux_corr=ux0; 118 | uy_corr=uy0; 119 | 120 | %% estimate the displacement vector and make correction in iterations 121 | 122 | k=1; 123 | while k<=no_iteration 124 | [Im1_shift,uxI,uyI]=shift_image_fun_refine_1(ux_corr,uy_corr,Im1,Im2); 125 | 126 | I1=double(Im1_shift); 127 | I2=double(Im2); 128 | 129 | size_filter_1=2; 130 | [I1,I2] = pre_processing_a(I1,I2,1,size_filter_1); 131 | 132 | % calculation of correction of the optical flow 133 | [dux,duy,vor,dux_horn,duy_horn,error2]=OpticalFlowPhysics_fun(I1,I2,lambda_1,lambda_2); 134 | 135 | % refined optical flow 136 | ux_corr=uxI+dux; 137 | uy_corr=uyI+duy; 138 | 139 | 140 | k=k+1; 141 | end 142 | 143 | %% refined velocity field 144 | ux=ux_corr; %%%%% 145 | uy=uy_corr; %%%%% 146 | 147 | %% show the images and processed results 148 | %% plot the images, velocity vector, and streamlines in the initail and 149 | %% refined estimations 150 | plots_set_1; 151 | 152 | %% plot the fields of velocity magnitude, vorticity and the second invariant Q 153 | plots_set_2; 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /MIT License.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianshu-Liu/OpenOpticalFlow/d802f56299ead7ff34118dbc144a115272138fa2/MIT License.pdf -------------------------------------------------------------------------------- /Open_Optical_Flow_Paper_v1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianshu-Liu/OpenOpticalFlow/d802f56299ead7ff34118dbc144a115272138fa2/Open_Optical_Flow_Paper_v1.pdf -------------------------------------------------------------------------------- /OpticalFlowPhysics_fun.m: -------------------------------------------------------------------------------- 1 | function [ux,uy,vor,ux_horn,uy_horn,error1]=OpticalFlowPhysics_fun(I1,I2,lambda_1,lambda_2) 2 | 3 | 4 | % Horn's solution as an initial approximation of u and v 5 | D1 = [0, 0, 0; 0,-1,-1;0,1,1]/2; 6 | F1 = [0, 0, 0; 0,1,1;0,1,1]/4; 7 | 8 | Ix = imfilter((I1+I2)/2, D1, 'symmetric', 'same'); 9 | Iy = imfilter((I1+I2)/2, D1', 'symmetric', 'same'); 10 | It = imfilter(I2-I1, F1, 'symmetric', 'same'); 11 | 12 | maxnum_1=500; 13 | tol_1 = 10^(-12); 14 | % lambda_1 = 10; 15 | 16 | [u,v] = horn_schunk_estimator(Ix, Iy, It, lambda_1, tol_1, maxnum_1); 17 | ux_horn = v; 18 | uy_horn = u; 19 | 20 | 21 | % new model 22 | Dm=0*10^(-3); 23 | f=Dm*laplacian(I1,1); 24 | 25 | maxnum=60; 26 | tol = 0.00000001; 27 | % lambda_2 = 4000; % 2000 for dI0 28 | 29 | dx=1; 30 | dt=1; % unit time 31 | [u,v,error1] = liu_shen_estimator(I1, I2, f, dx, dt, lambda_2, tol, maxnum, uy_horn, ux_horn); 32 | 33 | ux=v; 34 | uy=u; 35 | 36 | vor=vorticity(ux, uy); 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenOpticalFlow 2 | OpenOpticalFlow is an open source optical flow program in Matlab for extraction of high-resolution velocity fields from various flow visualization images. 3 | -------------------------------------------------------------------------------- /README.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianshu-Liu/OpenOpticalFlow/d802f56299ead7ff34118dbc144a115272138fa2/README.pdf -------------------------------------------------------------------------------- /White_Oval_1.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianshu-Liu/OpenOpticalFlow/d802f56299ead7ff34118dbc144a115272138fa2/White_Oval_1.tif -------------------------------------------------------------------------------- /White_Oval_2.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianshu-Liu/OpenOpticalFlow/d802f56299ead7ff34118dbc144a115272138fa2/White_Oval_2.tif -------------------------------------------------------------------------------- /correction_illumination.m: -------------------------------------------------------------------------------- 1 | function [I1,I2] = correction_illumination(Im1,Im2,window_shifting,size_average) 2 | 3 | 4 | Im1=double(Im1); 5 | Im2=double(Im2); 6 | 7 | I1=Im1; 8 | I2=Im2; 9 | 10 | % adjusting the overall illumination change 11 | x3=window_shifting(1); 12 | x4=window_shifting(2); 13 | y3=window_shifting(3); 14 | y4=window_shifting(4); 15 | 16 | I1_mean=mean(mean(I1(y3:y4,x3:x4))); 17 | I2_mean=mean(mean(I2(y3:y4,x3:x4))); 18 | R12=I1_mean/I2_mean; 19 | I2=R12*I2; 20 | 21 | 22 | % normalize the intensity for I2 to eliminate the local change of illumination light 23 | if size_average>0 24 | N=size_average; 25 | %N=30; % size for averaging 26 | h=ones(N,N)/(N*N); 27 | I12F=filter2(h,I1)-filter2(h,I2); 28 | I2=I2+I12F; 29 | elseif size_average==0 30 | I2=I2; 31 | end 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /generate_invmatrix.m: -------------------------------------------------------------------------------- 1 | function [B11, B12, B22] = generate_invmatrix(I, alpha, h) 2 | 3 | D = [0, -1, 0; 0,0,0; 0,1,0]/2; %%% partial derivative 4 | M = [1, 0, -1; 0,0,0;-1,0,1]/4; %%% mixed partial derivatives 5 | F = [0, 0, 0; 0,1,1;0,1,1]/4; %%% average 6 | D2 = [0, 1, 0; 0,-2,0;0,1,0]; %%% partial derivative 7 | H = [1, 1, 1; 1,0,1;1,1,1]; 8 | 9 | [r,c]=size(I); 10 | 11 | cmtx = imfilter(ones(size(I)), H/(h*h), 'same'); 12 | 13 | A11 = I.*(imfilter(I, D2/(h*h), 'replicate', 'same')-2*I/(h*h)) - alpha*cmtx; 14 | A22 = I.*(imfilter(I, D2'/(h*h), 'replicate', 'same')-2*I/(h*h)) - alpha*cmtx; 15 | A12 = I.*imfilter(I, M/(h*h), 'replicate', 'same'); 16 | 17 | DetA = A11.*A22-A12.*A12; 18 | 19 | B11 = A22./DetA; 20 | B12 = -A12./DetA; 21 | B22 = A11./DetA; 22 | 23 | 24 | 25 | 26 | 27 | % D = [0, 0, 0; 0,-1,0;0,1,0]; %%% partial derivative 28 | % M = [0, 0, 0; 0,1,-1;0,-1,1]; %%% mixed partial derivatives 29 | % F = [0, 0, 0; 0,1,1;0,1,1]/4; %%% average 30 | % D2 = [0, 1, 0; 0,-2,0;0,1,0]; %%% partial derivative 31 | % H = [1, 1, 1; 1,0,1;1,1,1]; 32 | % 33 | % [r,c]=size(I); 34 | % 35 | % cmtx = imfilter(ones(size(I)), H, 'same'); 36 | % 37 | % A11 = I.*(imfilter(I, D2, 'replicate', 'same') - ... 38 | % 2*imfilter(I, D, 'replicate', 'same') - 2*I) - alpha*cmtx; 39 | % A22 = I.*(imfilter(I, D2', 'replicate', 'same') - ... 40 | % 2*imfilter(I, D', 'replicate', 'same') - 2*I) - alpha*cmtx; 41 | % A12 = I.*(imfilter(I, M, 'replicate', 'same') - ... 42 | % imfilter(I, D, 'replicate', 'same')-imfilter(I, D', 'replicate', 'same') + I); 43 | % 44 | % DetA = A11.*A22-A12.*A12; 45 | % 46 | % B11 = A22./DetA; 47 | % B12 = -A12./DetA; 48 | % B22 = A11./DetA; 49 | % 50 | -------------------------------------------------------------------------------- /horn_schunk_estimator.m: -------------------------------------------------------------------------------- 1 | function [u,v] = horn_schunk_estimator(Ix, Iy, It, lambda, tol, maxnum) 2 | % 3 | % Ix: partial derivative for x-axis 4 | % Iy: partial derivative for y-axis 5 | % It: partial derivative for time t 6 | % lambda: regularization parameter 7 | % nb: the neighborhood information 8 | % 9 | % 10 | 11 | [r,c]=size(Ix); 12 | 13 | %------------------------------------------------------------------% 14 | chorizontal = [3, ones(1, c-2)*8, 3]; 15 | cvertical = [3; ones(r-2,1)*8; 3]; 16 | cmtx = 8*ones(r,c); cmtx(1,:)=chorizontal;cmtx(r,:)=chorizontal;cmtx(:,1)=cvertical;cmtx(:,c)=cvertical; 17 | 18 | uv = (Ix.*Iy)./(cmtx.*(Ix.^2+Iy.^2)+lambda*cmtx.^2); 19 | u1 = (Iy.^2+lambda*cmtx)./(cmtx.*(Ix.^2+Iy.^2)+lambda*cmtx.^2); 20 | u2 = (Ix.*It)./(Ix.^2+Iy.^2+lambda*cmtx); 21 | v1 = (Ix.^2+lambda*cmtx)./(cmtx.*(Ix.^2+Iy.^2)+lambda*cmtx.^2); 22 | v2 = (Iy.*It)./(Ix.^2+Iy.^2+lambda*cmtx); 23 | %------------------------------------------------------------------% 24 | %---------------- Initialize the parameters -----------------------% 25 | k=0; 26 | total_error=100000000; 27 | u = zeros(r,c); 28 | v = zeros(r,c); 29 | %------------------------------------------------------------------% 30 | while total_error > tol & k < maxnum 31 | total_error 32 | for n=1:c 33 | for m=1:r 34 | if n==1 35 | if m==1 36 | tmpu = u(m+1,n)+u(m,n+1)+u(m+1,n+1); 37 | tmpv = v(m+1,n)+v(m,n+1)+v(m+1,n+1); 38 | elseif m==r 39 | tmpu = u(m-1,n)+u(m,n+1)+u(m-1,n+1); 40 | tmpv = v(m-1,n)+v(m,n+1)+v(m-1,n+1); 41 | else 42 | tmpu = u(m-1,n)+u(m+1,n)+u(m-1,n+1)+u(m,n+1)+u(m+1,n+1); 43 | tmpv = v(m-1,n)+v(m+1,n)+v(m-1,n+1)+v(m,n+1)+v(m+1,n+1); 44 | end 45 | elseif n==c 46 | if m==1 47 | tmpu = u(m+1,n)+u(m,n-1)+u(m+1,n-1); 48 | tmpv = v(m+1,n)+v(m,n-1)+v(m+1,n-1); 49 | elseif m==r 50 | tmpu = u(m-1,n)+u(m,n-1)+u(m-1,n-1); 51 | tmpv = v(m-1,n)+v(m,n-1)+v(m-1,n-1); 52 | else 53 | tmpu = u(m-1,n)+u(m+1,n)+u(m-1,n-1)+u(m,n-1)+u(m+1,n-1); 54 | tmpv = v(m-1,n)+v(m+1,n)+v(m-1,n-1)+v(m,n-1)+v(m+1,n-1); 55 | end 56 | else 57 | if m==1 58 | tmpu = u(m,n-1)+u(m,n+1)+u(m+1,n-1)+u(m+1,n)+u(m+1,n+1); 59 | tmpv = v(m,n-1)+v(m,n+1)+v(m+1,n-1)+v(m+1,n)+v(m+1,n+1); 60 | elseif m==r 61 | tmpu = u(m,n-1)+u(m,n+1)+u(m-1,n-1)+u(m-1,n)+u(m-1,n+1); 62 | tmpv = v(m,n-1)+v(m,n+1)+v(m-1,n-1)+v(m-1,n)+v(m-1,n+1); 63 | else 64 | tmpu = u(m-1,n-1)+u(m-1,n)+u(m-1,n+1)+u(m,n-1)+u(m,n+1)+u(m+1,n-1)+u(m+1,n)+u(m+1,n+1); 65 | tmpv = v(m-1,n-1)+v(m-1,n)+v(m-1,n+1)+v(m,n-1)+v(m,n+1)+v(m+1,n-1)+v(m+1,n)+v(m+1,n+1); 66 | end 67 | end 68 | unew(m,n) = u1(m,n)*tmpu - uv(m,n)*tmpv - u2(m,n); 69 | vnew(m,n) = v1(m,n)*tmpv - uv(m,n)*tmpu - v2(m,n); 70 | end 71 | end 72 | total_error = (norm(unew-u,'fro')+norm(vnew-v,'fro'))/(r*c); 73 | u = unew; 74 | v = vnew; 75 | k=k+1 76 | end -------------------------------------------------------------------------------- /invariant2_factor.m: -------------------------------------------------------------------------------- 1 | function [QQ]=invariant2_factor(Vx, Vy, factor_x, factor_y) 2 | % factor_x: converting factor from pixel to m (m/pixel) in x 3 | % factor_y: converting factor from pixel to m (m/pixel) in y 4 | 5 | % Vx = imfilter(Vx, [1 1 1 1 1]'*[1 1 1 1 1]/25,'symmetric'); 6 | % Vy = imfilter(Vy, [1 1 1 1 1]'*[1,1 1 1,1]/25,'symmetric'); 7 | 8 | dx=1; 9 | D = [0, -1, 0; 0,0,0; 0,1,0]/2; %%% partial derivative 10 | Vx_x = imfilter(Vx, D'/dx, 'symmetric', 'same')/factor_x; 11 | Vx_y = imfilter(Vx, D/dx, 'symmetric', 'same')/factor_y; 12 | 13 | Vy_x = imfilter(Vy, D'/dx, 'symmetric', 'same')/factor_x; 14 | Vy_y = imfilter(Vy, D/dx, 'symmetric', 'same')/factor_y; 15 | 16 | 17 | [M,N]=size(Vx); 18 | 19 | for m=1:M 20 | for n=1:N 21 | u(1,1)=Vx_x(m,n); 22 | u(1,2)=Vx_y(m,n); 23 | u(2,1)=Vy_x(m,n); 24 | u(2,2)=Vy_y(m,n); 25 | 26 | for i=1:2 27 | for j=1:2 28 | S(i,j)=(u(i,j)+u(j,i))/2; 29 | Q(i,j)=(u(i,j)-u(j,i))/2; 30 | end 31 | end 32 | 33 | QQ(m,n)=(trace(Q*Q')-trace(S*S'))/2; 34 | 35 | 36 | % lambda1(m,n)=max(d); 37 | % lambda2(m,n)=min(d); 38 | end 39 | end 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /laplacian.m: -------------------------------------------------------------------------------- 1 | function delu = laplacian(u,h) 2 | % 3 | % u: Given image 4 | % h: step size 5 | % 6 | 7 | H = [1, 1, 1; 1,0,1;1,1,1]; 8 | %You could also choose (which seems more natural) 9 | % H = [0, 1, 0; 1,0,1;0,1,0]; 10 | delu = -u.*imfilter(ones(size(u)), H/(h*h), 'same') + imfilter(u, H/(h*h), 'same'); -------------------------------------------------------------------------------- /liu_shen_estimator.m: -------------------------------------------------------------------------------- 1 | function [u,v,error] = liu_shen_estimator(I0, I1, f, dx, dt, lambda, tol, maxnum, u0, v0) 2 | % 3 | % I: intensity function 4 | % Ix: partial derivative for x-axis 5 | % Iy: partial derivative for y-axis 6 | % It: partial derivative for time t 7 | % f: related all boundary assumption 8 | % lambda: regularization parameter 9 | % nb: the neighborhood information 10 | % 11 | %-------------------------------------------------------------------% 12 | D = [0, -1, 0; 0,0,0; 0,1,0]/2; %%% partial derivative 13 | M = [1, 0, -1; 0,0,0;-1,0,1]/4; %%% mixed partial derivatives 14 | F = [0, 1, 0; 0,0,0;0,1,0]; %%% average 15 | D2 = [0, 1, 0; 0,-2,0;0,1,0]; %%% partial derivative 16 | H = [1, 1, 1; 1,0,1;1,1,1]; 17 | %------------------------------------------------------------------% 18 | %------------------------------------------------------------------% 19 | IIx = I0.*imfilter(I0, D/dx, 'replicate', 'same'); 20 | IIy = I0.*imfilter(I0, D'/dx, 'replicate', 'same'); 21 | II = I0.*I0; 22 | Ixt = I0.*imfilter((I1-I0)/dt-f, D/dx, 'replicate', 'same'); 23 | Iyt = I0.*imfilter((I1-I0)/dt-f, D'/dx, 'replicate', 'same'); 24 | 25 | 26 | %------------------------------------------------------------------% 27 | %---------------- Initialize the parameters -----------------------% 28 | k=0; 29 | total_error=100000000; 30 | u=u0; 31 | v=v0; 32 | 33 | [r,c]=size(I1); 34 | 35 | %------------------------------------------------------------------% 36 | [B11, B12, B22] = generate_invmatrix(I0, lambda, dx); 37 | error=[]; 38 | while total_error > tol & k < maxnum 39 | total_error 40 | bu = 2*IIx.*imfilter(u, D/dx, 'replicate', 'same')+ ... 41 | IIx.*imfilter(v, D'/dx, 'replicate', 'same')+ ... 42 | IIy.*imfilter(v, D/dx, 'replicate', 'same') + ... 43 | II.*imfilter(u, F/(dx*dx), 'replicate', 'same')+ ... 44 | II.*imfilter(v, M/(dx*dx), 'replicate', 'same') + ... 45 | lambda*imfilter(u, H/(dx*dx), 'same')+Ixt; 46 | 47 | bv = IIy.*imfilter(u, D/dx, 'replicate', 'same') + ... 48 | IIx.*imfilter(u, D'/dx, 'replicate', 'same') + ... 49 | 2*IIy.*imfilter(v, D'/dx, 'replicate', 'same')+ ... 50 | II.*imfilter(u, M/(dx*dx), 'replicate', 'same') + ... 51 | II.*imfilter(v, F'/(dx*dx), 'replicate', 'same')+ ... 52 | lambda*imfilter(v, H/(dx*dx), 'same')+Iyt; 53 | 54 | unew = -(B11.*bu+B12.*bv); 55 | vnew = -(B12.*bu+B22.*bv); 56 | total_error = (norm(unew-u,'fro')+norm(vnew-v,'fro'))/(r*c) 57 | u = unew; 58 | v = vnew; 59 | error=[error; total_error]; 60 | k=k+1 61 | end -------------------------------------------------------------------------------- /plots_set_1.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | %% Show the pre-processed images in initial estimation 4 | figure(1); 5 | %clims=[1 250]; 6 | %imagesc(uint8(I_region1),clims); 7 | imagesc(uint8(I_region1)); 8 | colormap('gray') 9 | axis('image') 10 | title('Downsampled Image 1'); 11 | xlabel('x (pixels)'); 12 | ylabel('y (pixels)'); 13 | 14 | figure(2); 15 | %imagesc(uint8(I_region2),clims); 16 | imagesc(uint8(I_region2)); 17 | colormap('gray') 18 | axis('image') 19 | title('Downsampled Image 2'); 20 | xlabel('x (pixels)'); 21 | ylabel('y (pixels)'); 22 | 23 | 24 | % plot initial velocity vector field and streamlines 25 | figure(3); 26 | gx=30; offset=1; 27 | h = vis_flow (ux0, uy0, gx, offset, 3, 'm'); 28 | set(h, 'Color', 'red'); 29 | xlabel('x (pixels)'); 30 | ylabel('y (pixels)'); 31 | axis image; 32 | set(gca,'YDir','reverse'); 33 | title('Coarse-Grained Velocity Field'); 34 | 35 | 36 | % plot streamlines 37 | figure(4); 38 | [m,n]=size(ux0); 39 | [x,y]=meshgrid(1:n,1:m); 40 | dn=10; 41 | dm=10; 42 | [sx,sy]=meshgrid(1:dn:n,1:dm:m); 43 | h=streamslice(x, y, ux0, uy0, 4); 44 | set(h, 'Color', 'blue'); 45 | xlabel('x (pixels)'); 46 | ylabel('y (pixels)'); 47 | axis image; 48 | set(gca,'YDir','reverse'); 49 | title('Coarse-Grained Streamlines'); 50 | 51 | 52 | 53 | %% Plot the original images 54 | figure(10); 55 | imagesc(Im1); 56 | xlabel('x (pixels)'); 57 | ylabel('y (pixels)'); 58 | axis image; 59 | colormap('gray'); 60 | title('Image 1'); 61 | xlabel('x (pixels)'); 62 | ylabel('y (pixels)'); 63 | 64 | figure(11); 65 | imagesc(Im2); 66 | xlabel('x (pixels)'); 67 | ylabel('y (pixels)'); 68 | axis image; 69 | colormap('gray'); 70 | title('Image 2'); 71 | xlabel('x (pixels)'); 72 | ylabel('y (pixels)'); 73 | 74 | %% Plot refined velocity vector field 75 | figure(12); 76 | gx=50; offset=1; 77 | h = vis_flow (ux, uy, gx, offset, 5, 'm'); 78 | set(h, 'Color', 'red'); 79 | xlabel('x (pixels)'); 80 | ylabel('y (pixels)'); 81 | axis image; 82 | set(gca,'YDir','reverse'); 83 | title('Refined Velocity Field'); 84 | 85 | 86 | % plot streamlines 87 | figure(13); 88 | [m,n]=size(ux); 89 | [x,y]=meshgrid(1:n,1:m); 90 | dn=10; 91 | dm=10; 92 | [sx,sy]=meshgrid(1:dn:n,1:dm:m); 93 | h=streamslice(x, y, ux, uy, 4); 94 | set(h, 'Color', 'blue'); 95 | xlabel('x (pixels)'); 96 | ylabel('y (pixels)'); 97 | axis image; 98 | set(gca,'YDir','reverse'); 99 | title('Refined Streamlines'); 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /plots_set_2.asv: -------------------------------------------------------------------------------- 1 | 2 | % calculate the velocity magnitude 3 | u_mag=(ux.^2+uy.^2).^0.5; 4 | u_max=max(max(u_mag)); 5 | u_mag=u_mag/u_max; 6 | 7 | % calculate vorticity 8 | vor=vorticity(ux, uy); 9 | vor_max=max(max(abs(vor))); 10 | vor=vor/vor_max; 11 | 12 | 13 | % calculate the 2nd invariant 14 | Q=invariant2_factor(ux, uy, 1, 1); 15 | 16 | 17 | % plot velocity magnitude field 18 | figure(20); 19 | ulims=[0, 1]; 20 | imagesc(u_mag,ulims); 21 | xlabel('x (pixels)'); 22 | ylabel('y (pixels)'); 23 | axis image; 24 | set(gca,'YDir','reverse'); 25 | title('Velocity Magnitude Field'); 26 | colorbar; 27 | hold on; 28 | 29 | % plot streamlines 30 | figure(20); 31 | [m,n]=size(ux); 32 | [x,y]=meshgrid(1:n,1:m); 33 | dn=10; 34 | dm=10; 35 | [sx,sy]=meshgrid(1:dn:n,1:dm:m); 36 | h=streamslice(x, y, ux, uy, 4); 37 | set(h, 'Color', 'yellow'); 38 | hold off; 39 | 40 | 41 | % plot Vorticity field 42 | figure(21); 43 | vlims=[-1, 1]; 44 | imagesc(vor,vlims); 45 | xlabel('x (pixels)'); 46 | ylabel('y (pixels)'); 47 | axis image; 48 | set(gca,'YDir','reverse'); 49 | title('Vorticity Field'); 50 | colorbar; 51 | hold on; 52 | 53 | % plot streamlines 54 | figure(21); 55 | [m,n]=size(ux); 56 | [x,y]=meshgrid(1:n,1:m); 57 | dn=10; 58 | dm=10; 59 | [sx,sy]=meshgrid(1:dn:n,1:dm:m); 60 | h=streamslice(x, y, ux, uy, 4); 61 | set(h, 'Color', 'blue'); 62 | hold off; 63 | 64 | 65 | % plot Vorticity field 66 | figure(22); 67 | vlims=[-1, 1]; 68 | imagesc(vor,vlims); 69 | xlabel('x (pixels)'); 70 | ylabel('y (pixels)'); 71 | axis image; 72 | set(gca,'YDir','reverse'); 73 | title('Vorticity Field'); 74 | colorbar; 75 | hold on; 76 | 77 | % Plot refined velocity vector field 78 | figure(22); 79 | gx=50; offset=1; 80 | h = vis_flow (ux, uy, gx, offset, 3, 'm'); 81 | set(h, 'Color', 'black'); 82 | xlabel('x (pixels)'); 83 | ylabel('y (pixels)'); 84 | axis image; 85 | set(gca,'YDir','reverse'); 86 | hold off; 87 | 88 | % plot Vorticity field 89 | figure(23); 90 | vlims=[-1, 1]; 91 | imagesc(u_ma,vlims); 92 | xlabel('x (pixels)'); 93 | ylabel('y (pixels)'); 94 | axis image; 95 | set(gca,'YDir','reverse'); 96 | title('Vorticity Field'); 97 | colorbar; 98 | hold on; 99 | 100 | % Plot refined velocity vector field 101 | figure(22); 102 | gx=50; offset=1; 103 | h = vis_flow (ux, uy, gx, offset, 3, 'm'); 104 | set(h, 'Color', 'black'); 105 | xlabel('x (pixels)'); 106 | ylabel('y (pixels)'); 107 | axis image; 108 | set(gca,'YDir','reverse'); 109 | hold off; 110 | 111 | 112 | 113 | 114 | 115 | % plot Q field 116 | figure(24); 117 | Qlims=[0, 0.1]; 118 | imagesc(Q,Qlims); 119 | xlabel('x (pixels)'); 120 | ylabel('y (pixels)'); 121 | axis image; 122 | set(gca,'YDir','reverse'); 123 | title('Q Field'); 124 | colorbar; 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /plots_set_2.m: -------------------------------------------------------------------------------- 1 | 2 | % calculate the velocity magnitude 3 | u_mag=(ux.^2+uy.^2).^0.5; 4 | u_max=max(max(u_mag)); 5 | u_mag=u_mag/u_max; 6 | 7 | % calculate vorticity 8 | vor=vorticity(ux, uy); 9 | vor_max=max(max(abs(vor))); 10 | vor=vor/vor_max; 11 | 12 | 13 | % calculate the 2nd invariant 14 | Q=invariant2_factor(ux, uy, 1, 1); 15 | 16 | 17 | % plot velocity magnitude field 18 | figure(20); 19 | ulims=[0, 1]; 20 | imagesc(u_mag,ulims); 21 | xlabel('x (pixels)'); 22 | ylabel('y (pixels)'); 23 | axis image; 24 | set(gca,'YDir','reverse'); 25 | title('Velocity Magnitude Field'); 26 | colorbar; 27 | hold on; 28 | 29 | % plot streamlines 30 | figure(20); 31 | [m,n]=size(ux); 32 | [x,y]=meshgrid(1:n,1:m); 33 | dn=10; 34 | dm=10; 35 | [sx,sy]=meshgrid(1:dn:n,1:dm:m); 36 | h=streamslice(x, y, ux, uy, 4); 37 | set(h, 'Color', 'yellow'); 38 | hold off; 39 | 40 | 41 | % plot Vorticity field 42 | figure(21); 43 | vlims=[-1, 1]; 44 | imagesc(vor,vlims); 45 | xlabel('x (pixels)'); 46 | ylabel('y (pixels)'); 47 | axis image; 48 | set(gca,'YDir','reverse'); 49 | title('Vorticity Field'); 50 | colorbar; 51 | hold on; 52 | 53 | % plot streamlines 54 | figure(21); 55 | [m,n]=size(ux); 56 | [x,y]=meshgrid(1:n,1:m); 57 | dn=10; 58 | dm=10; 59 | [sx,sy]=meshgrid(1:dn:n,1:dm:m); 60 | h=streamslice(x, y, ux, uy, 4); 61 | set(h, 'Color', 'blue'); 62 | hold off; 63 | 64 | 65 | % plot Vorticity field 66 | figure(22); 67 | vlims=[-1, 1]; 68 | imagesc(vor,vlims); 69 | xlabel('x (pixels)'); 70 | ylabel('y (pixels)'); 71 | axis image; 72 | set(gca,'YDir','reverse'); 73 | title('Vorticity Field'); 74 | colorbar; 75 | hold on; 76 | 77 | % Plot refined velocity vector field 78 | figure(22); 79 | gx=50; offset=1; 80 | h = vis_flow (ux, uy, gx, offset, 3, 'm'); 81 | set(h, 'Color', 'black'); 82 | xlabel('x (pixels)'); 83 | ylabel('y (pixels)'); 84 | axis image; 85 | set(gca,'YDir','reverse'); 86 | hold off; 87 | 88 | % plot Vorticity field 89 | figure(23); 90 | vlims=[0, 1]; 91 | imagesc(u_mag,vlims); 92 | xlabel('x (pixels)'); 93 | ylabel('y (pixels)'); 94 | axis image; 95 | set(gca,'YDir','reverse'); 96 | title('Velocity Magnitue Field'); 97 | colorbar; 98 | hold on; 99 | 100 | % Plot refined velocity vector field 101 | figure(23); 102 | gx=50; offset=1; 103 | h = vis_flow (ux, uy, gx, offset, 3, 'm'); 104 | set(h, 'Color', 'black'); 105 | xlabel('x (pixels)'); 106 | ylabel('y (pixels)'); 107 | axis image; 108 | set(gca,'YDir','reverse'); 109 | hold off; 110 | 111 | 112 | % plot Q field 113 | figure(24); 114 | Qlims=[0, 0.1]; 115 | imagesc(Q,Qlims); 116 | xlabel('x (pixels)'); 117 | ylabel('y (pixels)'); 118 | axis image; 119 | set(gca,'YDir','reverse'); 120 | title('Q Field'); 121 | colorbar; 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /pre_processing_a.m: -------------------------------------------------------------------------------- 1 | function [I1,I2] = pre_processing_a(Im1,Im2,scale_im,size_filter) 2 | 3 | 4 | Im1=double(Im1); 5 | Im2=double(Im2); 6 | 7 | I1=Im1; 8 | I2=Im2; 9 | 10 | I1=imresize(I1,scale_im); 11 | I2=imresize(I2,scale_im); 12 | 13 | 14 | % applying a Gaussian filter to images 15 | mask_size=size_filter; 16 | %mask_size=4; 17 | std=mask_size*0.62; 18 | H1=fspecial('gaussian',mask_size,std); 19 | H2=fspecial('gaussian',mask_size,std); 20 | I1=(imfilter(I1,H1)+imfilter(I1,H2))/2; 21 | I2=(imfilter(I2,H1)+imfilter(I2,H2))/2; 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /rescaling_intensity.m: -------------------------------------------------------------------------------- 1 | function [I1,I2] = rescaling_intensity(Im1,Im2,max_intensity_value) 2 | 3 | Imax1=max(max(Im1)); 4 | Imin1=min(min(Im1)); 5 | Im1a=(Im1-Imin1)/(Imax1-Imin1); 6 | 7 | Imax2=max(max(Im2)); 8 | Imin2=min(min(Im2)); 9 | Im2a=(Im2-Imin2)/(Imax2-Imin2); 10 | 11 | Im1=Im1a*max_intensity_value; 12 | Im2=Im2a*max_intensity_value; 13 | 14 | I1=double(Im1); 15 | I2=double(Im2); 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /shift_image_fun_refine_1.m: -------------------------------------------------------------------------------- 1 | function [Im1_shift,uxI,uyI]=shift_image_fun_refine_1(ux,uy,Im1,Im2) 2 | 3 | % ux and uy are the initial velocity fields in pixels/unit time in coarse image 4 | % Im1 and Im2 are finer images at the times 1 and 2 5 | % uxI and uyI are the interpolated velocity fields in pixels/unit time in finer image 6 | % cut_vaule is the value of displacement between uses of the direct shift 7 | % method and optical flow shift method (such as 5 pixels) 8 | % Im1_shite is the shifted image from Im1 based on uxI and uyI 9 | 10 | Im1=double(Im1); 11 | Im2=double(Im2); 12 | ux=double(ux); 13 | uy=double(uy); 14 | 15 | 16 | [m0,n0]=size(ux); 17 | % normalized size of coarse image 18 | x0_normalized=[1:n0]/n0; 19 | y0_normalized=[1:m0]/m0; 20 | [X,Y] = meshgrid(x0_normalized,y0_normalized); 21 | 22 | [m1,n1]=size(Im1); 23 | % normalized size of finer image 24 | x1_normalized=[1:n1]/n1; 25 | y1_normalized=[1:m1]/m1; 26 | 27 | % obtain interpolated velocity field in the finer image 28 | [XI,YI] = meshgrid(x1_normalized,y1_normalized); 29 | % uxI = (n1/n0)*interp2(X,Y,ux,XI,YI); % pixels/unit time in finer image 30 | % uyI = (m1/m0)*interp2(X,Y,uy,XI,YI); % pixels/unit time in finer image 31 | 32 | uxI = (n1/n0)*imresize(ux,[length(y1_normalized) length(x1_normalized)]); % pixels/unit time in finer image 33 | uyI = (m1/m0)*imresize(uy,[length(y1_normalized) length(x1_normalized)]); % pixels/unit time in finer image 34 | 35 | 36 | % generate a shifted image from Im1 based on the velocity field that is 37 | % rounded 38 | 39 | Im1_shift0=Im2; 40 | for i=1:m1 41 | for j=1:n1 42 | i_shift=i+round(uyI(i,j)); 43 | j_shift=j+round(uxI(i,j)); 44 | if (i_shift<=m1) && (i_shift >=1) && (j_shift<=n1) && (j_shift>=1) 45 | Im1_shift0(i_shift,j_shift)=Im1(i,j); 46 | else 47 | Im1_shift0(i,j)=Im1(i,j); 48 | end 49 | end 50 | end 51 | 52 | 53 | Im3=Im1_shift0; 54 | Im1_shift1=Im3; 55 | duxI=uxI-round(uxI); 56 | duyI=uyI-round(uyI); 57 | 58 | mask_size=10; 59 | std=0.6*mask_size; 60 | H1=fspecial('gaussian',mask_size,std); 61 | duxI=imfilter(duxI,H1); 62 | duyI=imfilter(duyI,H1); 63 | 64 | 65 | dx=1; 66 | dy=1; 67 | dt=1; 68 | 69 | for i=1:(m1-1) 70 | for j=1:(n1-1) 71 | term1(i,j)=(Im3(i,j+dx)*duxI(i,j+dx)-Im3(i,j)*duxI(i,j))/dx; 72 | term2(i,j)=(Im3(i+dy,j)*duyI(i+dy,j)-Im3(i,j)*duyI(i,j))/dy; 73 | Im1_shift1(i,j)=Im3(i,j)-(term1(i,j)+term2(i,j))*dt; 74 | end 75 | end 76 | 77 | 78 | Im1_shift=uint8(Im1_shift1); 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /vis_flow.m: -------------------------------------------------------------------------------- 1 | % Quiver, with subsampling 2 | % 3 | % Usage: [Ox,Oy] = vis_flow (Vx, Vy, gx, offset, mag, col) 4 | % or H = vis_flow (Vx, Vy, gx, offset, mag, col) 5 | % 6 | 7 | function [Ox,Oy] = vis_flow (VVx, VVy, gx, offset, mag, col); 8 | 9 | if (nargin<3) 10 | gx = 25; 11 | end 12 | if (nargin<4) 13 | offset = 0; 14 | end 15 | if (nargin<5) 16 | mag = 1; 17 | end 18 | if (nargin<6) 19 | col = 'b'; 20 | end 21 | 22 | [sy sx] = size(VVx); 23 | if (gx==0) 24 | jmp = 1; 25 | else 26 | jmp = floor(sx/gx); 27 | jmp = jmp + (jmp==0); 28 | end 29 | 30 | indx = (offset+1):jmp:sx; 31 | c = 1; 32 | CX = []; 33 | CY = []; 34 | for j=(1+offset):jmp:sy 35 | Vx(c,:) = VVx(j,indx); 36 | Vy(c,:) = VVy(j,indx); 37 | CX(c,:) = indx; 38 | %CY(c,:) = ones(size(indx)).*(sy-j+1); 39 | CY(c,:) = ones(size(indx)).*j; 40 | c = c+1; 41 | end 42 | 43 | if (isnan(Vx(1,1))) 44 | Vx(1,1) = 1; 45 | Vy(1,1) = 0; 46 | CX(1,1) = 1; 47 | CY(1,1) = 1; 48 | end 49 | 50 | M = ~isnan(Vx) & ~isnan(Vy); 51 | H = quiver (CX(M), CY(M), Vx(M), Vy(M), mag); 52 | s = size(VVx); 53 | axis ([0 s(2) 0 s(1)]); 54 | set (H, 'Color', col); 55 | 56 | switch nargout 57 | case 0 58 | clear Ox; 59 | clear Oy; 60 | case 1 61 | Ox = H; 62 | otherwise 63 | Ox = Vx; 64 | Oy = Vy; 65 | end 66 | 67 | -------------------------------------------------------------------------------- /vortex_pair_particles_1.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianshu-Liu/OpenOpticalFlow/d802f56299ead7ff34118dbc144a115272138fa2/vortex_pair_particles_1.tif -------------------------------------------------------------------------------- /vortex_pair_particles_2.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianshu-Liu/OpenOpticalFlow/d802f56299ead7ff34118dbc144a115272138fa2/vortex_pair_particles_2.tif -------------------------------------------------------------------------------- /vorticity.m: -------------------------------------------------------------------------------- 1 | function [omega]=vorticity(Vx, Vy) 2 | 3 | % Vx = imfilter(Vx, [1 1 1 1 1]'*[1 1 1 1 1]/25,'symmetric'); 4 | % Vy = imfilter(Vy, [1 1 1 1 1]'*[1,1 1 1,1]/25,'symmetric'); 5 | 6 | dx=1; 7 | D = [0, -1, 0; 0,0,0; 0,1,0]/2; %%% partial derivative 8 | Vy_x = imfilter(Vy, D'/dx, 'symmetric', 'same'); 9 | Vx_y = imfilter(Vx, D/dx, 'symmetric', 'same'); 10 | omega=Vy_x-Vx_y; 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /vorticity_factor.m: -------------------------------------------------------------------------------- 1 | function [omega]=vorticity_factor(Vx, Vy, factor_x, factor_y) 2 | % factor_x: converting factor from pixel to m (m/pixel) in x 3 | % factor_y: converting factor from pixel to m (m/pixel) in y 4 | 5 | % Vx = imfilter(Vx, [1 1 1 1 1]'*[1 1 1 1 1]/25,'symmetric'); 6 | % Vy = imfilter(Vy, [1 1 1 1 1]'*[1,1 1 1,1]/25,'symmetric'); 7 | 8 | dx=1; 9 | D = [0, -1, 0; 0,0,0; 0,1,0]/2; %%% partial derivative 10 | Vy_x = imfilter(Vy, D'/dx, 'symmetric', 'same'); 11 | Vx_y = imfilter(Vx, D/dx, 'symmetric', 'same'); 12 | omega=(Vy_x/factor_x-Vx_y/factor_y); 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /wall_jet_1.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianshu-Liu/OpenOpticalFlow/d802f56299ead7ff34118dbc144a115272138fa2/wall_jet_1.tif -------------------------------------------------------------------------------- /wall_jet_2.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tianshu-Liu/OpenOpticalFlow/d802f56299ead7ff34118dbc144a115272138fa2/wall_jet_2.tif --------------------------------------------------------------------------------