├── README.md ├── boxfilter.m ├── example_enhancement.m ├── example_feathering.m ├── example_flash.m ├── example_smoothing.m ├── fastguidedfilter.m ├── fastguidedfilter_color.m ├── guidedfilter.m ├── guidedfilter_color.m ├── img_enhancement └── tulips.bmp ├── img_feathering ├── toy-mask.bmp └── toy.bmp ├── img_flash ├── cave-flash.bmp └── cave-noflash.bmp ├── img_smoothing └── cat.bmp └── readme.txt /README.md: -------------------------------------------------------------------------------- 1 | # fast-guided-filter 2 | Fast Guided Filter by Kaiming He 3 | 4 | We have uploaded it to github with a purpose of making it easy to access to developers. 5 | Original code (same as this repository) is stored at http://kaiminghe.com/eccv10/ 6 | 7 | 8 | *************************************************************************************** 9 | *************************************************************************************** 10 | 11 | Matlab demo code for "Fast Guided Filter" (arXiv 2015) 12 | 13 | by Kaiming He (kahe@microsoft.com) 14 | 15 | If you use/adapt our code in your work (either as a stand-alone tool or as a component 16 | of any algorithm), you need to appropriately cite our work. 17 | 18 | This code is for academic purpose only. Not for commercial/industrial activities. 19 | 20 | 21 | *************************************************************************************** 22 | *************************************************************************************** 23 | 24 | Usage: 25 | 26 | guidedfilter.m - (original) guided filter implementation 27 | guidedfilter_color.m - (original) guided filter for color guidance 28 | 29 | fastguidedfilter.m - fast guided filter implementation 30 | fastguidedfilter_color.m - fast guided filter for color guidance 31 | 32 | Run the four examples to see the results shown in the paper. 33 | -------------------------------------------------------------------------------- /boxfilter.m: -------------------------------------------------------------------------------- 1 | function imDst = boxfilter(imSrc, r) 2 | 3 | % BOXFILTER O(1) time box filtering using cumulative sum 4 | % 5 | % - Definition imDst(x, y)=sum(sum(imSrc(x-r:x+r,y-r:y+r))); 6 | % - Running time independent of r; 7 | % - Equivalent to the function: colfilt(imSrc, [2*r+1, 2*r+1], 'sliding', @sum); 8 | % - But much faster. 9 | 10 | [hei, wid] = size(imSrc); 11 | imDst = zeros(size(imSrc)); 12 | 13 | %cumulative sum over Y axis 14 | imCum = cumsum(imSrc, 1); 15 | %difference over Y axis 16 | imDst(1:r+1, :) = imCum(1+r:2*r+1, :); 17 | imDst(r+2:hei-r, :) = imCum(2*r+2:hei, :) - imCum(1:hei-2*r-1, :); 18 | imDst(hei-r+1:hei, :) = repmat(imCum(hei, :), [r, 1]) - imCum(hei-2*r:hei-r-1, :); 19 | 20 | %cumulative sum over X axis 21 | imCum = cumsum(imDst, 2); 22 | %difference over Y axis 23 | imDst(:, 1:r+1) = imCum(:, 1+r:2*r+1); 24 | imDst(:, r+2:wid-r) = imCum(:, 2*r+2:wid) - imCum(:, 1:wid-2*r-1); 25 | imDst(:, wid-r+1:wid) = repmat(imCum(:, wid), [1, r]) - imCum(:, wid-2*r:wid-r-1); 26 | end 27 | 28 | -------------------------------------------------------------------------------- /example_enhancement.m: -------------------------------------------------------------------------------- 1 | % example: detail enhancement 2 | 3 | close all; 4 | 5 | I = double(imread('.\img_enhancement\tulips.bmp')) / 255; 6 | p = I; 7 | 8 | r = 16; 9 | eps = 0.1^2; 10 | 11 | q = zeros(size(I)); 12 | tic; 13 | q(:, :, 1) = guidedfilter(I(:, :, 1), p(:, :, 1), r, eps); 14 | q(:, :, 2) = guidedfilter(I(:, :, 2), p(:, :, 2), r, eps); 15 | q(:, :, 3) = guidedfilter(I(:, :, 3), p(:, :, 3), r, eps); 16 | toc; 17 | 18 | q_sub = zeros(size(I)); 19 | s = 4; 20 | tic; 21 | q_sub(:, :, 1) = fastguidedfilter(I(:, :, 1), p(:, :, 1), r, eps, s); 22 | q_sub(:, :, 2) = fastguidedfilter(I(:, :, 2), p(:, :, 2), r, eps, s); 23 | q_sub(:, :, 3) = fastguidedfilter(I(:, :, 3), p(:, :, 3), r, eps, s); 24 | toc; 25 | 26 | I_enhanced = (I - q) * 5 + q; 27 | I_enhanced_sub = (I - q) * 5 + q_sub; 28 | 29 | figure(); 30 | imshow([I, q, q_sub, I_enhanced, I_enhanced_sub], [0, 1]); 31 | -------------------------------------------------------------------------------- /example_feathering.m: -------------------------------------------------------------------------------- 1 | % example: guided feathering 2 | 3 | close all; 4 | 5 | I = double(imread('.\img_feathering\toy.bmp')) / 255; 6 | p = double(rgb2gray(imread('.\img_feathering\toy-mask.bmp'))) / 255; 7 | 8 | r = 60; 9 | eps = 10^-6; 10 | 11 | tic; 12 | q = guidedfilter_color(I, p, r, eps); 13 | toc; 14 | 15 | s = 4; 16 | tic; 17 | q_sub = fastguidedfilter_color(I, p, r, eps, s); 18 | toc; 19 | 20 | figure(); 21 | imshow([I, repmat(p, [1, 1, 3]), repmat(q, [1, 1, 3]), repmat(q_sub, [1, 1, 3])], [0, 1]); 22 | -------------------------------------------------------------------------------- /example_flash.m: -------------------------------------------------------------------------------- 1 | % example: flash/noflash denoising 2 | 3 | close all; 4 | 5 | I = double(imread('.\img_flash\cave-flash.bmp')) / 255; 6 | p = double(imread('.\img_flash\cave-noflash.bmp')) / 255; 7 | 8 | r = 8; 9 | eps = 0.02^2; 10 | 11 | q = zeros(size(I)); 12 | tic; 13 | q(:, :, 1) = guidedfilter(I(:, :, 1), p(:, :, 1), r, eps); 14 | q(:, :, 2) = guidedfilter(I(:, :, 2), p(:, :, 2), r, eps); 15 | q(:, :, 3) = guidedfilter(I(:, :, 3), p(:, :, 3), r, eps); 16 | toc; 17 | 18 | s = 4; 19 | q_sub = zeros(size(I)); 20 | tic; 21 | q_sub(:, :, 1) = fastguidedfilter(I(:, :, 1), p(:, :, 1), r, eps, s); 22 | q_sub(:, :, 2) = fastguidedfilter(I(:, :, 2), p(:, :, 2), r, eps, s); 23 | q_sub(:, :, 3) = fastguidedfilter(I(:, :, 3), p(:, :, 3), r, eps, s); 24 | toc; 25 | 26 | figure(); 27 | imshow([I, p, q, q_sub], [0, 1]); 28 | -------------------------------------------------------------------------------- /example_smoothing.m: -------------------------------------------------------------------------------- 1 | % example: edge-preserving smoothing 2 | 3 | close all; 4 | 5 | I = double(imread('.\img_smoothing\cat.bmp')) / 255; % this image is too small to fully unleash the power of Fast GF 6 | p = I; 7 | r = 4; 8 | eps = 0.2^2; % try eps=0.1^2, 0.2^2, 0.4^2 9 | 10 | tic; 11 | q = guidedfilter(I, p, r, eps); 12 | toc; 13 | 14 | s = 4; % sampling ratio 15 | tic; 16 | q_sub = fastguidedfilter(I, p, r, eps, s); 17 | toc; 18 | 19 | figure(); 20 | imshow([I, q, q_sub], [0, 1]); 21 | -------------------------------------------------------------------------------- /fastguidedfilter.m: -------------------------------------------------------------------------------- 1 | function q = fastguidedfilter(I, p, r, eps, s) 2 | % GUIDEDFILTER O(1) time implementation of guided filter. 3 | % 4 | % - guidance image: I (should be a gray-scale/single channel image) 5 | % - filtering input image: p (should be a gray-scale/single channel image) 6 | % - local window radius: r 7 | % - regularization parameter: eps 8 | % - subsampling ratio: s (try s = r/4 to s=r) 9 | 10 | I_sub = imresize(I, 1/s, 'nearest'); % NN is often enough 11 | p_sub = imresize(p, 1/s, 'nearest'); 12 | r_sub = r / s; % make sure this is an integer 13 | 14 | [hei, wid] = size(I_sub); 15 | N = boxfilter(ones(hei, wid), r_sub); % the size of each local patch; N=(2r+1)^2 except for boundary pixels. 16 | 17 | mean_I = boxfilter(I_sub, r_sub) ./ N; 18 | mean_p = boxfilter(p_sub, r_sub) ./ N; 19 | mean_Ip = boxfilter(I_sub.*p_sub, r_sub) ./ N; 20 | cov_Ip = mean_Ip - mean_I .* mean_p; % this is the covariance of (I, p) in each local patch. 21 | 22 | mean_II = boxfilter(I_sub.*I_sub, r_sub) ./ N; 23 | var_I = mean_II - mean_I .* mean_I; 24 | 25 | a = cov_Ip ./ (var_I + eps); 26 | b = mean_p - a .* mean_I; 27 | 28 | mean_a = boxfilter(a, r_sub) ./ N; 29 | mean_b = boxfilter(b, r_sub) ./ N; 30 | 31 | mean_a = imresize(mean_a, [size(I, 1), size(I, 2)], 'bilinear'); % bilinear is recommended 32 | mean_b = imresize(mean_b, [size(I, 1), size(I, 2)], 'bilinear'); 33 | 34 | q = mean_a .* I + mean_b; 35 | end -------------------------------------------------------------------------------- /fastguidedfilter_color.m: -------------------------------------------------------------------------------- 1 | function q = fastguidedfilter_color(I, p, r, eps, s) 2 | % GUIDEDFILTER_COLOR O(1) time implementation of guided filter using a color image as the guidance. 3 | % 4 | % - guidance image: I (should be a color (RGB) image) 5 | % - filtering input image: p (should be a gray-scale/single channel image) 6 | % - local window radius: r 7 | % - regularization parameter: eps 8 | % - subsampling ratio: s (try s = r/4 to s=r) 9 | 10 | I_sub = imresize(I, 1/s, 'nearest'); % NN is often enough 11 | p_sub = imresize(p, 1/s, 'nearest'); 12 | r_sub = r / s; % make sure this is an integer 13 | 14 | [hei, wid] = size(p_sub); 15 | N = boxfilter(ones(hei, wid), r_sub); % the size of each local patch; N=(2r+1)^2 except for boundary pixels. 16 | 17 | mean_I_r = boxfilter(I_sub(:, :, 1), r_sub) ./ N; 18 | mean_I_g = boxfilter(I_sub(:, :, 2), r_sub) ./ N; 19 | mean_I_b = boxfilter(I_sub(:, :, 3), r_sub) ./ N; 20 | 21 | mean_p = boxfilter(p_sub, r_sub) ./ N; 22 | 23 | mean_Ip_r = boxfilter(I_sub(:, :, 1).*p_sub, r_sub) ./ N; 24 | mean_Ip_g = boxfilter(I_sub(:, :, 2).*p_sub, r_sub) ./ N; 25 | mean_Ip_b = boxfilter(I_sub(:, :, 3).*p_sub, r_sub) ./ N; 26 | 27 | % covariance of (I, p) in each local patch. 28 | cov_Ip_r = mean_Ip_r - mean_I_r .* mean_p; 29 | cov_Ip_g = mean_Ip_g - mean_I_g .* mean_p; 30 | cov_Ip_b = mean_Ip_b - mean_I_b .* mean_p; 31 | 32 | % variance of I in each local patch: the matrix Sigma in Eqn (14). 33 | % Note the variance in each local patch is a 3x3 symmetric matrix: 34 | % rr, rg, rb 35 | % Sigma = rg, gg, gb 36 | % rb, gb, bb 37 | var_I_rr = boxfilter(I_sub(:, :, 1).*I_sub(:, :, 1), r_sub) ./ N - mean_I_r .* mean_I_r; 38 | var_I_rg = boxfilter(I_sub(:, :, 1).*I_sub(:, :, 2), r_sub) ./ N - mean_I_r .* mean_I_g; 39 | var_I_rb = boxfilter(I_sub(:, :, 1).*I_sub(:, :, 3), r_sub) ./ N - mean_I_r .* mean_I_b; 40 | var_I_gg = boxfilter(I_sub(:, :, 2).*I_sub(:, :, 2), r_sub) ./ N - mean_I_g .* mean_I_g; 41 | var_I_gb = boxfilter(I_sub(:, :, 2).*I_sub(:, :, 3), r_sub) ./ N - mean_I_g .* mean_I_b; 42 | var_I_bb = boxfilter(I_sub(:, :, 3).*I_sub(:, :, 3), r_sub) ./ N - mean_I_b .* mean_I_b; 43 | 44 | a = zeros(hei, wid, 3); 45 | for y=1:hei 46 | for x=1:wid 47 | Sigma = [var_I_rr(y, x), var_I_rg(y, x), var_I_rb(y, x); 48 | var_I_rg(y, x), var_I_gg(y, x), var_I_gb(y, x); 49 | var_I_rb(y, x), var_I_gb(y, x), var_I_bb(y, x)]; 50 | 51 | cov_Ip = [cov_Ip_r(y, x), cov_Ip_g(y, x), cov_Ip_b(y, x)]; 52 | 53 | a(y, x, :) = cov_Ip * inv(Sigma + eps * eye(3)); % very inefficient. Replace this in your C++ code. 54 | end 55 | end 56 | 57 | b = mean_p - a(:, :, 1) .* mean_I_r - a(:, :, 2) .* mean_I_g - a(:, :, 3) .* mean_I_b; % Eqn. (15) in the paper; 58 | 59 | mean_a(:, :, 1) = boxfilter(a(:, :, 1), r_sub)./N; 60 | mean_a(:, :, 2) = boxfilter(a(:, :, 2), r_sub)./N; 61 | mean_a(:, :, 3) = boxfilter(a(:, :, 3), r_sub)./N; 62 | mean_b = boxfilter(b, r_sub)./N; 63 | 64 | mean_a = imresize(mean_a, [size(I, 1), size(I, 2)], 'bilinear'); % bilinear is recommended 65 | mean_b = imresize(mean_b, [size(I, 1), size(I, 2)], 'bilinear'); 66 | q = mean_a(:, :, 1) .* I(:, :, 1)... 67 | + mean_a(:, :, 2) .* I(:, :, 2)... 68 | + mean_a(:, :, 3) .* I(:, :, 3)... 69 | + mean_b; 70 | end -------------------------------------------------------------------------------- /guidedfilter.m: -------------------------------------------------------------------------------- 1 | function q = guidedfilter(I, p, r, eps) 2 | % GUIDEDFILTER O(1) time implementation of guided filter. 3 | % 4 | % - guidance image: I (should be a gray-scale/single channel image) 5 | % - filtering input image: p (should be a gray-scale/single channel image) 6 | % - local window radius: r 7 | % - regularization parameter: eps 8 | 9 | [hei, wid] = size(I); 10 | N = boxfilter(ones(hei, wid), r); % the size of each local patch; N=(2r+1)^2 except for boundary pixels. 11 | 12 | mean_I = boxfilter(I, r) ./ N; 13 | mean_p = boxfilter(p, r) ./ N; 14 | mean_Ip = boxfilter(I.*p, r) ./ N; 15 | cov_Ip = mean_Ip - mean_I .* mean_p; % this is the covariance of (I, p) in each local patch. 16 | 17 | mean_II = boxfilter(I.*I, r) ./ N; 18 | var_I = mean_II - mean_I .* mean_I; 19 | 20 | a = cov_Ip ./ (var_I + eps); % Eqn. (5) in the paper; 21 | b = mean_p - a .* mean_I; % Eqn. (6) in the paper; 22 | 23 | mean_a = boxfilter(a, r) ./ N; 24 | mean_b = boxfilter(b, r) ./ N; 25 | 26 | q = mean_a .* I + mean_b; % Eqn. (8) in the paper; 27 | end -------------------------------------------------------------------------------- /guidedfilter_color.m: -------------------------------------------------------------------------------- 1 | function q = guidedfilter_color(I, p, r, eps) 2 | % GUIDEDFILTER_COLOR O(1) time implementation of guided filter using a color image as the guidance. 3 | % 4 | % - guidance image: I (should be a color (RGB) image) 5 | % - filtering input image: p (should be a gray-scale/single channel image) 6 | % - local window radius: r 7 | % - regularization parameter: eps 8 | 9 | [hei, wid] = size(p); 10 | N = boxfilter(ones(hei, wid), r); % the size of each local patch; N=(2r+1)^2 except for boundary pixels. 11 | 12 | mean_I_r = boxfilter(I(:, :, 1), r) ./ N; 13 | mean_I_g = boxfilter(I(:, :, 2), r) ./ N; 14 | mean_I_b = boxfilter(I(:, :, 3), r) ./ N; 15 | 16 | mean_p = boxfilter(p, r) ./ N; 17 | 18 | mean_Ip_r = boxfilter(I(:, :, 1).*p, r) ./ N; 19 | mean_Ip_g = boxfilter(I(:, :, 2).*p, r) ./ N; 20 | mean_Ip_b = boxfilter(I(:, :, 3).*p, r) ./ N; 21 | 22 | % covariance of (I, p) in each local patch. 23 | cov_Ip_r = mean_Ip_r - mean_I_r .* mean_p; 24 | cov_Ip_g = mean_Ip_g - mean_I_g .* mean_p; 25 | cov_Ip_b = mean_Ip_b - mean_I_b .* mean_p; 26 | 27 | % variance of I in each local patch: the matrix Sigma in Eqn (14). 28 | % Note the variance in each local patch is a 3x3 symmetric matrix: 29 | % rr, rg, rb 30 | % Sigma = rg, gg, gb 31 | % rb, gb, bb 32 | var_I_rr = boxfilter(I(:, :, 1).*I(:, :, 1), r) ./ N - mean_I_r .* mean_I_r; 33 | var_I_rg = boxfilter(I(:, :, 1).*I(:, :, 2), r) ./ N - mean_I_r .* mean_I_g; 34 | var_I_rb = boxfilter(I(:, :, 1).*I(:, :, 3), r) ./ N - mean_I_r .* mean_I_b; 35 | var_I_gg = boxfilter(I(:, :, 2).*I(:, :, 2), r) ./ N - mean_I_g .* mean_I_g; 36 | var_I_gb = boxfilter(I(:, :, 2).*I(:, :, 3), r) ./ N - mean_I_g .* mean_I_b; 37 | var_I_bb = boxfilter(I(:, :, 3).*I(:, :, 3), r) ./ N - mean_I_b .* mean_I_b; 38 | 39 | a = zeros(hei, wid, 3); 40 | for y=1:hei 41 | for x=1:wid 42 | Sigma = [var_I_rr(y, x), var_I_rg(y, x), var_I_rb(y, x); 43 | var_I_rg(y, x), var_I_gg(y, x), var_I_gb(y, x); 44 | var_I_rb(y, x), var_I_gb(y, x), var_I_bb(y, x)]; 45 | %Sigma = Sigma + eps * eye(3); 46 | 47 | cov_Ip = [cov_Ip_r(y, x), cov_Ip_g(y, x), cov_Ip_b(y, x)]; 48 | 49 | a(y, x, :) = cov_Ip * inv(Sigma + eps * eye(3)); % Eqn. (14) in the paper; 50 | end 51 | end 52 | 53 | b = mean_p - a(:, :, 1) .* mean_I_r - a(:, :, 2) .* mean_I_g - a(:, :, 3) .* mean_I_b; % Eqn. (15) in the paper; 54 | 55 | q = (boxfilter(a(:, :, 1), r).* I(:, :, 1)... 56 | + boxfilter(a(:, :, 2), r).* I(:, :, 2)... 57 | + boxfilter(a(:, :, 3), r).* I(:, :, 3)... 58 | + boxfilter(b, r)) ./ N; % Eqn. (16) in the paper; 59 | end -------------------------------------------------------------------------------- /img_enhancement/tulips.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/accessify/fast-guided-filter/8a6e2ee4387c931d46d7445e26f0edb635d19b90/img_enhancement/tulips.bmp -------------------------------------------------------------------------------- /img_feathering/toy-mask.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/accessify/fast-guided-filter/8a6e2ee4387c931d46d7445e26f0edb635d19b90/img_feathering/toy-mask.bmp -------------------------------------------------------------------------------- /img_feathering/toy.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/accessify/fast-guided-filter/8a6e2ee4387c931d46d7445e26f0edb635d19b90/img_feathering/toy.bmp -------------------------------------------------------------------------------- /img_flash/cave-flash.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/accessify/fast-guided-filter/8a6e2ee4387c931d46d7445e26f0edb635d19b90/img_flash/cave-flash.bmp -------------------------------------------------------------------------------- /img_flash/cave-noflash.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/accessify/fast-guided-filter/8a6e2ee4387c931d46d7445e26f0edb635d19b90/img_flash/cave-noflash.bmp -------------------------------------------------------------------------------- /img_smoothing/cat.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/accessify/fast-guided-filter/8a6e2ee4387c931d46d7445e26f0edb635d19b90/img_smoothing/cat.bmp -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | 2 | *************************************************************************************** 3 | *************************************************************************************** 4 | 5 | Matlab demo code for "Fast Guided Filter" (arXiv 2015) 6 | 7 | by Kaiming He (kahe@microsoft.com) 8 | 9 | If you use/adapt our code in your work (either as a stand-alone tool or as a component 10 | of any algorithm), you need to appropriately cite our work. 11 | 12 | This code is for academic purpose only. Not for commercial/industrial activities. 13 | 14 | 15 | *************************************************************************************** 16 | *************************************************************************************** 17 | 18 | Usage: 19 | 20 | guidedfilter.m - (original) guided filter implementation 21 | guidedfilter_color.m - (original) guided filter for color guidance 22 | 23 | fastguidedfilter.m - fast guided filter implementation 24 | fastguidedfilter_color.m - fast guided filter for color guidance 25 | 26 | Run the four examples to see the results shown in the paper. 27 | --------------------------------------------------------------------------------