├── README.md └── eulerian.m /README.md: -------------------------------------------------------------------------------- 1 | eulerianmagnify 2 | =============== 3 | 4 | Quick Matlab implementation of Eulerian video magnification detailed: http://people.csail.mit.edu/mrub/vidmag/. 5 | 6 | Requires Minh Do's Laplacian pyramid toolbox available at http://www.ifp.illinois.edu/~minhdo/software/lptoolbox.tar.gz. 7 | -------------------------------------------------------------------------------- /eulerian.m: -------------------------------------------------------------------------------- 1 | % Hacked together code for implementing the colour magnifying component 2 | % of Eulerian Video Magnification: 3 | % http://people.csail.mit.edu/mrub/vidmag/ 4 | % 5 | % Only enhances the red RGB component at the moment. It can be 6 | % extended to handle all three; memory limitations on my laptop 7 | % prevents me from doing them all in one step. 8 | % 9 | % Requires Minh N. Do's laplacian pyramid toolbox: 10 | % http://www.ifp.illinois.edu/~minhdo/software/lptoolbox.tar.gz 11 | % 12 | % Copyright 2012 13 | % James Brotchie 14 | % https://github.com/brotchie/ 15 | % 16 | 17 | HOME = getenv('HOME'); 18 | LAPLACIAN_PYRAMID_TOOLBOX_PATH = [HOME filesep 'Downloads' filesep 'image']; 19 | addpath(LAPLACIAN_PYRAMID_TOOLBOX_PATH); 20 | 21 | % Video to process. 22 | VIDEO_PATH = [HOME filesep 'Downloads' filesep 'IMG_0940.MOV']; 23 | 24 | % Depth of the laplacian pyramid. 25 | NDECOMPOSITIONS = 4; 26 | 27 | % Scaling factor for bandpass filtered signal. 28 | SCALING_FACTOR_ALPHA = 5; 29 | 30 | % Type of Laplacian decomposition. 31 | DECOMPOSITION_TYPE = '9-7'; 32 | 33 | % Filter setup. 34 | FILTER_TYPE = 'butter'; 35 | FILTER_ORDER = 32; 36 | FILTER_LP_CUTOFF_HZ = 0.5; 37 | FILTER_HP_CUTOFF_HZ = 2; 38 | 39 | video = VideoReader(VIDEO_PATH); 40 | 41 | % Read video frame, we permute to flip from landscape 42 | % to portrait. 43 | frames = permute(video.read(), [2 1 3 4]); 44 | 45 | VIDEO_HEIGHT = size(frames, 1); 46 | VIDEO_WIDTH = size(frames, 2); 47 | 48 | assert(VIDEO_HEIGHT > VIDEO_WIDTH, ... 49 | 'We assume that the video width is greater than the height when padding.'); 50 | 51 | % Pad the video so it's square; laplacian pyramid toolbox requires 52 | % square inputs. 53 | PADDING = (VIDEO_HEIGHT - VIDEO_WIDTH) / 2; 54 | frames = [zeros(VIDEO_HEIGHT, PADDING, 3, size(frames,4), 'uint8') ... 55 | frames ... 56 | zeros(VIDEO_HEIGHT, PADDING , 3, size(frames,4), 'uint8')]; 57 | nFrames = size(frames, 4); 58 | 59 | % Pre-allocate memory to store red channel decompositions. 60 | decomposed = cell(NDECOMPOSITIONS+1, 1); 61 | for ii = 1:NDECOMPOSITIONS+1 62 | N = size(frames, 1) / 2^(NDECOMPOSITIONS - ii + 1); 63 | decomposed{ii} = zeros(N, N, nFrames); 64 | end 65 | 66 | % Perform the decompositions and store them in the decomposed cell 67 | % array. 68 | for ii = 1:nFrames 69 | fprintf('Decomposing frame %d of %d.\n', ii, nFrames); 70 | y = lpd(double(frames(:, :, 1, ii)), DECOMPOSITION_TYPE, NDECOMPOSITIONS); 71 | for jj = 1:NDECOMPOSITIONS 72 | decomposed{jj}(:,:,ii) = y{jj}; 73 | end 74 | end 75 | 76 | % Filter each decomposed pixel in the time domain. 77 | f = fdesign.bandpass('n,fc1,fc2', FILTER_ORDER, ... 78 | FILTER_LP_CUTOFF_HZ, FILTER_HP_CUTOFF_HZ, ... 79 | video.FrameRate); 80 | h = design(f, FILTER_TYPE); 81 | 82 | improved = cell(NDECOMPOSITIONS+1, 1); 83 | for ii = 1:NDECOMPOSITIONS+1 84 | fprintf('Band pass filtering laplacian pyramid level %d of %d.\n', ii, NDECOMPOSITIONS+1); 85 | improved{ii} = decomposed{ii} + SCALING_FACTOR_ALPHA*filter(h, decomposed{ii}, 3); 86 | end 87 | 88 | % Clear the decomposed frames to free up a bit of memory. 89 | clear decomposed; 90 | 91 | % Recompose the filtered signal. 92 | red_signal = zeros(480, 480, nFrames, 'uint8'); 93 | M = repmat(struct('cdata', zeros(size(red_signal, 1), size(red_signal, 2), 3, 'uint8'), ... 94 | 'colormap', []), [nFrames 1]); 95 | 96 | for ii = 1:nFrames 97 | fprintf('Recomposing frame %d of %d.\n', ii, nFrames); 98 | y = cellfun(@(x)x(:,:,ii), improved, 'UniformOutput', 0); 99 | signal(:,:,ii) = uint8(lpr(y, DECOMPOSITION_TYPE)); 100 | M(ii).cdata = cat(3, signal(:,:,ii),frames(:, :, 2:3, ii)); 101 | end 102 | 103 | figure; 104 | movie(M, 1, video.FrameRate); 105 | --------------------------------------------------------------------------------