├── horn-schunck ├── Im6.png ├── Im7.png ├── video.mpg ├── showOF.m ├── README.txt ├── derivative.m ├── HS.m ├── imHS.m └── vidHS.m ├── lucas-kanade ├── Im6.png ├── Im7.png ├── video.mpg ├── showOF.m ├── README.txt ├── derivative.m ├── imLK.m ├── vidLK.m └── LK.m ├── README.md └── LICENSE /horn-schunck/Im6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuanhtuan1012/determining-optical-flow/HEAD/horn-schunck/Im6.png -------------------------------------------------------------------------------- /horn-schunck/Im7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuanhtuan1012/determining-optical-flow/HEAD/horn-schunck/Im7.png -------------------------------------------------------------------------------- /horn-schunck/video.mpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuanhtuan1012/determining-optical-flow/HEAD/horn-schunck/video.mpg -------------------------------------------------------------------------------- /lucas-kanade/Im6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuanhtuan1012/determining-optical-flow/HEAD/lucas-kanade/Im6.png -------------------------------------------------------------------------------- /lucas-kanade/Im7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuanhtuan1012/determining-optical-flow/HEAD/lucas-kanade/Im7.png -------------------------------------------------------------------------------- /lucas-kanade/video.mpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuanhtuan1012/determining-optical-flow/HEAD/lucas-kanade/video.mpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # determining-optical-flow 2 | Determining optical flow by using Horn-Schunck method and Lucas-Kanade method 3 | -------------------------------------------------------------------------------- /lucas-kanade/showOF.m: -------------------------------------------------------------------------------- 1 | function showOF(I, C, U, V) 2 | % function showOF draws the optical flow from flow velocities U, V 3 | % and suitable corners C on image I 4 | 5 | imshow(I); hold on; 6 | quiver(C(:,1), C(:,2), -U, -V, 1, 'r'); hold off; -------------------------------------------------------------------------------- /horn-schunck/showOF.m: -------------------------------------------------------------------------------- 1 | function showOF(U, V) 2 | % function showOF shows the optical flow from flow velocities matrix U, V 3 | 4 | [l,c] = size(U); 5 | d = 5; % step 6 | IndX = 1:d:l; 7 | IndY = 1:d:c; 8 | [X,Y] = meshgrid(IndY, IndX); 9 | U1 = U(IndX, IndY); 10 | V1 = V(IndX, IndY); 11 | quiver(X, Y, U1(end:-1:1,:), V1(end:-1:1,:), 3); -------------------------------------------------------------------------------- /lucas-kanade/README.txt: -------------------------------------------------------------------------------- 1 | - To find optical flow of images use 1 of 2 commands: 2 | imLK(ws) - ws is window size. 3 | or: 4 | imLK - in this case, ws gets default values 15. 5 | 6 | - To find optical flow of given video use 1 of 2 commands: 7 | vidLK(ws) - ws is window size. 8 | or: 9 | vidLK - in this case, ws gets default values 15. 10 | -------------------------------------------------------------------------------- /horn-schunck/README.txt: -------------------------------------------------------------------------------- 1 | - To find optical flow of images use 1 of 2 commands: 2 | imHS(alpha, N) - alpha is weighting factor, N is iteration number 3 | or: 4 | imHS - in this case, alpha and N get default values: alpha = 0.01, N = 512. 5 | 6 | - To find optical flow of given video use 1 of 2 commands: 7 | vidHS(alpha, N) - alpha is weighting factor, N is iteration number 8 | or: 9 | vidHS - in this case, alpha and N get default values: alpha = 0.5, N = 128. 10 | -------------------------------------------------------------------------------- /horn-schunck/derivative.m: -------------------------------------------------------------------------------- 1 | function [Ex, Ey, Et] = derivative(Im1, Im2) 2 | % function DERIVATIVE computes partial derivatives Ex, Ey, Et 3 | % of a sequence of 2 images Im1, Im2 of double class. 4 | 5 | % kernels for convolution 6 | Kx = 0.25 * [-1 1; -1 1]; 7 | Ky = 0.25 * [-1 -1; 1 1]; 8 | Kt = 0.25 * [-1 -1; -1 -1]; % kt1 = Kt, kt2 = -Kt 9 | 10 | % compute derivatives 11 | Ex = conv2(Im1, Kx, 'same') + conv2(Im2, Kx, 'same'); 12 | Ey = conv2(Im1, Ky, 'same') + conv2(Im2, Ky, 'same'); 13 | Et = conv2(Im1, Kt, 'same') + conv2(Im2, -Kt, 'same'); -------------------------------------------------------------------------------- /lucas-kanade/derivative.m: -------------------------------------------------------------------------------- 1 | function [Ex, Ey, Et] = derivative(Im1, Im2) 2 | % function DERIVATIVE computes partial derivatives Ex, Ey, Et 3 | % of a sequence of 2 images Im1, Im2 of double class. 4 | 5 | % kernels for convolution 6 | Kx = 0.25 * [-1 1; -1 1]; 7 | Ky = 0.25 * [-1 -1; 1 1]; 8 | Kt = 0.25 * [-1 -1; -1 -1]; % kt1 = Kt, kt2 = -Kt 9 | 10 | % compute derivatives 11 | Ex = conv2(Im1, Kx, 'same') + conv2(Im2, Kx, 'same'); 12 | Ey = conv2(Im1, Ky, 'same') + conv2(Im2, Ky, 'same'); 13 | Et = conv2(Im1, Kt, 'same') + conv2(Im2, -Kt, 'same'); -------------------------------------------------------------------------------- /horn-schunck/HS.m: -------------------------------------------------------------------------------- 1 | function [U, V] = HS(Im1, Im2, alpha, N) 2 | % function HS computes flow velocities U, V of a sequence of 2 images 3 | % Im1, Im2 of double class based on Horn-Schunck algorithm. alpha is the 4 | % weighting factor and N is the number of iteration. 5 | 6 | % compute partial derivatives 7 | [Ex, Ey, Et] = derivative(Im1, Im2); 8 | 9 | % intial U, V 10 | [l, c] = size(Im1); 11 | U = zeros(l, c); 12 | V = zeros(l, c); 13 | 14 | K = [1/12 1/6 1/12; 1/6 -1 1/6; 1/12 1/6 1/12]; % Laplacian kernel 15 | A = alpha^2 + Ex.^2 + Ey.^2; 16 | 17 | for i = 1:N 18 | % compute U,V averages 19 | U_avg = conv2(U, K, 'same'); 20 | V_avg = conv2(V, K, 'same'); 21 | B = (Ex.*U_avg + Ey.*V_avg + Et); 22 | 23 | % compute U, V at current iteration 24 | U = U_avg - Ex.*B./A; 25 | V = V_avg - Ey.*B./A; 26 | end; -------------------------------------------------------------------------------- /lucas-kanade/imLK.m: -------------------------------------------------------------------------------- 1 | function imLK(ws) 2 | % function imLK shows optical flow of given sequence of images 3 | % computations based on the algorithm of Lucas-Kanade. 4 | % ws is the window size, by default ws = 15 5 | 6 | % clear the command window 7 | clc; 8 | 9 | %set default value to alpha, N 10 | if (nargin < 1) 11 | ws = 15; 12 | end 13 | 14 | % read images 15 | Im1 = imread('Im6.png'); 16 | Im2 = imread('Im7.png'); 17 | 18 | % compute U, V by Lucas Kanade 19 | % C is coordinates of corners in Im1 20 | Im1 = im2double(Im1); 21 | Im2 = im2double(Im2); 22 | [U, V, C] = LK(Im1, Im2, ws); 23 | 24 | % show images 25 | figure; 26 | subplot(1, 2, 1); imshow(Im1, []); title('Im6.png'); 27 | subplot(1, 2, 2); imshow(Im2, []); title('Im7.png'); 28 | 29 | % show optical flow and save it to a file 30 | figure; showOF(Im1, C, U, V); 31 | filename = sprintf('lk-%d.png', ws); 32 | print(filename, '-dpng'); -------------------------------------------------------------------------------- /horn-schunck/imHS.m: -------------------------------------------------------------------------------- 1 | function imHS(alpha, N) 2 | % function imHS shows optical flow of given sequence of images 3 | % computations based on the algorithm of Horn and Schunck. 4 | % alpha is the weighting factor, by default alpha = 0.01 5 | % N is the number of iteration, by default N = 512 6 | 7 | % clear command window 8 | clc; 9 | 10 | %set default value to alpha, N 11 | if (nargin < 1) 12 | alpha = 0.01; 13 | N = 512; 14 | elseif (nargin == 1) 15 | N = 512; 16 | end 17 | 18 | % read images 19 | Im1 = imread('Im6.png'); 20 | Im2 = imread('Im7.png'); 21 | 22 | % compute U, V by HS 23 | Im1 = im2double(Im1); 24 | Im2 = im2double(Im2); 25 | [U,V] = HS(Im1, Im2, alpha, N); 26 | 27 | % show images 28 | figure; 29 | subplot(1, 2, 1); imshow(Im1, []); title('Im6.png'); 30 | subplot(1, 2, 2); imshow(Im2, []); title('Im7.png'); 31 | 32 | % show optical flow and save it to a file 33 | figure; showOF(U, V); 34 | str = sprintf('%.5g; N = %d', alpha, N); 35 | title(strcat('\alpha = ',str)); 36 | filename = sprintf('hs-%0.5g-%d.png', alpha, N); 37 | print(filename, '-dpng'); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 VU Anh Tuan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lucas-kanade/vidLK.m: -------------------------------------------------------------------------------- 1 | function vidLK(ws) 2 | % function vidLK shows optical flow in a video 3 | % computations based on the algorithm of Lucas and Kanade. 4 | % ws is the window size, by default ws = 15 5 | 6 | % clear the command window 7 | clc; 8 | 9 | %set default value to alpha, N 10 | if (nargin < 1) 11 | ws = 15; 12 | end 13 | 14 | % read video to object 15 | vidObj = VideoReader('video.mpg'); 16 | 17 | % get first frame 18 | if hasFrame(vidObj) 19 | Fr1 = rgb2gray(readFrame(vidObj)); 20 | Fr1 = im2double(Fr1); 21 | else 22 | return 23 | end 24 | i = 0; 25 | while hasFrame(vidObj) 26 | i = i+1; 27 | Fr2 = rgb2gray(readFrame(vidObj)); % get second frame 28 | Fr2 = im2double(Fr2); 29 | 30 | % compute U, V by LK 31 | [U, V, C] = LK(Fr1, Fr2, ws); 32 | 33 | % show frames and optical flow 34 | subplot(1, 3, 1); 35 | imshow(Fr1, []); title('Frame 1'); 36 | subplot(1, 3, 2); 37 | imshow(Fr2, []); title('Frame 2'); 38 | subplot(1, 3, 3); 39 | showOF(Fr1, C, U, V); title('Optical Flow'); 40 | axis image; % set subplot same size 41 | str = sprintf('Window size = %d', ws); 42 | suptitle(strcat(str)); 43 | 44 | Fr1 = Fr2; % Fr2 becomes first frame of next sequence 45 | end -------------------------------------------------------------------------------- /horn-schunck/vidHS.m: -------------------------------------------------------------------------------- 1 | function vidHS(alpha, N) 2 | % function vidHS shows optical flow in a video 3 | % computations based on the algorithm of Horn and Schunck. 4 | % alpha is the weighting factor, by default alpha = 0.5 5 | % N is the number of iteration, by default N = 128 6 | 7 | % clear the command window 8 | clc; 9 | 10 | %set default value to alpha, N 11 | if (nargin < 1) 12 | alpha = 0.5; 13 | N = 128; 14 | elseif (nargin == 1) 15 | N = 128; 16 | end 17 | 18 | % read video to object 19 | vidObj = VideoReader('video.mpg'); 20 | 21 | % get first frame 22 | if hasFrame(vidObj) 23 | Fr1 = rgb2gray(readFrame(vidObj)); 24 | Fr1 = im2double(Fr1); 25 | else 26 | return 27 | end 28 | 29 | while hasFrame(vidObj) 30 | Fr2 = rgb2gray(readFrame(vidObj)); % get second frame 31 | Fr2 = im2double(Fr2); 32 | 33 | % compute U, V by HS 34 | [U, V] = HS(Fr1, Fr2, alpha, N); 35 | 36 | % show frames and optical flow 37 | subplot(1, 3, 1); 38 | imshow(Fr1, []); title('Frame 1'); 39 | subplot(1, 3, 2); 40 | imshow(Fr2, []); title('Frame 2'); 41 | subplot(1, 3, 3); 42 | showOF(U, V); title('Optical Flow'); 43 | axis image; % set subplot same size 44 | str = sprintf('%.5g; N = %d', alpha, N); 45 | suptitle(strcat('\alpha = ',str)); 46 | 47 | Fr1 = Fr2; % Fr2 becomes first frame of next sequence 48 | end -------------------------------------------------------------------------------- /lucas-kanade/LK.m: -------------------------------------------------------------------------------- 1 | function [U, V, C] = LK(Im1, Im2, ws) 2 | % function LK computes flow velocities U, V of a sequence of 2 images 3 | % Im1, Im2 of double class based on Lucas-Kanade method. ws is the 4 | % window size. 5 | % return (U, V) flow velocities, C coordinates of corners in Im1 6 | 7 | % find corners by Harris 8 | C = corner(Im1, 500); 9 | 10 | % mark corners in the margin as (-1, -1) 11 | [m, n] = size(Im1); 12 | w = round(ws/2); % half of windows size 13 | for i = 1:size(C, 1) 14 | x = C(i, 1); 15 | y = C(i, 2); 16 | if (x <= w) || (x >= n-w) % corners in left, right margin 17 | C(i,:) = -1; 18 | end 19 | if (y <= w) || (y >= m-w) % corner in top, bottom margin 20 | C(i,:) = -1; 21 | end 22 | end 23 | 24 | % remove corners in margins 25 | i = 0; 26 | while i < size(C, 1) 27 | i = i+1; 28 | if C(i,1) == -1 29 | C(i,:) = []; 30 | i = i - 1; 31 | end 32 | end 33 | 34 | % Lucas-Kanade constraint 35 | nc = size(C, 1); % number of suitable corners 36 | U = zeros(nc, 1); 37 | V = zeros(nc, 1); 38 | 39 | % compute partial derivatives 40 | [Ex, Ey, Et] = derivative(Im1, Im2); 41 | 42 | for i = 1:nc 43 | % get derivatives of neighborhood points 44 | x = C(i, 1); y = C(i, 2); 45 | Ix = Ex(y-w:y+w, x-w:x+w)'; 46 | Iy = Ey(y-w:y+w, x-w:x+w)'; 47 | It = Et(y-w:y+w, x-w:x+w)'; 48 | 49 | % get A, b 50 | Ix = Ix(:); Iy = Iy(:); It = It(:); 51 | A = [Ix Iy]; 52 | b = -It; 53 | 54 | % compute U, V 55 | X = pinv(A) * b; 56 | U(i) = X(1); 57 | V(i) = X(2); 58 | end --------------------------------------------------------------------------------