├── .DS_Store ├── .gitignore ├── BF-ICCV1998 ├── bilateralFilter.m └── testBF.m ├── DiffusionMap ├── ag.m ├── decomposeFast.m ├── dist.cpp ├── dist.mexmaci64 ├── dist.mexw64 ├── max2.m ├── patchToPoints.m ├── readLDR.m ├── rgb2lab.m └── runme.m ├── EAW-TOG2009 ├── Demo_EAW_Enhance.m ├── Demo_EAW_Inter.m ├── Demo_EAW_smooth.m ├── Demo_EAW_test.m ├── EAW.m ├── eaw.cpp ├── eaw.mexa64 ├── eaw.mexglx ├── eaw.mexmaci64 ├── eaw_imp.h ├── gEAW.m ├── geaw.cpp ├── geaw.mexa64 ├── geaw.mexglx ├── geaw.mexmaci64 ├── iEAW.m ├── ieaw.cpp ├── ieaw.mexa64 ├── ieaw.mexglx ├── ieaw.mexmaci64 ├── igEAW.m ├── igeaw.cpp ├── igeaw.mexa64 ├── igeaw.mexmaci64 ├── makefile.m ├── rgb2yuv.m └── yuv2rgb.m ├── FGS-TIP2014 ├── Demo.m ├── FGS.m ├── README_FGS.txt ├── compile.m ├── mexFGS.cpp ├── mexFGS.mexa64 ├── mexFGS.mexw64 ├── mexFGS_simple.cpp ├── mexFGS_simple.mexa64 └── mexFGS_simple.mexw64 ├── Fast_Image_Processing_ICCV2017.pdf ├── GF-ECCV2010TPAMI2013 ├── boxfilter.m ├── example_enhancement.m ├── example_feathering.m ├── example_flash.m ├── example_smoothing.m ├── guidedfilter.m ├── guidedfilter_color.m └── readme.txt ├── L0-TOG2011 ├── .DS_Store ├── L0Smoothing.m └── testL0Smoothing.m ├── LICENSE ├── LLF-TOG2011 ├── LICENSE ├── README ├── child_window.m ├── downsample.m ├── gaussian_pyramid.m ├── lapfilter.m ├── lapfilter_core.m ├── lapfilter_demo.m ├── laplacian_pyramid.m ├── numlevels.m ├── pyramid_filter.m ├── reconstruct_laplacian_pyramid.m └── upsample.m ├── README.md ├── RGF-ECCV2014 ├── RollingGuidanceFilter.m ├── bilateralFilter.m └── example.m ├── RTV-TOG2012 ├── Demo.m └── tsmooth.m ├── SGF-ICCV2015.pdf ├── SGF-ICCV2015 ├── CMakeLists.txt ├── LICENSE ├── README.md ├── SGF.exe ├── VisualMap.m ├── abstraction.m ├── demo_abs.m ├── demo_depth.m ├── demo_iterative.m ├── demo_smooth.m ├── demo_smooth_JX.m ├── demo_texture.m ├── depth │ └── shrink.m ├── exe │ ├── VisualMap.m │ ├── abstraction.m │ ├── demo_abs.m │ ├── demo_depth.m │ ├── demo_iterative.m │ ├── demo_smooth.m │ ├── demo_texture.m │ ├── depth │ │ └── shrink.m │ └── readme.txt ├── opencv_core248.dll ├── opencv_highgui248.dll ├── opencv_imgproc248.dll └── src │ ├── Image.cpp │ ├── Image.h │ ├── SGF.cpp │ ├── SLIC.cpp │ ├── SLIC.h │ └── main.cpp ├── TF-TIP2014 ├── .DS_Store ├── README.txt ├── TreeFilterRGB_Uint8.m ├── TreeFilterRGB_Uint8.mexa64 ├── TreeFilterRGB_Uint8.mexw64 ├── demo_filter.m └── demo_texture_edit.m ├── TotalVariation ├── SplitBregmanROF.c └── rof_mex_demo.m ├── WLS-TOG2008 ├── testWLS.m └── wlsFilter.m └── fastABF-TIP2019 ├── LICENSE ├── README.md ├── abf_bruteforce.m ├── demo_deblocking.m ├── demo_sharpening.m ├── demo_smooth.m ├── demo_texture.m ├── fastABF ├── MinMaxFilter.cpp ├── MinMaxFilter.mexa64 ├── compInt.m ├── fastABF.m └── fitPolynomial.m ├── linearMap.m ├── logClassifier.m ├── mrtv.m ├── peppers_degraded.tif └── sigmaJPEG.m /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | *.png 30 | *.jpg 31 | *.bmp 32 | run.m 33 | -------------------------------------------------------------------------------- /BF-ICCV1998/bilateralFilter.m: -------------------------------------------------------------------------------- 1 | % 2 | % output = bilateralFilter( data, edge, sigmaSpatial, sigmaRange, ... 3 | % samplingSpatial, samplingRange ) 4 | % 5 | % Bilateral and Cross-Bilateral Filter 6 | % 7 | % Bilaterally filters the image 'data' using the edges in the image 'edge'. 8 | % If 'data' == 'edge', then it the normal bilateral filter. 9 | % Else, then it is the "cross" or "joint" bilateral filter. 10 | % 11 | % Note that for the cross bilateral filter, data does not need to be 12 | % defined everywhere. Undefined values can be set to 'NaN'. However, edge 13 | % *does* need to be defined everywhere. 14 | % 15 | % data and edge should be of the same size and greyscale. 16 | % (i.e. they should be ( height x width x 1 matrices )) 17 | % 18 | % data is the only required argument 19 | % 20 | % By default: 21 | % edge = data 22 | % sigmaSpatial = samplingSpatial = min( width, height ) / 16; 23 | % sigmaRange = samplingRange = ( max( edge( : ) ) - min( edge( : ) ) ) / 10 24 | % 25 | % 26 | 27 | % Copyright (c) <2007> 28 | % 29 | % Permission is hereby granted, free of charge, to any person obtaining a copy 30 | % of this software and associated documentation files (the "Software"), to deal 31 | % in the Software without restriction, including without limitation the rights 32 | % to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 33 | % copies of the Software, and to permit persons to whom the Software is 34 | % furnished to do so, subject to the following conditions: 35 | % 36 | % The above copyright notice and this permission notice shall be included in 37 | % all copies or substantial portions of the Software. 38 | % 39 | % THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 40 | % IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 41 | % FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 42 | % AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 43 | % LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 44 | % OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 45 | % THE SOFTWARE. 46 | % 47 | 48 | function output = bilateralFilter( data, edge, sigmaSpatial, sigmaRange, ... 49 | samplingSpatial, samplingRange ) 50 | 51 | if ~exist( 'edge', 'var' ) 52 | edge = data; 53 | end 54 | 55 | inputHeight = size( data, 1 ); 56 | inputWidth = size( data, 2 ); 57 | 58 | if ~exist( 'sigmaSpatial', 'var' ) 59 | sigmaSpatial = min( inputWidth, inputHeight ) / 16; 60 | end 61 | 62 | edgeMin = min( edge( : ) ); 63 | edgeMax = max( edge( : ) ); 64 | edgeDelta = edgeMax - edgeMin; 65 | 66 | if ~exist( 'sigmaRange', 'var' ) 67 | sigmaRange = 0.1 * edgeDelta; 68 | end 69 | 70 | if ~exist( 'samplingSpatial', 'var' ) 71 | samplingSpatial = sigmaSpatial; 72 | end 73 | 74 | if ~exist( 'samplingRange', 'var' ) 75 | samplingRange = sigmaRange; 76 | end 77 | 78 | if size( data ) ~= size( edge ) 79 | error( 'data and edge must be of the same size' ); 80 | end 81 | 82 | % parameters 83 | derivedSigmaSpatial = sigmaSpatial / samplingSpatial; 84 | derivedSigmaRange = sigmaRange / samplingRange; 85 | 86 | paddingXY = floor( 2 * derivedSigmaSpatial ) + 1; 87 | paddingZ = floor( 2 * derivedSigmaRange ) + 1; 88 | 89 | % allocate 3D grid 90 | downsampledWidth = floor( ( inputWidth - 1 ) / samplingSpatial ) + 1 + 2 * paddingXY; 91 | downsampledHeight = floor( ( inputHeight - 1 ) / samplingSpatial ) + 1 + 2 * paddingXY; 92 | downsampledDepth = floor( edgeDelta / samplingRange ) + 1 + 2 * paddingZ; 93 | 94 | gridData = zeros( downsampledHeight, downsampledWidth, downsampledDepth ); 95 | gridWeights = zeros( downsampledHeight, downsampledWidth, downsampledDepth ); 96 | 97 | % compute downsampled indices 98 | [ jj, ii ] = meshgrid( 0 : inputWidth - 1, 0 : inputHeight - 1 ); 99 | 100 | % ii = 101 | % 0 0 0 0 0 102 | % 1 1 1 1 1 103 | % 2 2 2 2 2 104 | 105 | % jj = 106 | % 0 1 2 3 4 107 | % 0 1 2 3 4 108 | % 0 1 2 3 4 109 | 110 | % so when iterating over ii( k ), jj( k ) 111 | % get: ( 0, 0 ), ( 1, 0 ), ( 2, 0 ), ... (down columns first) 112 | 113 | di = round( ii / samplingSpatial ) + paddingXY + 1; 114 | dj = round( jj / samplingSpatial ) + paddingXY + 1; 115 | dz = round( ( edge - edgeMin ) / samplingRange ) + paddingZ + 1; 116 | 117 | % perform scatter (there's probably a faster way than this) 118 | % normally would do downsampledWeights( di, dj, dk ) = 1, but we have to 119 | % perform a summation to do box downsampling 120 | for k = 1 : numel( dz ) 121 | 122 | dataZ = data( k ); % traverses the image column wise, same as di( k ) 123 | if ~isnan( dataZ ) 124 | 125 | dik = di( k ); 126 | djk = dj( k ); 127 | dzk = dz( k ); 128 | 129 | gridData( dik, djk, dzk ) = gridData( dik, djk, dzk ) + dataZ; 130 | gridWeights( dik, djk, dzk ) = gridWeights( dik, djk, dzk ) + 1; 131 | 132 | end 133 | end 134 | 135 | % make gaussian kernel 136 | kernelWidth = 2 * derivedSigmaSpatial + 1; 137 | kernelHeight = kernelWidth; 138 | kernelDepth = 2 * derivedSigmaRange + 1; 139 | 140 | halfKernelWidth = floor( kernelWidth / 2 ); 141 | halfKernelHeight = floor( kernelHeight / 2 ); 142 | halfKernelDepth = floor( kernelDepth / 2 ); 143 | 144 | [gridX, gridY, gridZ] = meshgrid( 0 : kernelWidth - 1, 0 : kernelHeight - 1, 0 : kernelDepth - 1 ); 145 | gridX = gridX - halfKernelWidth; 146 | gridY = gridY - halfKernelHeight; 147 | gridZ = gridZ - halfKernelDepth; 148 | gridRSquared = ( gridX .* gridX + gridY .* gridY ) / ( derivedSigmaSpatial * derivedSigmaSpatial ) + ( gridZ .* gridZ ) / ( derivedSigmaRange * derivedSigmaRange ); 149 | kernel = exp( -0.5 * gridRSquared ); 150 | 151 | % convolve 152 | blurredGridData = convn( gridData, kernel, 'same' ); 153 | blurredGridWeights = convn( gridWeights, kernel, 'same' ); 154 | 155 | % divide 156 | blurredGridWeights( blurredGridWeights == 0 ) = -2; % avoid divide by 0, won't read there anyway 157 | normalizedBlurredGrid = blurredGridData ./ blurredGridWeights; 158 | normalizedBlurredGrid( blurredGridWeights < -1 ) = 0; % put 0s where it's undefined 159 | blurredGridWeights( blurredGridWeights < -1 ) = 0; % put zeros back 160 | 161 | % upsample 162 | [ jj, ii ] = meshgrid( 0 : inputWidth - 1, 0 : inputHeight - 1 ); % meshgrid does x, then y, so output arguments need to be reversed 163 | % no rounding 164 | di = ( ii / samplingSpatial ) + paddingXY + 1; 165 | dj = ( jj / samplingSpatial ) + paddingXY + 1; 166 | dz = ( edge - edgeMin ) / samplingRange + paddingZ + 1; 167 | 168 | % interpn takes rows, then cols, etc 169 | % i.e. size(v,1), then size(v,2), ... 170 | output = interpn( normalizedBlurredGrid, di, dj, dz ); 171 | -------------------------------------------------------------------------------- /BF-ICCV1998/testBF.m: -------------------------------------------------------------------------------- 1 | clear,close; 2 | 3 | Original_image_dir = '/Users/xujun/Desktop/YingkunHou/dataset/origin_images'; 4 | fpath = fullfile(Original_image_dir, '*.png'); 5 | im_dir = dir(fpath); 6 | im_num = length(im_dir); 7 | 8 | method = 'BF'; 9 | for i = 1:im_num 10 | I = imread(fullfile(Original_image_dir, im_dir(i).name)); 11 | S = regexp(im_dir(i).name, '\.', 'split'); 12 | %sI = bilateralFilter(I); 13 | sI = imbilatfilt(I); 14 | fprintf('%s is done!\n', im_dir(i).name); 15 | outname = sprintf(['/Users/xujun/Desktop/YingkunHou/results/500images/' S{1} '_' method '.png']); 16 | imwrite(sI, outname); 17 | end -------------------------------------------------------------------------------- /DiffusionMap/ag.m: -------------------------------------------------------------------------------- 1 | function [ out ] = ag( I, gamma ) 2 | %AG Raise I in power gamma (ApplyGamma) 3 | 4 | if nargin==1 5 | gamma = 1/2.2; 6 | end 7 | 8 | out = real(I.^gamma); -------------------------------------------------------------------------------- /DiffusionMap/decomposeFast.m: -------------------------------------------------------------------------------- 1 | function [E, D] = decomposeFast(rgb, sigma_r, nvec, nsamples) 2 | 3 | 4 | % Some people advocate LAB... 5 | X = patchToPoints(rgb2lab(rgb)/100); 6 | % X = patchToPoints(rgb); 7 | 8 | if(~exist('nsamples', 'var')), 9 | n = 50; 10 | else 11 | n = nsamples; 12 | end 13 | 14 | subs = round(size(X,1)/n); 15 | find = 1:size(X,1); 16 | 17 | ind1 = 1:subs:size(X,1); 18 | ind2 = setdiff(find, ind1); 19 | 20 | p = randperm(size(X,1)); 21 | ind1 = p(ind1); 22 | ind2 = p(ind2); 23 | 24 | Ximp = X(ind1,:)'; 25 | Xoth = X(ind2,:)'; 26 | 27 | A = dist(Ximp,Ximp,sigma_r); 28 | B = dist(Ximp,Xoth,sigma_r); 29 | 30 | % Nystrom 31 | n = size(B,1); 32 | m = size(B,2); 33 | Up = [A;B']; 34 | 35 | d1 = sum(Up, 1); 36 | d2 = sum(B,1) + sum(B,2)'*pinv(A)*B; 37 | dhat = sqrt(1./[d1 d2])'; 38 | 39 | A = A.*(dhat(1:n)*dhat(1:n)'); 40 | B = B.*(dhat(1:n)*dhat(n+(1:m))'); 41 | 42 | Asi = sqrtm(pinv(A)); 43 | Q = A+Asi*(B*B')*Asi; 44 | 45 | % Apparently this is faster 46 | if (true) 47 | % [U L] = eig(Q); 48 | [U,L,T] = svd(Q); 49 | else 50 | opts.issym = 1; 51 | [U L] = eigs(Q,nvec+1,'lm',opts) ; 52 | end 53 | 54 | V = Up*(Asi*U*diag(1./sqrt(abs(diag(L))))); 55 | 56 | E=[]; pres=[]; D=[]; 57 | for i = 2:nvec+1 58 | res = V(:,i)./V(:,1); 59 | pres(ind1) = res(1:n); 60 | pres(ind2) = res(n+1:end); 61 | E(:,i-1) = real(pres); 62 | end 63 | D = diag(L); 64 | D = D(2:nvec+1); 65 | 66 | -------------------------------------------------------------------------------- /DiffusionMap/dist.cpp: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // 3 | // 4 | // The C-mex implementation of euclidean pairwise metrics 5 | // 6 | // 7 | ///////////////////////////////////////////////////////////////////// 8 | 9 | #include "mex.h" 10 | 11 | #include 12 | 13 | 14 | template 15 | void euclidean(const Ty* X1, const Ty* X2, Ty* M, int d, int n1, int n2) 16 | { 17 | const Ty* v2 = X2; 18 | for(int j = 0; j < n2; ++j) 19 | { 20 | const Ty* v1 = X1; 21 | for (int i = 0; i < n1; ++i) 22 | { 23 | Ty s = 0; 24 | for (int k = 0; k < d; ++k) 25 | { 26 | s += (v1[k] - v2[k])*(v1[k] - v2[k]); 27 | } 28 | *M++ = s; 29 | 30 | v1 += d; 31 | } 32 | v2 += d; 33 | } 34 | } 35 | 36 | template 37 | void euclidean_exp(const Ty* X1, const Ty* X2, Ty* M, int d, int n1, int n2, double sigma_r) 38 | { 39 | double sigma = 1.0/sigma_r; 40 | const Ty* v2 = X2; 41 | for(int j = 0; j < n2; ++j) 42 | { 43 | const Ty* v1 = X1; 44 | for (int i = 0; i < n1; ++i) 45 | { 46 | Ty s = 0; 47 | for (int k = 0; k < d; ++k) 48 | { 49 | s += (v1[k] - v2[k])*(v1[k] - v2[k]); 50 | } 51 | *M++ = exp(-sigma*s); 52 | 53 | v1 += d; 54 | } 55 | v2 += d; 56 | } 57 | } 58 | 59 | 60 | 61 | //void euclidean(const double* X1, const double* X2, double* M, int d, int n1, int n2) 62 | //{ 63 | // const double* v2 = X2; 64 | // for(int j = 0; j < n2; ++j) 65 | // { 66 | // const double* v1 = X1; 67 | // for (int i = 0; i < n1; ++i) 68 | // { 69 | // double s = 0; 70 | // for (int k = 0; k < d; ++k) 71 | // { 72 | // s += (v1[k] - v2[k])*(v1[k] - v2[k]); 73 | // } 74 | // *M++ = s; 75 | // 76 | // v1 += d; 77 | // } 78 | // v2 += d; 79 | // } 80 | //} 81 | 82 | /** 83 | * main entry 84 | * Input: X1, X2, sigma(opcode) 85 | * Output: D 86 | */ 87 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 88 | { 89 | const mxArray* mxX1 = prhs[0]; 90 | const mxArray* mxX2 = prhs[1]; 91 | const mxArray* mxSigma = prhs[2]; 92 | 93 | mwSize d = mxGetM(mxX1); 94 | mwSize n1 = mxGetN(mxX1); 95 | mwSize n2 = mxGetN(mxX2); 96 | 97 | double sigma_r = *((const double*)mxGetData(mxSigma)); 98 | 99 | if (mxGetClassID(mxX1) == mxDOUBLE_CLASS) 100 | { 101 | mxArray* mxD = mxCreateNumericMatrix(n1, n2, mxDOUBLE_CLASS, mxREAL); 102 | euclidean_exp((const double*)mxGetData(mxX1), (const double*)mxGetData(mxX2), 103 | (double *)mxGetData(mxD), (int)d, (int)n1, (int)n2,sigma_r); 104 | plhs[0] = mxD; 105 | } 106 | else // SINGLE 107 | { 108 | mxArray* mxD = mxCreateNumericMatrix(n1, n2, mxSINGLE_CLASS, mxREAL); 109 | euclidean_exp((const float*)mxGetData(mxX1), (const float*)mxGetData(mxX2), 110 | (float*)mxGetData(mxD), (int)d, (int)n1, (int)n2,sigma_r); 111 | plhs[0] = mxD; 112 | } 113 | } 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /DiffusionMap/dist.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/DiffusionMap/dist.mexmaci64 -------------------------------------------------------------------------------- /DiffusionMap/dist.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/DiffusionMap/dist.mexw64 -------------------------------------------------------------------------------- /DiffusionMap/max2.m: -------------------------------------------------------------------------------- 1 | function out = max2( in ) 2 | %MAX2 Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | out = max(in(:)); -------------------------------------------------------------------------------- /DiffusionMap/patchToPoints.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | function points = patchToPoints(patch) 4 | 5 | points = squeeze(reshape(patch, size(patch,1)*size(patch,2), 1, 3)); 6 | 7 | -------------------------------------------------------------------------------- /DiffusionMap/readLDR.m: -------------------------------------------------------------------------------- 1 | function [I, r,g,b] = readLDR(filename, path, maxDim, method) 2 | 3 | 4 | if nargin==1 5 | method = 'bicubic'; 6 | path = '~/Images/testImages/'; 7 | end 8 | 9 | if nargin==3 10 | method = 'bicubic'; 11 | end 12 | 13 | fullpath = strcat(path,filename); 14 | 15 | rc = 0.2989; 16 | gc = 0.587; 17 | bc = 0.114; 18 | 19 | degamma = 2.2; 20 | 21 | Im = imread(fullpath); 22 | maxIm = max(Im(:)); 23 | 24 | if nargin == 1 || nargin == 2 25 | ; 26 | else 27 | imMaxDim = max(size(Im)); 28 | if imMaxDim > maxDim 29 | Im = imresize(Im, maxDim/imMaxDim, method); 30 | end 31 | end 32 | % Heuristics 33 | m = 256.0; 34 | if maxIm>m 35 | m = 65535.0; 36 | end 37 | Im = (double(Im)/m).^degamma; 38 | 39 | r = 0; g = 0; b = 0; 40 | 41 | if ndims(Im)==3 42 | r = Im(:,:,1); g = Im(:,:,2); b = Im(:,:,3); 43 | I = r*rc + g*gc + b*bc +0.0000001; 44 | else 45 | I = Im; 46 | end 47 | 48 | 49 | -------------------------------------------------------------------------------- /DiffusionMap/rgb2lab.m: -------------------------------------------------------------------------------- 1 | function lab = rgb2lab( rgb ) 2 | %RGB2LAB Summary of this function goes here 3 | % Detailed explanation goes here 4 | 5 | C = makecform('srgb2lab'); 6 | lab = applycform(rgb,C); 7 | -------------------------------------------------------------------------------- /DiffusionMap/runme.m: -------------------------------------------------------------------------------- 1 | %% Compute diffusion maps 2 | 3 | % Compute diffusion maps and use them as per-pixel affinity. 4 | 5 | % Make sure you compiled dist.cpp for your platform: 6 | % mex dist.cpp 7 | 8 | clear 9 | 10 | rgb = im2double(imread('../L0-TOG2011/pflower.jpg')); 11 | rgb = imresize(rgb, 0.3); 12 | % Optional: Remove "gamma". 13 | rgb = ag(rgb, 2.2); 14 | [h,w,~] = size(rgb); 15 | 16 | % Try other sigma values (0.05) 17 | GAUSS_SIGMA = 0.1; 18 | NUM_VECTORS = 7; 19 | NUM_SAMPLES = 40; 20 | [E, D] = decomposeFast(rgb, GAUSS_SIGMA, NUM_VECTORS, NUM_SAMPLES); 21 | 22 | % Plot eigenvectors 23 | figure(1) 24 | subplot(2,4,1); imshow(ag(rgb)); title('Original Image'); 25 | for i=2:min(8,NUM_VECTORS+1) 26 | subplot(2,4,i), imagesc(real(reshape(E(:,i-1),h,w))), title(D(i-1)) 27 | title(['EValue' num2str(i) ': ' num2str(D(i-1),4)]); 28 | axis off 29 | end 30 | 31 | %% Fading gradients with different t values 32 | 33 | % Let's stack first three eigenvectors as an image and visaulize the 34 | % magnitude of its gradients. This is how we got the WLS with Diffusion 35 | % Maps set of results (Section 4). 36 | 37 | orig_map=reshape(E,h,w,NUM_VECTORS); 38 | map = zeros([h w 3]); 39 | D = D./D(1); 40 | 41 | t = [1, 2, 4, 16]; 42 | 43 | alpha = 1.0; 44 | for tt = 1:length(t) 45 | DD = ag(D,t(tt)); 46 | for i=1:NUM_VECTORS 47 | map(:,:,i) = orig_map(:,:,i)*ag(DD(i),t(tt)); 48 | end 49 | dy = diff(map, 1, 1); 50 | dy = sum(abs(dy),3).^alpha; 51 | dy = padarray(dy, [1 0], 'post'); 52 | dx = diff(map, 1, 2); 53 | dx = sum(abs(dx),3).^alpha; 54 | dx = padarray(dx, [0 1], 'post'); 55 | grad = dx+dy; 56 | geoGrad(:,:,tt) = grad./max2(grad); 57 | end 58 | 59 | figure(2); 60 | subplot(2,2,1), imshow(geoGrad(:,:,1)), title(['DM Gradient, t=',num2str(t(1))]) 61 | subplot(2,2,2), imshow(geoGrad(:,:,2)), title(['DM Gradient, t=',num2str(t(2))]) 62 | subplot(2,2,3), imshow(geoGrad(:,:,3)), title(['DM Gradient, t=',num2str(t(3))]) 63 | subplot(2,2,4), imshow(geoGrad(:,:,4)), title(['DM Gradient, t=',num2str(t(4))]) 64 | 65 | 66 | -------------------------------------------------------------------------------- /EAW-TOG2009/Demo_EAW_Enhance.m: -------------------------------------------------------------------------------- 1 | %%%%%%% Detail Enhacement 2 | 3 | 4 | clear 5 | 6 | wave_type = 1 ; 7 | 8 | figure(1) 9 | clf 10 | colormap(gray(256)) ; 11 | 12 | I = imread('pflower.jpg'); 13 | I = double(I) / 255 ; 14 | [w, h, c] = size(I) ; 15 | nlevels = floor(log2(min(size(I(:,:,1)))))-1 ; 16 | 17 | figure(1) 18 | 19 | subplot(2,3,1), imagesc(I), title('Input'), axis off ; drawnow 20 | I = rgb2hsv(I) ; 21 | 22 | R = I ; 23 | [A, W] = EAW(R(:,:,3),nlevels,wave_type,1,0) ; % sigma = 0 24 | for i=1:nlevels 25 | A{i,1} = A{i,1} * 1.5^(nlevels-i) ; % enhance fine detail 26 | end 27 | R(:,:,3) = iEAW(A,W,wave_type) ; 28 | 29 | R = hsv2rgb(R) ; 30 | 31 | R(R<0) = 0 ; 32 | R(R>1) = 1 ; 33 | 34 | subplot(2,3,2), imagesc(R), title('Regular Wavelets'), axis off ; drawnow 35 | 36 | R = I ; 37 | [A, W] = EAW(R(:,:,3),nlevels,wave_type,1,1) ; 38 | for i=1:nlevels 39 | A{i,1} = A{i,1} * 1.4^(nlevels-i) ; 40 | 41 | end 42 | R(:,:,3) = iEAW(A,W,wave_type) ; 43 | 44 | R = hsv2rgb(R) ; 45 | 46 | R(R<0) = 0 ; 47 | R(R>1) = 1 ; 48 | 49 | subplot(2,3,3), imagesc(R), title('Edge-Avoiding Wavelets'), axis off ; drawnow 50 | nlevels = floor(log2(min(size(I(:,:,1)))))-2 ; 51 | 52 | R = I ; 53 | [A, W] = EAW(R(:,:,3),nlevels,wave_type,1,0) ; 54 | for i=1:nlevels 55 | A{i,1} = A{i,1} * 0.7^(nlevels+1-i) ; % attenuate fine detail 56 | end 57 | R(:,:,3) = iEAW(A,W,wave_type) ; 58 | 59 | R = hsv2rgb(R) ; 60 | 61 | R(R<0) = 0 ; 62 | R(R>1) = 1 ; 63 | 64 | subplot(2,3,5), imagesc(R), title('Regular Wavelets'), axis off ; drawnow 65 | 66 | 67 | R = I ; 68 | [A, W] = EAW(R(:,:,3),nlevels,wave_type,1,1) ; 69 | for i=1:nlevels 70 | A{i,1} = A{i,1} * 0.7^(nlevels+1-i) ; 71 | end 72 | R(:,:,3) = iEAW(A,W,wave_type) ; 73 | 74 | R = hsv2rgb(R) ; 75 | 76 | R(R<0) = 0 ; 77 | R(R>1) = 1 ; 78 | 79 | subplot(2,3,6), imagesc(R), title('Edge-Avoiding Wavelets'), axis off ; drawnow 80 | -------------------------------------------------------------------------------- /EAW-TOG2009/Demo_EAW_Inter.m: -------------------------------------------------------------------------------- 1 | %%%%%%% Guided Edge-Aware Interpolation 2 | 3 | clear 4 | figure(2) 5 | 6 | S = imread('pflower.jpg'); 7 | S = double(S) / 255 ; 8 | G = imread('pflower.jpg'); 9 | G = double(G) / 255 ; 10 | [w, h, c] = size(S) ; 11 | nlevels = floor(log2(min(size(S(:,:,1))))) ; 12 | 13 | figure(2) 14 | subplot(2,2,1), imagesc(G), title('Input Image'), axis off, drawnow 15 | subplot(2,2,2), imagesc(S), title('Input Scribbles'), axis off, drawnow 16 | 17 | smth_factor = 0.125 ; 18 | 19 | wave_type = 1 ; 20 | 21 | [A, W] = EAW(G(:,:,1),nlevels,wave_type,1,0) ; % construction wavelets weights based on guiding BW image (A not needed) 22 | 23 | N = (abs(S(:,:,1) - S(:,:,2)) > 0.01) ; % extract scribbles 24 | 25 | for c=1:3 26 | tS = S(:,:,c) ; 27 | tS(~N) = 0; 28 | S(:,:,c) = tS ; 29 | end 30 | 31 | yuv = rgb2yuv(S) ; % operating on the UV of the YUV color space 32 | U = yuv(:,:,2) ; 33 | V = yuv(:,:,3) ; 34 | 35 | N = double(N) ; % normalization field 36 | 37 | Au = gEAW(U,W,wave_type) ; % Forward transform using weights W 38 | Av = gEAW(V,W,wave_type) ; 39 | An = gEAW(N,W,wave_type) ; 40 | 41 | for i=1:nlevels+1 42 | Au{i,1} = Au{i,1} * smth_factor^i ; 43 | Av{i,1} = Av{i,1} * smth_factor^i ; 44 | An{i,1} = An{i,1} * smth_factor^i ; 45 | end 46 | 47 | yuv(:,:,2) = igEAW(Au,W,wave_type) ; % inv transform using weight W 48 | yuv(:,:,3) = igEAW(Av,W,wave_type) ; 49 | N = igEAW(An,W,wave_type) ; 50 | 51 | 52 | N(N<1e-8) = 1 ; 53 | 54 | yuv(:,:,2) = yuv(:,:,2)./N; % normalize (like Shepard method) 55 | yuv(:,:,3) = yuv(:,:,3)./N; 56 | 57 | Y = rgb2yuv(G) ; 58 | yuv(:,:,1) = Y(:,:,1) ; % retrieve old Y channel 59 | C = yuv2rgb(yuv) ; 60 | 61 | C(C<0) = 0 ; 62 | C(C>1) = 1 ; 63 | 64 | subplot(2,2,3), imagesc(C), title('Regular Wavelets'), axis off, drawnow 65 | 66 | [A W] = EAW(G(:,:,1),nlevels,wave_type,1,1) ; 67 | 68 | N = (abs(S(:,:,1) - S(:,:,2)) > 0.01) ; % extracting scribbles 69 | 70 | for c=1:3 71 | tS = S(:,:,c) ; 72 | tS(~N) = 0; 73 | S(:,:,c) = tS ; 74 | end 75 | 76 | yuv = rgb2yuv(S) ; % operating on the UV of the YUV color space 77 | U = yuv(:,:,2) ; 78 | V = yuv(:,:,3) ; 79 | 80 | N = double(N) ; % normalization field 81 | 82 | Au = gEAW(U,W,wave_type) ; 83 | Av = gEAW(V,W,wave_type) ; 84 | An = gEAW(N,W,wave_type) ; 85 | 86 | for i=1:nlevels+1 87 | Au{i,1} = Au{i,1} * smth_factor^i ; 88 | Av{i,1} = Av{i,1} * smth_factor^i ; 89 | An{i,1} = An{i,1} * smth_factor^i ; 90 | end 91 | 92 | yuv(:,:,2) = igEAW(Au,W,wave_type) ; 93 | yuv(:,:,3) = igEAW(Av,W,wave_type) ; 94 | N = igEAW(An,W,wave_type) ; 95 | 96 | N(N<1e-8) = 1 ; 97 | 98 | yuv(:,:,2) = yuv(:,:,2)./N; % normalize (like Shepard method) 99 | yuv(:,:,3) = yuv(:,:,3)./N; 100 | 101 | 102 | Y = rgb2yuv(G) ; 103 | yuv(:,:,1) = Y(:,:,1) ; % retrieve old Y channel 104 | C = yuv2rgb(yuv) ; 105 | 106 | C(C<0) = 0 ; 107 | C(C>1) = 1 ; 108 | 109 | subplot(2,2,4), imagesc(C), title('Edge-Avoiding Wavelets'), axis off, drawnow 110 | -------------------------------------------------------------------------------- /EAW-TOG2009/Demo_EAW_smooth.m: -------------------------------------------------------------------------------- 1 | clear,close; 2 | 3 | Original_image_dir = '/Users/xujun/Desktop/YingkunHou/dataset/origin_images'; 4 | fpath = fullfile(Original_image_dir, '*.png'); 5 | im_dir = dir(fpath); 6 | im_num = length(im_dir); 7 | 8 | method = 'EAW'; 9 | %%%%%%% Detail Enhacement 10 | wave_type = 1; 11 | for i = 1:im_num 12 | I = double(imread(fullfile(Original_image_dir, im_dir(i).name)))/255; 13 | S = regexp(im_dir(i).name, '\.', 'split'); 14 | [w, h, c] = size(I) ; 15 | I = rgb2hsv(I) ; 16 | nlevels = floor(log2(min(size(I(:,:,1)))))-2 ; 17 | R = I ; 18 | [A, W] = EAW(R(:,:,3),nlevels,wave_type,1,1) ; 19 | for n=1:nlevels 20 | A{n,1} = A{n,1} * 0.7^(nlevels+1-n) ; 21 | end 22 | R(:,:,3) = iEAW(A,W,wave_type) ; 23 | R = hsv2rgb(R) ; 24 | R(R<0) = 0 ; 25 | R(R>1) = 1 ; 26 | fprintf('%s is done!\n', im_dir(i).name); 27 | outname = sprintf(['/Users/xujun/Desktop/YingkunHou/results/500images/' S{1} '_' method '.png']); 28 | imwrite(R, outname); 29 | end 30 | -------------------------------------------------------------------------------- /EAW-TOG2009/Demo_EAW_test.m: -------------------------------------------------------------------------------- 1 | % Egde-Avoiding Wavelets demo 2 | % 3 | % comparison to regular (1st generation) wavelets is implemnented 4 | % by setting sigma=0 5 | % 6 | % Shows (Guided) Edge-Aware Interpolation by colorization, detail 7 | % enhacement and edge-preservign detail suppression. 8 | % 9 | % This code implements the paper "Edge-Avoiding Wavelets and their 10 | % Applications" SIGGRAPH 2009. 11 | % 12 | % Code written by Raanan Fattal 13 | 14 | 15 | 16 | %%%%%%% Speed Check 17 | 18 | clear 19 | 20 | wave_type = 1 ; 21 | 22 | figure(1) 23 | clf 24 | colormap(gray(256)) ; 25 | 26 | I = imread('pflower.jpg'); 27 | I = double(I) / 255 ; 28 | [w, h, c] = size(I) ; 29 | nlevels = floor(log2(min(size(I(:,:,1)))))-2 ; 30 | 31 | figure(1) 32 | 33 | 34 | A = cell(nlevels+1,3) ; 35 | W = cell(nlevels,3) ; 36 | 37 | nc = 3 ; 38 | 39 | for k=1:3 40 | R=I ; 41 | for i=1:nlevels 42 | [tA, tW] = EAW(R,1,wave_type,1,1) ; % process a single level at a time 43 | % (not really needed - it's just for 44 | % this demo) 45 | for c=1:nc 46 | A{i,c} = tA{1,c} ; 47 | W{i,c} = tW{1,c} ; 48 | end 49 | 50 | R = reshape([tA{2,1} tA{2,2} tA{2,3}],size(tA{2,1},1),size(tA{2,1},2),3) ; 51 | 52 | R(R>1)=1; 53 | R(R<0)=0; 54 | imagesc(R) 55 | drawnow 56 | end 57 | title('Forward Transform Speed Check') 58 | drawnow 59 | end 60 | pause(0.1) 61 | -------------------------------------------------------------------------------- /EAW-TOG2009/EAW.m: -------------------------------------------------------------------------------- 1 | % 2 | % Forward Edge-Avoiding Wavelet Transform 3 | % 4 | % Input: 5 | % I - 2D image (must have its values between 0 and 1) 6 | % nlevels - number of transformation levels (each is full octave) 7 | % wavelet_type - 0 for seperable wavelets and 1 for Red-Black wavelets 8 | % dist_func - 0 for exp(-(I-J)^2/sigma^2) and 1 for 1/(|I-J|^sigma+eps) 9 | % sigma - sets the range scale used in the pixel-range distance function 10 | % 11 | % Output: 12 | % A - (cell array) approximation and detail coeficients (approx. 13 | % not really needed), 14 | % W - (cell array) wavelets weights 15 | % 16 | % This code implements the paper "Edge-Avoiding Wavelets and their 17 | % Applications" from SIGGRAPH 2009. 18 | % 19 | % Code written by Raanan Fattal 20 | 21 | function [A, W] = EAW(I, nlevels, wavelet_type, dist_func, sigma) 22 | 23 | nc = size(I,3) ; 24 | 25 | A = cell(nlevels+1,nc) ; 26 | W = cell(nlevels,nc) ; 27 | 28 | for c=1:nc 29 | J = I(:,:,c) ; 30 | for i=1:nlevels 31 | [J tW] = eaw(J,wavelet_type,dist_func,sigma) ; 32 | A{i,c} = J ; 33 | J = J(1:2:end,1:2:end) ; 34 | W{i,c} = tW ; 35 | end 36 | 37 | A{nlevels+1,c} = J ; 38 | end 39 | 40 | -------------------------------------------------------------------------------- /EAW-TOG2009/eaw.cpp: -------------------------------------------------------------------------------- 1 | #include "mex.h" 2 | #include "matrix.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | #include "eaw_imp.h" 11 | 12 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { 13 | 14 | if(nrhs != 4) 15 | mexErrMsgIdAndTxt( "MATLAB:convec:invalidNumInputs", 16 | "image wavelet_type dist_type sigma."); 17 | 18 | if(nlhs > 4) 19 | mexErrMsgIdAndTxt( "MATLAB:convec:maxlhs", 20 | "Too many output arguments."); 21 | 22 | if(!mxIsDouble(prhs[0]) || mxIsComplex(prhs[1]) ) 23 | mexErrMsgIdAndTxt( "MATLAB:convec:inputsNotComplex", 24 | "Must be double and real."); 25 | 26 | 27 | Grid I(prhs[0]); 28 | Grid A, W ; 29 | 30 | int wtype = mxGetPr(prhs[1])[0]; 31 | int distf = mxGetPr(prhs[2])[0]; 32 | double sigma = mxGetPr(prhs[3])[0]; 33 | 34 | if(distf) 35 | init(sigma) ; 36 | else 37 | init_exp(sigma) ; 38 | 39 | if(wtype) 40 | WRB(I, A, W); 41 | else 42 | SPW(I, A, W) ; 43 | 44 | plhs[0] = A.mxa ; 45 | plhs[1] = W.mxa ; 46 | } 47 | -------------------------------------------------------------------------------- /EAW-TOG2009/eaw.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/EAW-TOG2009/eaw.mexa64 -------------------------------------------------------------------------------- /EAW-TOG2009/eaw.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/EAW-TOG2009/eaw.mexglx -------------------------------------------------------------------------------- /EAW-TOG2009/eaw.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/EAW-TOG2009/eaw.mexmaci64 -------------------------------------------------------------------------------- /EAW-TOG2009/gEAW.m: -------------------------------------------------------------------------------- 1 | % 2 | % Guided Edge-Avoiding Wavelet Transform 3 | % 4 | % Input: 5 | % I - 2D image (must have its values between 0 and 1) 6 | % W - Guided wavelets weights 7 | % wavelet_type - 0 for seperable wavelets and 1 for Red-Black wavelets 8 | % 9 | % Output: 10 | % A - (cell array) approximation and detail coeficients 11 | % 12 | % This code implements the paper "Edge-Avoiding Wavelets and their 13 | % Applications" from SIGGRAPH 2009. 14 | % 15 | % Code written by Raanan Fattal 16 | 17 | function [A W] = gEAW(I, W, wavelet_type) 18 | 19 | nlevels = size(W,1) ; 20 | 21 | nc = size(I,3) ; 22 | 23 | A = cell(nlevels+1,nc) ; 24 | 25 | for c=1:nc 26 | J = I(:,:,c) ; 27 | A{1,c} = J ; 28 | for i=1:nlevels 29 | J = geaw(J,W{i,c},wavelet_type) ; 30 | J = J(1:2:end,1:2:end) ; 31 | A{i+1,c} = J ; 32 | 33 | 34 | end 35 | end 36 | 37 | -------------------------------------------------------------------------------- /EAW-TOG2009/geaw.cpp: -------------------------------------------------------------------------------- 1 | #include "mex.h" 2 | #include "matrix.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | #include "eaw_imp.h" 11 | 12 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { 13 | 14 | if(nrhs != 3) 15 | mexErrMsgIdAndTxt( "MATLAB:convec:invalidNumInputs", 16 | "image weights wavelet_type."); 17 | 18 | if(nlhs > 3) 19 | mexErrMsgIdAndTxt( "MATLAB:convec:maxlhs", 20 | "Too many output arguments."); 21 | 22 | if(!mxIsDouble(prhs[0]) || mxIsComplex(prhs[1]) ) 23 | mexErrMsgIdAndTxt( "MATLAB:convec:inputsNotComplex", 24 | "Must be double and real."); 25 | 26 | 27 | Grid I(prhs[0]); 28 | Grid W(prhs[1]); 29 | Grid A ; 30 | 31 | int wtype = mxGetPr(prhs[2])[0]; 32 | 33 | //if(wtype) 34 | WRBg(I, A, W) ; 35 | //else 36 | //SPWg(I, A, W) ; 37 | 38 | plhs[0] = A.mxa ; 39 | } 40 | -------------------------------------------------------------------------------- /EAW-TOG2009/geaw.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/EAW-TOG2009/geaw.mexa64 -------------------------------------------------------------------------------- /EAW-TOG2009/geaw.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/EAW-TOG2009/geaw.mexglx -------------------------------------------------------------------------------- /EAW-TOG2009/geaw.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/EAW-TOG2009/geaw.mexmaci64 -------------------------------------------------------------------------------- /EAW-TOG2009/iEAW.m: -------------------------------------------------------------------------------- 1 | % 2 | % Backward Edge-Avoiding Wavelet Transform 3 | % 4 | % Input: 5 | % A - (cell array) approximation and detail coeficients 6 | % W - (cell array) wavelets weights 7 | % wavelet_type - 0 for seperable wavelets and 1 for Red-Black wavelets 8 | % 9 | % Output: 10 | % I - 2D image 11 | % 12 | % This code implements the paper "Edge-Avoiding Wavelets and their 13 | % Applications" from SIGGRAPH 2009. 14 | % 15 | % Code written by Raanan Fattal 16 | 17 | function I = iEAW(A,W,wavelet_type) 18 | 19 | nc = size(A,2) ; 20 | 21 | nlevels = size(W,1) ; 22 | 23 | for c=1:nc 24 | J = A{nlevels+1,c} ; 25 | 26 | for i=nlevels:-1:1 27 | A{i,c}(1:2:end,1:2:end) = J ; 28 | 29 | J = ieaw(A{i,c},W{i,c},wavelet_type) ; 30 | end 31 | I(:,:,c) = J ; 32 | end 33 | 34 | -------------------------------------------------------------------------------- /EAW-TOG2009/ieaw.cpp: -------------------------------------------------------------------------------- 1 | #include "mex.h" 2 | #include "matrix.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | #include "eaw_imp.h" 11 | 12 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { 13 | 14 | if(nrhs != 3) 15 | mexErrMsgIdAndTxt( "MATLAB:convec:invalidNumInputs", 16 | "image weights wavelet_type"); 17 | 18 | if(nlhs > 4) 19 | mexErrMsgIdAndTxt( "MATLAB:convec:maxlhs", 20 | "Too many output arguments."); 21 | 22 | if(!mxIsDouble(prhs[0]) || mxIsComplex(prhs[1]) ) 23 | mexErrMsgIdAndTxt( "MATLAB:convec:inputsNotComplex", 24 | "Must be double and real."); 25 | 26 | 27 | Grid I(prhs[0]) ; 28 | Grid W(prhs[1]) ; 29 | 30 | Grid A ; 31 | 32 | int wtype = mxGetPr(prhs[2])[0]; 33 | 34 | if(wtype) 35 | iWRB(I, A, W); 36 | else 37 | iSPW(I, A, W) ; 38 | 39 | plhs[0] = A.mxa; 40 | } 41 | -------------------------------------------------------------------------------- /EAW-TOG2009/ieaw.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/EAW-TOG2009/ieaw.mexa64 -------------------------------------------------------------------------------- /EAW-TOG2009/ieaw.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/EAW-TOG2009/ieaw.mexglx -------------------------------------------------------------------------------- /EAW-TOG2009/ieaw.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/EAW-TOG2009/ieaw.mexmaci64 -------------------------------------------------------------------------------- /EAW-TOG2009/igEAW.m: -------------------------------------------------------------------------------- 1 | % 2 | % Backward Guided Edge-Avoiding Wavelet Transform 3 | % 4 | % Input: 5 | % A - (cell array) approximation and detail coeficients 6 | % W - (cell array) wavelets weights 7 | % wavelet_type - 0 for seperable wavelets and 1 for Red-Black wavelet 8 | % 9 | % Output: 10 | % I - 2D image 11 | % 12 | % This code implements the paper "Edge-Avoiding Wavelets and their 13 | % Applications" from SIGGRAPH 2009. 14 | % 15 | % Code written by Raanan Fattal 16 | 17 | function I = igEAW(A,W,wavelet_type) 18 | 19 | nc = size(A,2) ; 20 | 21 | nlevels = size(W,1) ; 22 | 23 | for c=1:nc 24 | J = A{nlevels+1,c} ; 25 | 26 | for i=nlevels:-1:1 27 | Jt = zeros(size(A{i,c})) ; 28 | Jt(1:2:end,1:2:end) = J ; 29 | Jt = Jt + A{i,c} ; 30 | J = igeaw(Jt,W{i,c},wavelet_type) ; 31 | end 32 | I(:,:,c) = J ; 33 | end 34 | 35 | -------------------------------------------------------------------------------- /EAW-TOG2009/igeaw.cpp: -------------------------------------------------------------------------------- 1 | #include "mex.h" 2 | #include "matrix.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | #include "eaw_imp.h" 11 | 12 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { 13 | 14 | if(nrhs != 3) 15 | mexErrMsgIdAndTxt( "MATLAB:convec:invalidNumInputs", 16 | "image weights wavelet_type"); 17 | 18 | if(nlhs > 3) 19 | mexErrMsgIdAndTxt( "MATLAB:convec:maxlhs", 20 | "Too many output arguments."); 21 | 22 | if(!mxIsDouble(prhs[0]) || mxIsComplex(prhs[1]) ) 23 | mexErrMsgIdAndTxt( "MATLAB:convec:inputsNotComplex", 24 | "Must be double and real."); 25 | 26 | 27 | Grid I(prhs[0]) ; 28 | Grid W(prhs[1]) ; 29 | Grid A ; 30 | 31 | int wtype = mxGetPr(prhs[2])[0]; 32 | 33 | //if(wtype) 34 | iWRBg(I, A, W); 35 | //else 36 | // igSPW(I, A, W) ; 37 | 38 | plhs[0] = A.mxa; 39 | } 40 | -------------------------------------------------------------------------------- /EAW-TOG2009/igeaw.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/EAW-TOG2009/igeaw.mexa64 -------------------------------------------------------------------------------- /EAW-TOG2009/igeaw.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/EAW-TOG2009/igeaw.mexmaci64 -------------------------------------------------------------------------------- /EAW-TOG2009/makefile.m: -------------------------------------------------------------------------------- 1 | mex -largeArrayDims -O eaw.cpp 2 | mex -largeArrayDims -O ieaw.cpp 3 | mex -largeArrayDims -O geaw.cpp 4 | mex -largeArrayDims -O igeaw.cpp 5 | -------------------------------------------------------------------------------- /EAW-TOG2009/rgb2yuv.m: -------------------------------------------------------------------------------- 1 | function J = rgb2yuv(I) 2 | 3 | M = [0.299 0.587 0.114 ; -0.147 -0.289 0.436 ; 0.615 -0.515 -0.1] ; 4 | 5 | for c=1:3 6 | J(:,:,c) = M(c,1) * I(:,:,1) + M(c,2) * I(:,:,2) + M(c,3) * I(:,:,3) ; 7 | end 8 | -------------------------------------------------------------------------------- /EAW-TOG2009/yuv2rgb.m: -------------------------------------------------------------------------------- 1 | function J = yuv2rgb(I) 2 | 3 | M = inv([0.299 0.587 0.114 ; -0.147 -0.289 0.436 ; 0.615 -0.515 -0.1]) ; 4 | 5 | for c=1:3 6 | J(:,:,c) = M(c,1) * I(:,:,1) + M(c,2) * I(:,:,2) + M(c,3) * I(:,:,3) ; 7 | end 8 | -------------------------------------------------------------------------------- /FGS-TIP2014/Demo.m: -------------------------------------------------------------------------------- 1 | close all; 2 | clc; 3 | 4 | %% Edge-preserving smoothing example 5 | 6 | % % sigma = 0.1 7 | % % lambda = 30^2 8 | % % iteration = 3 9 | % % attenuation = 4 10 | img = imread('noisy_13.png'); 11 | F = FGS(img, 0.1, 30^2, [], 3, 4); 12 | figure,imshow(F); 13 | 14 | 15 | % % sigma = 0.03 16 | % % lambda = 20^2 17 | % % iteration = 3 (default) 18 | % % attenuation = 4 (default) 19 | % img = imread('lamp.jpg'); 20 | % F = FGS(img, 0.03, 20^2); 21 | % figure,imshow(F); -------------------------------------------------------------------------------- /FGS-TIP2014/FGS.m: -------------------------------------------------------------------------------- 1 | % FGS Fast global image smoother. 2 | % 3 | % F = FGS(img, sigma, lambda, joint_image, num_iterations, attenuation) 4 | % 5 | % Parameters: 6 | % img Input image to be filtered [0,255]. 7 | % sigma Filter range standard deviation. 8 | % lambda Filter lambda. 9 | % joint_image (optional) Guidance image for joint filtering [0,255]. 10 | % num_iterations (optional) Number of iterations to perform (default: 3). 11 | % attenuation (optional) attenuation factor for iteration (default: 4). 12 | % 13 | % This is the reference implementation of the fast global image smoother 14 | % described in the paper: 15 | % 16 | % Fast Global Image Smoothing based on Weighted Least Squares 17 | % D. Min, S. Choi, J. Lu, B. Ham, K. Sohn, and M. N. Do, 18 | % IEEE Trans. Image Processing, vol. no. pp., 2014. 19 | % 20 | % Please refer to the publication above if you use this software. For an 21 | % up-to-date version go to: 22 | % 23 | % https://sites.google.com/site/globalsmoothing/ 24 | % 25 | % THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY EXPRESSED OR IMPLIED WARRANTIES 26 | % OF ANY KIND, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | % FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | % AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | % LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | % OUT OF OR IN CONNECTION WITH THIS SOFTWARE OR THE USE OR OTHER DEALINGS IN 31 | % THIS SOFTWARE. 32 | % 33 | % Version 1.0 - December 2014. 34 | 35 | function F = FGS(img, sigma, lambda, joint_image, num_iterations, attenuation) 36 | 37 | I = double(img); 38 | 39 | if ~exist('num_iterations', 'var') 40 | num_iterations = 3; 41 | end 42 | 43 | if ~exist('attenuation', 'var') 44 | attenuation = 4; 45 | end 46 | 47 | 48 | if exist('joint_image', 'var') && ~isempty(joint_image) 49 | J = double(joint_image); 50 | 51 | if (size(I,1) ~= size(J,1)) || (size(I,2) ~= size(J,2)) 52 | error('Input and joint images must have equal width and height.'); 53 | end 54 | else 55 | J = []; 56 | end 57 | 58 | %% The code-optimized mex version only supports 1- or 3-channels input images 59 | if (size(I,3) ~= 1 && size(I,3) ~= 3) || (size(J,3) ~= 1 && size(J,3) ~= 3) 60 | error('FGS only supports 1- or 3-channel images.'); 61 | end 62 | F = mexFGS(I, J, sigma, lambda, num_iterations, attenuation); 63 | 64 | %% The intuitive mex version 65 | % F = mexFGS_simple(I, J, sigma, lambda, num_iterations, attenuation); 66 | 67 | %% Return the result 68 | F = cast(F, class(img)); 69 | 70 | end -------------------------------------------------------------------------------- /FGS-TIP2014/README_FGS.txt: -------------------------------------------------------------------------------- 1 | This software provides the reference implementation of the fast global image smoother described in the paper: 2 | 3 | Fast Global Image Smoothing based on Weighted Least Squares 4 | D. Min, S. Choi, J. Lu, B. Ham, K. Sohn, and M. N. Do, 5 | IEEE Trans. Image Processing, vol. 23, no. 12, pp. 5638-5653, Dec. 2014. 6 | 7 | Please cite the paper above if you use this software. For an up-to-date version, refer to: 8 | https://sites.google.com/site/globalsmoothing/ 9 | 10 | Only 'Algorithm 1' of the paper was implemented in this software. Note that other functions such as sparse data interpolation, L_gamma norm smoothing with the iterative re-weighted least squares (IRLS) algorithm, and robust smoothing using aggregated data term are not provided. 11 | 12 | It supports both a pure filtering (with 'img') and a joint filtering (with 'img' and 'guide_img'). 13 | For instance, in 'Demo.m', 14 | Pure filtering, 'F = FGS(img, 0.1, 30^2, [], 3, 4);' 15 | Joint filtering, 'F = FGS(img, 0.1, 30^2, guide_img, 3, 4);' 16 | 17 | The code was implemented using C++ with a MATLAB interface (mex file). Please compile C++ files by running 'compile.m' or using the following command: 'mex mexFGS_simple.cpp' or 'mex mexFGS.cpp'. 18 | 19 | 'mexFGS_simple.cpp': an intuitive code that works for an input image and a guidance image with an arbitrary number of color channels. The smoothing function of this code is slower than that of 'mexFGS.cpp'. 20 | 21 | 'mexFGS.cpp': an optimized code used for measuring the runtime of Table I in the paper. The smoothing function works for the following cases only. 22 | 'FGS()': input image with 3-ch and guidance image with 3-ch 23 | 'FGS_single()': input image with 1-ch and guidance image with 1-ch 24 | 'FGS_13()': input image with 1-ch and guidance image with 3-ch 25 | 'FGS_31()': input image with 3-ch and guidance image with 1-ch 26 | -------------------------------------------------------------------------------- /FGS-TIP2014/compile.m: -------------------------------------------------------------------------------- 1 | % tested under Windows7 64bit, MSVC v10.0 compiler 2 | mex OPTIMFLAGS="/Ox /Oi /Oy /DNDEBUG /fp:fast /arch:SSE2 /DMEX_MODE" mexFGS.cpp 3 | mex OPTIMFLAGS="/Ox /Oi /Oy /DNDEBUG /fp:fast /arch:SSE2 /DMEX_MODE" mexFGS_simple.cpp -------------------------------------------------------------------------------- /FGS-TIP2014/mexFGS.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/FGS-TIP2014/mexFGS.mexa64 -------------------------------------------------------------------------------- /FGS-TIP2014/mexFGS.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/FGS-TIP2014/mexFGS.mexw64 -------------------------------------------------------------------------------- /FGS-TIP2014/mexFGS_simple.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "mex.h" 6 | 7 | #define SQ(x) ((x)*(x)) 8 | 9 | int W, H; // image width, height 10 | int nChannels, nChannels_guide; 11 | double *BLFKernelI; // Kernel LUT 12 | 13 | // Main functions 14 | void prepareBLFKernel(double sigma); 15 | void FGS_simple(double ***image, double ***joint_image, double sigma, double lambda, int solver_iteration, double solver_attenuation); 16 | void solve_tridiagonal_in_place_destructive(double x[], const size_t N, const double a[], const double b[], double c[]); 17 | 18 | // Memory management 19 | double *** memAllocDouble3(int n,int r,int c); 20 | double** memAllocDouble2(int r,int c); 21 | void memFreeDouble3(double ***p); 22 | void memFreeDouble2(double **p); 23 | 24 | 25 | // Build LUT for bilateral kernel weight 26 | void prepareBLFKernel(double sigma) 27 | { 28 | const int MaxSizeOfFilterI = 195075; 29 | BLFKernelI = (double *)malloc(sizeof(double)*MaxSizeOfFilterI); 30 | 31 | for(int m=0;m 2) 48 | nChannels = mxGetDimensions(img)[2]; 49 | else 50 | nChannels = 1; 51 | 52 | // FGS parameters 53 | double sigma = mxGetScalar(prhs[2]); 54 | double lambda = mxGetScalar(prhs[3]); 55 | int solver_iteration = (int)mxGetScalar(prhs[4]); 56 | double solver_attenuation = mxGetScalar(prhs[5]); 57 | 58 | mexPrintf("Image resolution: %d x %d x %d\n", W, H, nChannels); 59 | mexPrintf("Parameters:\n"); 60 | mexPrintf(" Sigma = %f\n", sigma); 61 | mexPrintf(" Lambda = %f\n", lambda); 62 | mexPrintf(" Iteration = %d\n", solver_iteration); 63 | mexPrintf(" Attenuation = %f\n", solver_attenuation); 64 | 65 | // Image buffer preperation 66 | double*** image_filtered = memAllocDouble3(H, W, nChannels); 67 | double* ptr_image = (double*)mxGetPr(img); 68 | double* ptr_image_array = image_filtered[0][0]; 69 | for(int y=0;y 2) 81 | nChannels_guide = mxGetDimensions(imgGuide)[2]; 82 | else 83 | nChannels_guide = 1; 84 | 85 | mexPrintf("Joint filtering mode: %d x %d x %d\n", W, H, nChannels_guide); 86 | image_guidance = memAllocDouble3(H, W, nChannels_guide); 87 | 88 | double* ptr_guidance = (double*)mxGetPr(imgGuide); 89 | double* ptr_guidance_array = image_guidance[0][0]; 90 | for(int y=0;y= 0; n--) 233 | x[n] = x[n] - c[n] * x[n + 1]; 234 | } 235 | 236 | double *** memAllocDouble3(int n,int r,int c) 237 | { 238 | int padding=10; 239 | double *a,**p,***pp; 240 | int rc=r*c; 241 | int i,j; 242 | a=(double*) malloc(sizeof(double)*(n*rc+padding)); 243 | if(a==NULL) {mexErrMsgTxt("memAllocDouble: Memory is too huge.\n"); } 244 | p=(double**) malloc(sizeof(double*)*n*r); 245 | pp=(double***) malloc(sizeof(double**)*n); 246 | for(i=0;i1 48 | Denormin2 = repmat(Denormin2,[1,1,D]); 49 | end 50 | beta = 2*lambda; 51 | while beta < betamax 52 | Denormin = 1 + beta*Denormin2; 53 | % h-v subproblem 54 | h = [diff(S,1,2), S(:,1,:) - S(:,end,:)]; 55 | v = [diff(S,1,1); S(1,:,:) - S(end,:,:)]; 56 | if D==1 57 | t = (h.^2+v.^2) sigma_r,[1 1 3]); 143 | inew = ~isedge.*rd + isedge.*re; 144 | end 145 | 146 | % grayscale remapping function 147 | function inew = r_gray(i,g0,sigma_r,fd,fe) 148 | dnrm = abs(i-g0); 149 | dsgn = sign(i-g0); 150 | % detail and edge processing 151 | rd = g0 + dsgn*sigma_r.*fd(dnrm/sigma_r); 152 | re = g0 + dsgn.*(fe(dnrm - sigma_r) + sigma_r); 153 | % edge-detail separation based on sigma_r threshold 154 | isedge = dnrm > sigma_r; 155 | inew = ~isedge.*rd + isedge.*re; 156 | end 157 | 158 | end 159 | -------------------------------------------------------------------------------- /LLF-TOG2011/lapfilter_core.m: -------------------------------------------------------------------------------- 1 | % Laplacian Filtering 2 | % - public Matlab implementation for reproducibility 3 | % - about 30x slower than our single-thread C++ version 4 | % 5 | % This script implements the core image processing algorithm 6 | % described in Paris, Hasinoff, and Kautz, "Local Laplacian Filters: 7 | % Edge-aware Image Processing with a Laplacian Pyramid", ACM 8 | % Transactions on Graphics (Proc. SIGGRAPH 2011), 30(4), 2011. 9 | % 10 | % Processes an input image using a general pointwise remapping function 11 | % r(I,g0) in a pyramid-based way. Its running time is O(N log N), where 12 | % N is the number of pixels. 13 | % 14 | % Most of the code is bookkeeping to isolate the subpyramid contributing 15 | % to a particular Laplacian coefficient. See below for a 14-line naive 16 | % O(N^2) implementation that gives identical results. 17 | % 18 | % Arguments: 19 | % image 'I' 20 | % pixel-wise remapping function 'r', expects arguments r(I,g0) 21 | % 22 | % sam.hasinoff@gmail.com, March 2011 23 | % 24 | 25 | function R = lapfilter_core(I,r) 26 | 27 | G = gaussian_pyramid(I); % compute input Gaussian pyramid 28 | 29 | % build up the result, one Laplacian coefficient at a time 30 | L = laplacian_pyramid(zeros(size(I))); % allocate space for result 31 | tic; 32 | for lev0 = 1:length(L)-1 33 | hw = 3*2^lev0 - 2; % half-width of full-res footprint (conservative) 34 | fprintf('level %d (%dx%d), footprint %dx%d ... 0%',lev0,size(G{lev0},1),size(G{lev0},2),min(2*hw+1,size(I,1)),min(2*hw+1,size(I,2))); 35 | for y0 = 1:size(G{lev0},1) 36 | for x0 = 1:size(G{lev0},2) 37 | % coords in full-res image corresponding to (lev0,y0,x0) 38 | yf = (y0-1)*2^(lev0-1) + 1; 39 | xf = (x0-1)*2^(lev0-1) + 1; 40 | % subwindow in full-res image needed to evaluate (lev0,y0,x0) in result 41 | yrng = [max(1,yf-hw) min(size(I,1),yf+hw)]; 42 | xrng = [max(1,xf-hw) min(size(I,2),xf+hw)]; 43 | Isub = I(yrng(1):yrng(2),xrng(1):xrng(2),:); 44 | 45 | % use the corresponding Gaussian pyramid coefficient to remap 46 | % the full-res subwindow 47 | g0 = G{lev0}(y0,x0,:); 48 | Iremap = r(Isub,g0); 49 | % compute Laplacian pyramid for remapped subwindow 50 | Lremap = laplacian_pyramid(Iremap,lev0+1,[yrng xrng]); 51 | 52 | % bookkeeping to compute index of (lev0,y0,x0) within the 53 | % subwindow, at full-res and at current pyramid level 54 | yfc = yf - yrng(1) + 1; 55 | xfc = xf - xrng(1) + 1; 56 | yfclev0 = floor((yfc-1)/2^(lev0-1)) + 1; 57 | xfclev0 = floor((xfc-1)/2^(lev0-1)) + 1; 58 | 59 | % set coefficient in result based on the corresponding 60 | % coefficient in the remapped pyramid 61 | L{lev0}(y0,x0,:) = Lremap{lev0}(yfclev0,xfclev0,:); 62 | end 63 | fprintf('\b\b\b\b%3d%%',floor(y0/size(G{lev0},1)*100)); 64 | end 65 | fprintf('\n'); 66 | end 67 | L{end} = G{end}; % residual not affected 68 | R = reconstruct_laplacian_pyramid(L); % collapse result Laplacian pyramid 69 | toc; 70 | 71 | end 72 | 73 | %% naive O(N^2) version for reference 74 | % 75 | % G = gaussian_pyramid(I); 76 | % L = laplacian_pyramid(zeros(size(I))); 77 | % for lev0 = 1:length(L)-1 78 | % for y0 = 1:size(G{lev0},1) 79 | % for x0 = 1:size(G{lev0},2) 80 | % g0 = G{lev0}(y0,x0,:); 81 | % Iremap = r(I,g0); 82 | % Lremap = laplacian_pyramid(Iremap,lev0+1); 83 | % L{lev0}(y0,x0,:) = Lremap{lev0}(y0,x0,:); 84 | % end 85 | % end 86 | % end 87 | % L{end} = G{end}; 88 | % R = reconstruct_laplacian_pyramid(L); 89 | -------------------------------------------------------------------------------- /LLF-TOG2011/lapfilter_demo.m: -------------------------------------------------------------------------------- 1 | %% example: detail manipulation 2 | 3 | fn_in = 'pflower.jpg'; 4 | I = double( imread(fn_in) )/255; 5 | I = min(1,max(0, imresize(I,1/4) )); % downscale, Matlab version is slow 6 | 7 | figure; imshow(I); set(gcf,'name',fn_in) 8 | 9 | sigma_r = 0.4; 10 | alpha = 0.25; 11 | beta = 1; 12 | colorRemapping = 'rgb'; 13 | domain = 'lin'; 14 | R = lapfilter(I,sigma_r,alpha,beta,colorRemapping,domain); 15 | figure; clf; imshow(R); 16 | 17 | %% example: tone manipulation 18 | 19 | fn_in = 'input_hdr/doll.hdr'; 20 | I = double( hdrread(fn_in) ); 21 | I = I(245:500,50:272,:); % crop, Matlab version is slow 22 | 23 | Igamma = lapfilter(I,0,1,1,'lum','log'); % simple gamma tonemapping 24 | figure; imshow(Igamma); set(gcf,'name',fn_in) 25 | 26 | sigma_r = 2.5; 27 | alpha = 1; 28 | beta = 0; 29 | colorRemapping = 'lum'; 30 | domain = 'log'; 31 | R = lapfilter(I,sigma_r,alpha,beta,colorRemapping,domain); 32 | figure; clf; imshow(R); 33 | 34 | %% generate supplementary material: detail manipulation 35 | 36 | beta = 1; 37 | colorRemapping = 'rgb'; 38 | domain = 'lin'; 39 | 40 | srcdir = 'input_png/'; 41 | fnlist = dir([srcdir,'*.png']); 42 | mkdir('results_detail') 43 | for F = 1:length(fnlist) 44 | fn_in = [srcdir,fnlist(F).name] 45 | I = double( imread(fn_in) )/255; 46 | %figure; imshow(I); set(gcf,'name',fn_in) 47 | 48 | for sigma_r = [0.1 0.2 0.4] 49 | for alpha = [0.25 0.5 2 4] 50 | R = lapfilter(I,sigma_r,alpha,beta,colorRemapping,domain); 51 | fn_out = sprintf('results_detail/%s_%s_%s_s%g_a%g_b%g.png',fnlist(F).name(1:end-4),colorRemapping,domain,sigma_r,alpha,beta) 52 | imwrite(R,fn_out) 53 | %figure; clf; imshow(R); set(gcf,'name',fn_out) 54 | end 55 | end 56 | end 57 | 58 | %% generate supplementary material: tone manipulation 59 | 60 | sigma_r = 2.5; 61 | colorRemapping = 'lum'; 62 | domain = 'log'; 63 | 64 | srcdir = 'input_hdr/'; 65 | fnlist = dir([srcdir,'*.hdr']); 66 | mkdir('results_hdr') 67 | for F = 1:length(fnlist) 68 | fn_in = [srcdir,fnlist(F).name] 69 | I = double( hdrread(fn_in) ); 70 | %figure; imshow(I); set(gcf,'name',fn_in) 71 | 72 | for alpha = [0.25 0.5 0.75 1] 73 | for beta = [0 0.3 0.6] 74 | R = lapfilter(I,sigma_r,alpha,beta,colorRemapping,domain); 75 | fn_out = sprintf('results_hdr/%s_%s_%s_s%g_a%g_b%g.png',fnlist(F).name(1:end-4),colorRemapping,domain,sigma_r,alpha,beta) 76 | imwrite(R,fn_out) 77 | %figure; clf; imshow(R); set(gcf,'name',fn_out) 78 | end 79 | end 80 | 81 | alpha = 1; 82 | beta = 1; 83 | R = lapfilter(I,sigma_r,alpha,beta,colorRemapping,domain); 84 | fn_out = sprintf('results_hdr/%s.png',fnlist(F).name(1:end-4)) 85 | imwrite(R,fn_out) 86 | end 87 | 88 | srcdir = 'input_hdr_large/'; 89 | fnlist = dir([srcdir,'*.hdr']); 90 | mkdir('results_hdr_large') 91 | for F = 1:length(fnlist) 92 | fn_in = [srcdir,fnlist(F).name] 93 | I = double( hdrread(fn_in) ); 94 | %figure; imshow(I); set(gcf,'name',fn_in) 95 | 96 | for alpha = [0.25 1] 97 | for beta = [0] 98 | R = lapfilter(I,sigma_r,alpha,beta,colorRemapping,domain); 99 | fn_out = sprintf('results_hdr_large/%s_%s_%s_s%g_a%g_b%g.png',fnlist(F).name(1:end-4),colorRemapping,domain,sigma_r,alpha,beta) 100 | imwrite(R,fn_out) 101 | %figure; clf; imshow(R); set(gcf,'name',fn_out) 102 | end 103 | end 104 | 105 | alpha = 1; 106 | beta = 1; 107 | R = lapfilter(I,sigma_r,alpha,beta,colorRemapping,domain); 108 | fn_out = sprintf('results_hdr_large/%s.png',fnlist(F).name(1:end-4)) 109 | imwrite(R,fn_out) 110 | end 111 | 112 | %% generate supplementary material: inverse tone mapping 113 | 114 | sigma_r = 2.5; 115 | colorRemapping = 'lum'; 116 | domain = 'log'; 117 | alpha = 1; 118 | beta = 2.5; 119 | 120 | srcdir = 'input_png/'; 121 | fnlist = dir([srcdir,'*.png']); 122 | mkdir('results_ihdr') 123 | for F = 1:length(fnlist) 124 | fn_in = [srcdir,fnlist(F).name] 125 | I = (double( imread(fn_in) )/255) .^ 2.2; % apply gamma to linearize 126 | %figure; imshow(I); set(gcf,'name',fn_in) 127 | 128 | R = lapfilter(I,sigma_r,alpha,beta,colorRemapping,domain); 129 | fn_out = sprintf('results_ihdr/%s_%s_%s_s%g_a%g_b%g.hdr',fnlist(F).name(1:end-4),colorRemapping,domain,sigma_r,alpha,beta) 130 | hdrwrite(R,fn_out) 131 | end 132 | -------------------------------------------------------------------------------- /LLF-TOG2011/laplacian_pyramid.m: -------------------------------------------------------------------------------- 1 | % Contruction of Laplacian pyramid 2 | % 3 | % Arguments: 4 | % image 'I' 5 | % 'nlev', number of levels in the pyramid (optional) 6 | % subwindow indices 'subwindow', given as [r1 r2 c1 c2] (optional) 7 | % 8 | % tom.mertens@gmail.com, August 2007 9 | % sam.hasinoff@gmail.com, March 2011 [modified to handle subwindows] 10 | % 11 | % 12 | % More information: 13 | % 'The Laplacian Pyramid as a Compact Image Code' 14 | % Burt, P., and Adelson, E. H., 15 | % IEEE Transactions on Communication, COM-31:532-540 (1983). 16 | % 17 | 18 | function pyr = laplacian_pyramid(I,nlev,subwindow) 19 | 20 | r = size(I,1); 21 | c = size(I,2); 22 | if ~exist('subwindow','var') 23 | subwindow = [1 r 1 c]; 24 | end 25 | if ~exist('nlev','var') 26 | nlev = numlevels([r c]); % build highest possible pyramid 27 | end 28 | 29 | % recursively build pyramid 30 | pyr = cell(nlev,1); 31 | filter = pyramid_filter; 32 | J = I; 33 | for l = 1:nlev - 1 34 | % apply low pass filter, and downsample 35 | [I,subwindow_child] = downsample(J,filter,subwindow); 36 | 37 | % in each level, store difference between image and upsampled low pass version 38 | pyr{l} = J - upsample(I,filter,subwindow); 39 | 40 | J = I; % continue with low pass image 41 | subwindow = subwindow_child; 42 | end 43 | pyr{nlev} = J; % the coarest level contains the residual low pass image 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /LLF-TOG2011/numlevels.m: -------------------------------------------------------------------------------- 1 | function nlev = numlevels(im_sz) 2 | % number of pyramid levels for an image of size [r c] 3 | 4 | % as many pyramid levels as possible, up to 1x1 5 | min_d = min(im_sz(1:2)); 6 | nlev = 1; 7 | while min_d>1 8 | nlev = nlev+1; 9 | min_d = floor((min_d+1)/2); 10 | end 11 | 12 | %nlev = floor(log(min(im_sz(1:2))) / log(2)); 13 | %nlev = ceil(log(min(im_sz(1:2))) / log(2)); 14 | 15 | end -------------------------------------------------------------------------------- /LLF-TOG2011/pyramid_filter.m: -------------------------------------------------------------------------------- 1 | % This is a 2D separable low pass filter for constructing Gaussian and 2 | % Laplacian pyramids, built from a 1D 5-tap low pass filter. 3 | % 4 | % tom.mertens@gmail.com, August 2007 5 | % sam.hasinoff@gmail.com, March 2011 [imfilter faster with 2D filter] 6 | % 7 | 8 | function f = pyramid_filter() 9 | f = [.05, .25, .4, .25, .05]; % original [Burt and Adelson, 1983] 10 | %f = [.0625, .25, .375, .25, .0625]; % binom-5 11 | f = f'*f; 12 | end -------------------------------------------------------------------------------- /LLF-TOG2011/reconstruct_laplacian_pyramid.m: -------------------------------------------------------------------------------- 1 | % Reconstruction of image from Laplacian pyramid 2 | % 3 | % Arguments: 4 | % pyramid 'pyr', as generated by function 'laplacian_pyramid' 5 | % subwindow indices 'subwindow', given as [r1 r2 c1 c2] (optional) 6 | % 7 | % tom.mertens@gmail.com, August 2007 8 | % sam.hasinoff@gmail.com, March 2011 [modified to handle subwindows] 9 | % 10 | % 11 | % More information: 12 | % 'The Laplacian Pyramid as a Compact Image Code' 13 | % Burt, P., and Adelson, E. H., 14 | % IEEE Transactions on Communication, COM-31:532-540 (1983). 15 | % 16 | 17 | function R = reconstruct_laplacian_pyramid(pyr,subwindow) 18 | 19 | r = size(pyr{1},1); 20 | c = size(pyr{1},2); 21 | nlev = length(pyr); 22 | 23 | subwindow_all = zeros(nlev,4); 24 | if ~exist('subwindow','var') 25 | subwindow_all(1,:) = [1 r 1 c]; 26 | else 27 | subwindow_all(1,:) = subwindow; 28 | end 29 | for lev = 2:nlev 30 | subwindow_all(lev,:) = child_window(subwindow_all(lev-1,:)); 31 | end 32 | 33 | % start with low pass residual 34 | R = pyr{nlev}; 35 | filter = pyramid_filter; 36 | for lev = nlev-1 : -1 : 1 37 | % upsample, and add to current level 38 | R = pyr{lev} + upsample(R,filter,subwindow_all(lev,:)); 39 | end 40 | -------------------------------------------------------------------------------- /LLF-TOG2011/upsample.m: -------------------------------------------------------------------------------- 1 | % Upsampling procedure. 2 | % 3 | % Argments: 4 | % 'I': image 5 | % 'filter': 2D separable upsampling filter 6 | % parent subwindow indices 'subwindow', given as [r1 r2 c1 c2] 7 | % 8 | % tom.mertens@gmail.com, August 2007 9 | % sam.hasinoff@gmail.com, March 2011 [handle subwindows, reweighted boundaries] 10 | % 11 | 12 | function R = upsample(I, filter, subwindow) 13 | 14 | % increase size to match dimensions of the parent subwindow, 15 | % about 2x in each dimension 16 | r = subwindow(2) - subwindow(1) + 1; 17 | c = subwindow(4) - subwindow(3) + 1; 18 | k = size(I,3); 19 | reven = mod(subwindow(1),2)==0; 20 | ceven = mod(subwindow(3),2)==0; 21 | 22 | border_mode = 'reweighted'; 23 | %border_mode = 'symmetric'; 24 | 25 | switch border_mode 26 | case 'reweighted' 27 | % interpolate, convolve with 2D separable filter 28 | R = zeros(r,c,k); 29 | R(1+reven:2:r, 1+ceven:2:c, :) = I; 30 | R = imfilter(R,filter); 31 | 32 | % reweight, brute force weights from 1's in valid image positions 33 | Z = zeros(r,c,k); 34 | Z(1+reven:2:r, 1+ceven:2:c, :) = 1; 35 | Z = imfilter(Z,filter); 36 | R = R./Z; 37 | 38 | otherwise 39 | % increase resolution 40 | I = padarray(I,[1 1 0],'replicate'); % pad the image with a 1-pixel border 41 | R = zeros(r+4,c+4,k); 42 | R(1+reven:2:end, 1+ceven:2:end, :) = 4*I; 43 | 44 | % interpolate, convolve with 2D separable filter 45 | R = imfilter(R,filter,border_mode); 46 | 47 | % remove the border 48 | R = R(3:end-2, 3:end-2, :); 49 | end 50 | end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SOTA Image Smoothing Methods 2 | 3 | 1. "FBF-ECCV2006": A Fast Approximation of the Bilateral Filter using a Signal Processing Approach. Sylvain Paris and Frédo Durand. ECCV 2006. (http://people.csail.mit.edu/sparis/bf/) 4 | 5 | 1. "WLS-TOG2008": Edge-Preserving Decompositions for Multi-Scale Tone and Detail Manipulation. Zeev Farbman, Raanan Fattal, Dani Lischinski, Richard Szeliski. ACM TOG 2008. (http://www.cs.huji.ac.il/~danix/epd/) 6 | 7 | 2. "EAW-TOG2009": Edge-Avoiding Wavelets and their Applications. Raanan Fattal. ACM TOG (SIGGRAPH) 2009. (http://www.cs.huji.ac.il/~raananf/projects/eaw/) 8 | 9 | 3. Diffusion Maps for Edge-Aware Image Editing. Zeev Farbman, Raanan Fattal, and Dani Lischinski. SIGGRAPH Asia, 2010. (http://www.cs.huji.ac.il/labs/cglab/projects/diffmaps/) 10 | 11 | 4. "GF-ECCV2010TPAMI2013": Guided Image Filtering, by Kaiming He, Jian Sun, and Xiaoou Tang. ECCV 2010, TPAMI 2013. (http://kaiminghe.com/eccv10/) 12 | 13 | 5. "DTF-TOG2011": Domain Transform for Edge-Aware Image and Video Processing. Eduardo S. L. Gastal and Manuel M. Oliveira. ACM TOG (SIGGRAPH), 2011. (http://inf.ufrgs.br/~eslgastal/DomainTransform/, Real-time!) 14 | 15 | 5. "LLF-TOG2011": Local Laplacian Filters: Edge-aware Image Processing with a Laplacian Pyramid. Sylvain Paris, Samuel W. Hasinoff, Jan Kautz. ACM TOG (SIGGRAPH), 2011. (http://people.csail.mit.edu/sparis/publi/2011/siggraph/) 16 | 17 | 6. "L0-TOG2011": Image Smoothing via L0 Gradient Minimization. Li Xu, Cewu Lu, Yi Xu, Jiaya Jia. ACM TOG (SIGGRAPH Asia), 2011. (http://www.cse.cuhk.edu.hk/leojia/projects/L0smoothing/index.html) 18 | 19 | 7. "RTV-TOG2012": Structure Extraction from Texture via Relative Total Variation. Li Xu, Qiong Yan, Yang Xia, Jiaya Jia. ACM TOG 2012. (http://www.cse.cuhk.edu.hk/~leojia/projects/texturesep/) 20 | 21 | 8. "FGS-TIP2014": Fast Global Image Smoothing Based on Weighted Least Squares. Dongbo Min, Sunghwan Choi, Jiangbo Lu, Bumsub Ham, Kwanghoon Sohn, and Minh N. Do. TIP 2014. (https://sites.google.com/site/globalsmoothing/) 22 | 23 | 9. "TF-TIP2014": Tree Filtering: Efficient Structure-Preserving Smoothing With a Minimum Spanning Tree. Linchao Bao, Yibing Song, Qingxiong Yang, Hao Yuan, and Gang Wang. TIP 2014. (http://linchaobao.github.io/) 24 | 25 | 10. "RGF-ECCV2014": Rolling Guidance Filter. Qi Zhang, Li Xu, Jiaya Jia. ECCV 2014. (http://www.cse.cuhk.edu.hk/leojia/projects/rollguidance/) 26 | 27 | 10. "DEAF-ICML2015": Deep Edge-Aware Filters. Li Xu, Jimmy SJ. Ren, Qiong Yan, Renjie Liao, Jiaya Jia. ICML 2015. (https://github.com/csjunxu/vcnn_double-bladed) 28 | 29 | 11. "SGF-ICCV2015": Segment Graph Based Image Filtering: Fast Structure-Preserving Smoothing. Feihu Zhang, Longquan Dai, Shiming Xiang, and Xiaopeng Zhang. ICCV 2015. (http://www.feihuzhang.com/SGF.html, Note that SGF.exe may not work well on linux or windows!) 30 | 31 | 12. "LRNN-ECCV2016": Learning Recursive Filters for Low-Level Vision via a Hybrid Neural Network. Sifei Liu, Jinshan Pan and Ming-Hsuan Yang. ECCV 2016. (https://github.com/silverneko/Linear-RNN) 32 | 33 | 13. "FIP-ICCV2017": Fast image processing with fullyconvolutional networks. Qifeng Chen, Jia Xu, and Vladlen Koltun. ICCV 2017. (https://github.com/CQFIO/FastImageProcessing) 34 | 35 | 14. "UL-TOG2018": Image Smoothing via Unsupervised Learning, ACM TOG (SIGGRAPH Asia), 2018. (https://github.com/fqnchina/ImageSmoothing) 36 | 37 | 15. Deep Texture and Structure Aware Filtering Network for Image Smoothing. Kaiyue Lu, Shaodi You, Nick Barnes. ECCV 2018. (Code: https://github.com/JiaBob/TSAFN; data will be released.) 38 | 39 | 16. "fastABF-TIP2019": Fast Adaptive Bilateral Filtering. R. G. Gavaskar and K. N. Chaudhury. TIP, 2019. (https://github.com/rgavaska/Fast-Adaptive-Bilateral-Filtering) 40 | 41 | TBC. 42 | -------------------------------------------------------------------------------- /RGF-ECCV2014/RollingGuidanceFilter.m: -------------------------------------------------------------------------------- 1 | % 2 | % Rolling Guidance Filter 3 | % 4 | % res = RollingGuidanceFilter(I,sigma_s,sigma_r,iteration) filters image 5 | % "I" by removing its small structures. The borderline between "small" 6 | % and "large" is determined by the parameter sigma_s. The sigma_r is 7 | % fixed to 0.1. The filter is an iteration process. "iteration" is used 8 | % to control the number of iterations. 9 | % 10 | % Paras: 11 | % @I : input image, DOUBLE image, any # of channels 12 | % @sigma_s : spatial sigma (default 3.0). Controlling the spatial 13 | % weight of bilateral filter and also the filtering scale of 14 | % rolling guidance filter. 15 | % @sigma_r : range sigma (default 0.1). Controlling the range weight of 16 | % bilateral filter. 17 | % @iteration : the iteration number of rolling guidance (default 4). 18 | % 19 | % 20 | % Example 21 | % ========== 22 | % I = im2double(imread('image.png')); 23 | % res = RollingGuidanceFilter(I,3,0.05,4); 24 | % figure, imshow(res); 25 | % 26 | % 27 | % Note 28 | % ========== 29 | % This implementation filters multi-channel/color image by separating its 30 | % channels, so the result of this implementation will be different with 31 | % that in the corresponding paper. To generate the results in the paper, 32 | % please refer to our executable file or C++ implementation on our 33 | % website. 34 | % 35 | % ========== 36 | % The Code is created based on the method described in the following paper: 37 | % [1] "Rolling Guidance Filter", Qi Zhang, Li Xu, Jiaya Jia, European 38 | % Conference on Computer Vision (ECCV), 2014 39 | % 40 | % The code and the algorithm are for non-comercial use only. 41 | % 42 | % 43 | % Author: Qi Zhang (zhangqi@cse.cuhk.edu.hk) 44 | % Date : 08/14/2014 45 | % Version : 1.0 46 | % Copyright 2014, The Chinese University of Hong Kong. 47 | % 48 | 49 | function res = RollingGuidanceFilter(I,sigma_s,sigma_r,iteration) 50 | 51 | if ~exist('iteration','var') 52 | iteration = 4; 53 | end 54 | 55 | if ~exist('sigma_s','var') 56 | sigma_s = 3; 57 | end 58 | 59 | if ~exist('sigma_r','var') 60 | sigma_r = 0.1; 61 | end 62 | 63 | res = I.*0; 64 | 65 | for i=1:iteration 66 | disp(['RGF iteration ' num2str(i) '...']); 67 | for c=1:size(I,3) 68 | G = res(:,:,c); 69 | res(:,:,c) = bilateralFilter(I(:,:,c),G,min(G(:)),max(G(:)),sigma_s,sigma_r); 70 | end 71 | end 72 | 73 | end 74 | -------------------------------------------------------------------------------- /RGF-ECCV2014/bilateralFilter.m: -------------------------------------------------------------------------------- 1 | % 2 | % output = bilateralFilter( data, edge, ... 3 | % edgeMin, edgeMax, ... 4 | % sigmaSpatial, sigmaRange, ... 5 | % samplingSpatial, samplingRange ) 6 | % 7 | % Bilateral and Cross-Bilateral Filter using the Bilateral Grid. 8 | % 9 | % Bilaterally filters the image 'data' using the edges in the image 'edge'. 10 | % If 'data' == 'edge', then it the standard bilateral filter. 11 | % Otherwise, it is the 'cross' or 'joint' bilateral filter. 12 | % For convenience, you can also pass in [] for 'edge' for the normal 13 | % bilateral filter. 14 | % 15 | % Note that for the cross bilateral filter, data does not need to be 16 | % defined everywhere. Undefined values can be set to 'NaN'. However, edge 17 | % *does* need to be defined everywhere. 18 | % 19 | % data and edge should be of the greyscale, double-precision floating point 20 | % matrices of the same size (i.e. they should be [ height x width ]) 21 | % 22 | % data is the only required argument 23 | % 24 | % edgeMin and edgeMax specifies the min and max values of 'edge' (or 'data' 25 | % for the normal bilateral filter) and is useful when the input is in a 26 | % range that's not between 0 and 1. For instance, if you are filtering the 27 | % L channel of an image that ranges between 0 and 100, set edgeMin to 0 and 28 | % edgeMax to 100. 29 | % 30 | % edgeMin defaults to min( edge( : ) ) and edgeMax defaults to max( edge( : ) ). 31 | % This is probably *not* what you want, since the input may not span the 32 | % entire range. 33 | % 34 | % sigmaSpatial and sigmaRange specifies the standard deviation of the space 35 | % and range gaussians, respectively. 36 | % sigmaSpatial defaults to min( width, height ) / 16 37 | % sigmaRange defaults to ( edgeMax - edgeMin ) / 10. 38 | % 39 | % samplingSpatial and samplingRange specifies the amount of downsampling 40 | % used for the approximation. Higher values use less memory but are also 41 | % less accurate. The default and recommended values are: 42 | % 43 | % samplingSpatial = sigmaSpatial 44 | % samplingRange = sigmaRange 45 | % 46 | 47 | function output = bilateralFilter( data, edge, edgeMin, edgeMax, sigmaSpatial, sigmaRange, ... 48 | samplingSpatial, samplingRange ) 49 | 50 | if( ndims( data ) > 2 ), 51 | error( 'data must be a greyscale image with size [ height, width ]' ); 52 | end 53 | 54 | if( ~isa( data, 'double' ) ), 55 | error( 'data must be of class "double"' ); 56 | end 57 | 58 | if ~exist( 'edge', 'var' ), 59 | edge = data; 60 | elseif isempty( edge ), 61 | edge = data; 62 | end 63 | 64 | if( ndims( edge ) > 2 ), 65 | error( 'edge must be a greyscale image with size [ height, width ]' ); 66 | end 67 | 68 | if( ~isa( edge, 'double' ) ), 69 | error( 'edge must be of class "double"' ); 70 | end 71 | 72 | inputHeight = size( data, 1 ); 73 | inputWidth = size( data, 2 ); 74 | 75 | if ~exist( 'edgeMin', 'var' ), 76 | edgeMin = min( edge( : ) ); 77 | warning( 'edgeMin not set! Defaulting to: %f\n', edgeMin ); 78 | end 79 | 80 | if ~exist( 'edgeMax', 'var' ), 81 | edgeMax = max( edge( : ) ); 82 | warning( 'edgeMax not set! Defaulting to: %f\n', edgeMax ); 83 | end 84 | 85 | edgeDelta = edgeMax - edgeMin; 86 | 87 | if ~exist( 'sigmaSpatial', 'var' ), 88 | sigmaSpatial = min( inputWidth, inputHeight ) / 16; 89 | fprintf( 'Using default sigmaSpatial of: %f\n', sigmaSpatial ); 90 | end 91 | 92 | if ~exist( 'sigmaRange', 'var' ), 93 | sigmaRange = 0.1 * edgeDelta; 94 | fprintf( 'Using default sigmaRange of: %f\n', sigmaRange ); 95 | end 96 | 97 | if ~exist( 'samplingSpatial', 'var' ), 98 | samplingSpatial = sigmaSpatial; 99 | end 100 | 101 | if ~exist( 'samplingRange', 'var' ), 102 | samplingRange = sigmaRange; 103 | end 104 | 105 | if size( data ) ~= size( edge ), 106 | error( 'data and edge must be of the same size' ); 107 | end 108 | 109 | % parameters 110 | derivedSigmaSpatial = sigmaSpatial / samplingSpatial; 111 | derivedSigmaRange = sigmaRange / samplingRange; 112 | 113 | paddingXY = floor( 2 * derivedSigmaSpatial ) + 1; 114 | paddingZ = floor( 2 * derivedSigmaRange ) + 1; 115 | 116 | % allocate 3D grid 117 | downsampledWidth = floor( ( inputWidth - 1 ) / samplingSpatial ) + 1 + 2 * paddingXY; 118 | downsampledHeight = floor( ( inputHeight - 1 ) / samplingSpatial ) + 1 + 2 * paddingXY; 119 | downsampledDepth = floor( edgeDelta / samplingRange ) + 1 + 2 * paddingZ; 120 | 121 | gridData = zeros( downsampledHeight, downsampledWidth, downsampledDepth ); 122 | gridWeights = zeros( downsampledHeight, downsampledWidth, downsampledDepth ); 123 | 124 | % compute downsampled indices 125 | [ jj, ii ] = meshgrid( 0 : inputWidth - 1, 0 : inputHeight - 1 ); 126 | 127 | % ii = 128 | % 0 0 0 0 0 129 | % 1 1 1 1 1 130 | % 2 2 2 2 2 131 | 132 | % jj = 133 | % 0 1 2 3 4 134 | % 0 1 2 3 4 135 | % 0 1 2 3 4 136 | 137 | % so when iterating over ii( k ), jj( k ) 138 | % get: ( 0, 0 ), ( 1, 0 ), ( 2, 0 ), ... (down columns first) 139 | 140 | di = round( ii / samplingSpatial ) + paddingXY + 1; 141 | dj = round( jj / samplingSpatial ) + paddingXY + 1; 142 | dz = round( ( edge - edgeMin ) / samplingRange ) + paddingZ + 1; 143 | 144 | % perform scatter (there's probably a faster way than this) 145 | % normally would do downsampledWeights( di, dj, dk ) = 1, but we have to 146 | % perform a summation to do box downsampling 147 | for k = 1 : numel( dz ), 148 | 149 | dataZ = data( k ); % traverses the image column wise, same as di( k ) 150 | if ~isnan( dataZ ), 151 | 152 | dik = di( k ); 153 | djk = dj( k ); 154 | dzk = dz( k ); 155 | 156 | gridData( dik, djk, dzk ) = gridData( dik, djk, dzk ) + dataZ; 157 | gridWeights( dik, djk, dzk ) = gridWeights( dik, djk, dzk ) + 1; 158 | 159 | end 160 | end 161 | 162 | % make gaussian kernel 163 | kernelWidth = 2 * derivedSigmaSpatial + 1; 164 | kernelHeight = kernelWidth; 165 | kernelDepth = 2 * derivedSigmaRange + 1; 166 | 167 | halfKernelWidth = floor( kernelWidth / 2 ); 168 | halfKernelHeight = floor( kernelHeight / 2 ); 169 | halfKernelDepth = floor( kernelDepth / 2 ); 170 | 171 | [gridX, gridY, gridZ] = meshgrid( 0 : kernelWidth - 1, 0 : kernelHeight - 1, 0 : kernelDepth - 1 ); 172 | gridX = gridX - halfKernelWidth; 173 | gridY = gridY - halfKernelHeight; 174 | gridZ = gridZ - halfKernelDepth; 175 | gridRSquared = ( gridX .* gridX + gridY .* gridY ) / ( derivedSigmaSpatial * derivedSigmaSpatial ) + ( gridZ .* gridZ ) / ( derivedSigmaRange * derivedSigmaRange ); 176 | kernel = exp( -0.5 * gridRSquared ); 177 | 178 | % convolve 179 | blurredGridData = convn( gridData, kernel, 'same' ); 180 | blurredGridWeights = convn( gridWeights, kernel, 'same' ); 181 | 182 | % divide 183 | blurredGridWeights( blurredGridWeights == 0 ) = -2; % avoid divide by 0, won't read there anyway 184 | normalizedBlurredGrid = blurredGridData ./ blurredGridWeights; 185 | normalizedBlurredGrid( blurredGridWeights < -1 ) = 0; % put 0s where it's undefined 186 | 187 | % for debugging 188 | % blurredGridWeights( blurredGridWeights < -1 ) = 0; % put zeros back 189 | 190 | % upsample 191 | [ jj, ii ] = meshgrid( 0 : inputWidth - 1, 0 : inputHeight - 1 ); % meshgrid does x, then y, so output arguments need to be reversed 192 | % no rounding 193 | di = ( ii / samplingSpatial ) + paddingXY + 1; 194 | dj = ( jj / samplingSpatial ) + paddingXY + 1; 195 | dz = ( edge - edgeMin ) / samplingRange + paddingZ + 1; 196 | 197 | % interpn takes rows, then cols, etc 198 | % i.e. size(v,1), then size(v,2), ... 199 | output = interpn( normalizedBlurredGrid, di, dj, dz ); 200 | a = interpn(blurredGridWeights,di,dj,dz); 201 | 202 | % correction for outliers (January 10, 2013, Qiong Yan) 203 | mask = isnan(output); 204 | output(mask) = data(mask); -------------------------------------------------------------------------------- /RGF-ECCV2014/example.m: -------------------------------------------------------------------------------- 1 | 2 | clear,close; 3 | 4 | Original_image_dir = '/Users/xujun/Desktop/YingkunHou/dataset/origin_images'; 5 | fpath = fullfile(Original_image_dir, '*.png'); 6 | im_dir = dir(fpath); 7 | im_num = length(im_dir); 8 | 9 | method = 'RGF'; 10 | for i = 1:im_num 11 | I = im2double(imread(fullfile(Original_image_dir, im_dir(i).name))); 12 | S = regexp(im_dir(i).name, '\.', 'split'); 13 | sI = RollingGuidanceFilter(I,3,0.05,4); 14 | fprintf('%s is done!\n', im_dir(i).name); 15 | outname = sprintf(['/Users/xujun/Desktop/YingkunHou/results/500images' S{1} '_' method '.png']); 16 | imwrite(sI, outname); 17 | end -------------------------------------------------------------------------------- /RTV-TOG2012/Demo.m: -------------------------------------------------------------------------------- 1 | % Demo script 2 | % Uncomment each case to see the results 3 | 4 | clear,close; 5 | 6 | Original_image_dir = '/Users/xujun/Desktop/YingkunHou/dataset/origin_images'; 7 | fpath = fullfile(Original_image_dir, '*.png'); 8 | im_dir = dir(fpath); 9 | im_num = length(im_dir); 10 | 11 | method = 'RTV'; 12 | for i = 1:im_num 13 | I = imread(fullfile(Original_image_dir, im_dir(i).name)); 14 | S = regexp(im_dir(i).name, '\.', 'split'); 15 | sI = tsmooth(I,0.015,3); 16 | fprintf('%s is done!\n', im_dir(i).name); 17 | outname = sprintf(['/Users/xujun/Desktop/YingkunHou/results/500images/' S{1} '_' method '.png']); 18 | imwrite(sI, outname); 19 | end 20 | 21 | % I = (imread('imgs/crossstitch.jpg')); 22 | % S = tsmooth(I,0.015,3); 23 | % figure, imshow(I), figure, imshow(S); 24 | 25 | % I = (imread('imgs/graffiti.jpg')); 26 | % S = tsmooth(I,0.015,3); 27 | % figure, imshow(I), figure, imshow(S); 28 | 29 | % I = (imread('imgs/crossstitch.jpg')); 30 | % S = tsmooth(I,0.015,3); 31 | % figure, imshow(I), figure, imshow(S); 32 | 33 | % I = (imread('imgs/mosaicfloor.jpg')); 34 | % S = tsmooth(I, 0.01, 3, 0.02, 5); 35 | % figure, imshow(I), figure, imshow(S); 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /RTV-TOG2012/tsmooth.m: -------------------------------------------------------------------------------- 1 | function S = tsmooth(I,lambda,sigma,sharpness,maxIter) 2 | %tsmooth - Structure Extraction from Texture via Relative Total Variation 3 | % S = tsmooth(I, lambda, sigma, maxIter) extracts structure S from 4 | % structure+texture input I, with smoothness weight lambda, scale 5 | % parameter sigma and iteration number maxIter. 6 | % 7 | % Paras: 8 | % @I : Input UINT8 image, both grayscale and color images are acceptable. 9 | % @lambda : Parameter controlling the degree of smooth. 10 | % Range (0, 0.05], 0.01 by default. 11 | % @sigma : Parameter specifying the maximum size of texture elements. 12 | % Range (0, 6], 3 by defalut. 13 | % @sharpness : Parameter controlling the sharpness of the final results, 14 | % which corresponds to \epsilon_s in the paper [1]. The smaller the value, the sharper the result. 15 | % Range (1e-3, 0.03], 0.02 by defalut. 16 | % @maxIter : Number of itearations, 4 by default. 17 | % 18 | % Example 19 | % ========== 20 | % I = imread('Bishapur_zan.jpg'); 21 | % S = tsmooth(I); % Default Parameters (lambda = 0.01, sigma = 3, sharpness = 0.02, maxIter = 4) 22 | % figure, imshow(I), figure, imshow(S); 23 | % 24 | % ========== 25 | % The Code is created based on the method described in the following paper 26 | % [1] "Structure Extraction from Texture via Relative Total Variation", Li Xu, Qiong Yan, Yang Xia, Jiaya Jia, ACM Transactions on Graphics, 27 | % (SIGGRAPH Asia 2012), 2012. 28 | % The code and the algorithm are for non-comercial use only. 29 | % 30 | % Author: Li Xu (xuli@cse.cuhk.edu.hk) 31 | % Date : 08/25/2012 32 | % Version : 1.0 33 | % Copyright 2012, The Chinese University of Hong Kong. 34 | % 35 | 36 | if (~exist('lambda','var')) 37 | lambda=0.01; 38 | end 39 | if (~exist('sigma','var')) 40 | sigma=3.0; 41 | end 42 | if (~exist('sharpness','var')) 43 | sharpness = 0.02; 44 | end 45 | if (~exist('maxIter','var')) 46 | maxIter=4; 47 | end 48 | I = im2double(I); 49 | x = I; 50 | sigma_iter = sigma; 51 | lambda = lambda/2.0; 52 | dec=2.0; 53 | for iter = 1:maxIter 54 | [wx, wy] = computeTextureWeights(x, sigma_iter, sharpness); 55 | x = solveLinearEquation(I, wx, wy, lambda); 56 | sigma_iter = sigma_iter/dec; 57 | if sigma_iter < 0.5 58 | sigma_iter = 0.5; 59 | end 60 | end 61 | S = x; 62 | end 63 | 64 | function [retx, rety] = computeTextureWeights(fin, sigma,sharpness) 65 | 66 | fx = diff(fin,1,2); 67 | fx = padarray(fx, [0 1 0], 'post'); 68 | fy = diff(fin,1,1); 69 | fy = padarray(fy, [1 0 0], 'post'); 70 | 71 | vareps_s = sharpness; 72 | vareps = 0.001; 73 | 74 | wto = max(sum(sqrt(fx.^2+fy.^2),3)/size(fin,3),vareps_s).^(-1); 75 | fbin = lpfilter(fin, sigma); 76 | gfx = diff(fbin,1,2); 77 | gfx = padarray(gfx, [0 1], 'post'); 78 | gfy = diff(fbin,1,1); 79 | gfy = padarray(gfy, [1 0], 'post'); 80 | wtbx = max(sum(abs(gfx),3)/size(fin,3),vareps).^(-1); 81 | wtby = max(sum(abs(gfy),3)/size(fin,3),vareps).^(-1); 82 | retx = wtbx.*wto; 83 | rety = wtby.*wto; 84 | 85 | retx(:,end) = 0; 86 | rety(end,:) = 0; 87 | 88 | end 89 | 90 | function ret = conv2_sep(im, sigma) 91 | ksize = bitor(round(5*sigma),1); 92 | g = fspecial('gaussian', [1,ksize], sigma); 93 | ret = conv2(im,g,'same'); 94 | ret = conv2(ret,g','same'); 95 | end 96 | 97 | function FBImg = lpfilter(FImg, sigma) 98 | FBImg = FImg; 99 | for ic = 1:size(FBImg,3) 100 | FBImg(:,:,ic) = conv2_sep(FImg(:,:,ic), sigma); 101 | end 102 | end 103 | 104 | function OUT = solveLinearEquation(IN, wx, wy, lambda) 105 | % 106 | % The code for constructing inhomogenious Laplacian is adapted from 107 | % the implementaion of the wlsFilter. 108 | % 109 | % For color images, we enforce wx and wy be same for three channels 110 | % and thus the pre-conditionar only need to be computed once. 111 | % 112 | [r,c,ch] = size(IN); 113 | k = r*c; 114 | dx = -lambda*wx(:); 115 | dy = -lambda*wy(:); 116 | B(:,1) = dx; 117 | B(:,2) = dy; 118 | d = [-r,-1]; 119 | A = spdiags(B,d,k,k); 120 | e = dx; 121 | w = padarray(dx, r, 'pre'); w = w(1:end-r); 122 | s = dy; 123 | n = padarray(dy, 1, 'pre'); n = n(1:end-1); 124 | D = 1-(e+w+s+n); 125 | A = A + A' + spdiags(D, 0, k, k); 126 | if exist('ichol','builtin') 127 | L = ichol(A,struct('michol','on')); 128 | OUT = IN; 129 | for ii=1:ch 130 | tin = IN(:,:,ii); 131 | [tout, flag] = pcg(A, tin(:),0.1,100, L, L'); 132 | OUT(:,:,ii) = reshape(tout, r, c); 133 | end 134 | else 135 | OUT = IN; 136 | for ii=1:ch 137 | tin = IN(:,:,ii); 138 | tout = A\tin(:); 139 | OUT(:,:,ii) = reshape(tout, r, c); 140 | end 141 | end 142 | 143 | end -------------------------------------------------------------------------------- /SGF-ICCV2015.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/SGF-ICCV2015.pdf -------------------------------------------------------------------------------- /SGF-ICCV2015/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(SGF) 2 | cmake_minimum_required(VERSION 2.8) 3 | set(CMAKE_BUILD_TYPE "Release") 4 | #set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") 5 | 6 | #include_directories(${CMAKE_CURRENT_SOURCE_DIR}) 7 | 8 | find_package( OpenCV REQUIRED ) 9 | if( OpenCV_FOUND ) 10 | list( APPEND ThirdParty_LIBS ${OpenCV_LIBS} ) 11 | include_directories( ${OpenCV_INCLUDE_DIRS} ) 12 | endif( OpenCV_FOUND ) 13 | 14 | FIND_PACKAGE(OpenMP REQUIRED) 15 | if(OPENMP_FOUND) 16 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 17 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 18 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") 19 | endif() 20 | 21 | #this is for c++11 support 22 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 23 | 24 | set(${PROJECT_NAME}_SRC src/main.cpp src/SGF.cpp src/Image.cpp src/SLIC.cpp) 25 | set(${PROJECT_NAME}_HDR src/Image.h src/SLIC.cpp) 26 | 27 | add_executable(${PROJECT_NAME} ${${PROJECT_NAME}_SRC} ${${PROJECT_NAME}_HDR}) 28 | target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS}) 29 | -------------------------------------------------------------------------------- /SGF-ICCV2015/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Feihu Zhang 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 | -------------------------------------------------------------------------------- /SGF-ICCV2015/README.md: -------------------------------------------------------------------------------- 1 | # SGF 2 | Method 3 | ========= 4 | This is the implementation of 'Segment Graph Based Image Filtering: Fast Structure-Preserving Smoothing' as 5 | described in 6 | 7 | @inproceedings{zhang2015segment, 8 | 9 | title={Segment Graph Based Image Filtering: Fast Structure-Preserving Smoothing}, 10 | 11 | author={Zhang, Feihu and Dai, Longquan and Xiang, Shiming and Zhang, Xiaopeng}, 12 | 13 | booktitle={Proceedings of the IEEE International Conference on Computer Vision}, 14 | 15 | pages={361--369}, 16 | 17 | year={2015} 18 | } 19 | 20 | Compiling the code 21 | ================== 22 | To compile the source code, you must have opencv installed (libpng is also necessary if you didn't install it along with opencv). Then, 23 | 24 | $cmake . 25 | 26 | $make 27 | 28 | or directly 29 | 30 | $g++ -fopenmp src/*.cpp `pkg-config opencv --libs --cflags opencv` -o SGF -fpermissive 31 | 32 | The code is already tested both on Linux and Windows. 33 | To recompile it on windows, you need to rebuild a project, add the source file and set the opencv environment. 34 | Or, you can directly use the released win32 software in the exe folder. 35 | 36 | Interface function 37 | ================== 38 | If you want to use the code in your own project. You can directly add the SGF.cpp Image.cpp SLIC.cpp Image.h SLIC.h to your project. 39 | 4 interface functions are provided as follows: (You can view them in the SGF.cpp) 40 | 41 | 1) Mat Image::FilteringColor(Mat &guid, Mat &target, int Radius, float Eps, float Thresh) 42 | 43 | Parameters: 44 | 45 | guid: can be CV_8UC3(color) or CV_8UC1(gray) image; 46 | 47 | target: must be CV_8UC3(color) image and in the same size with guid; 48 | 49 | Radius: radius of the filtering window; 50 | 51 | Eps: just like the bilateral filter value. range: (0,1) 52 | 53 | Thresh: As Described in the paper. range: (0,1) 54 | 55 | 2) Mat Image::FilteringGray(Mat guid, Mat target, int Radius,float Eps, float Thresh) 56 | 57 | Parameters: 58 | 59 | guid: can be CV_8UC3(color) or CV_8UC1(gray) image; 60 | 61 | target: must be CV_8UC1(gray) image; 62 | 63 | Radius: radius of the filtering window; 64 | 65 | Eps: just like the bilateral filter value. range: (0,1) 66 | 67 | Thresh: As Described in the paper. range: (0,1) 68 | 69 | 3) Mat Image::IterFiltering(Mat&guid,Mat &target,int radius, float eps, float thresh,int Iter) 70 | 71 | Parameters: 72 | 73 | guid and target must be can be the same image, CV_8UC3(color) or CV_8UC1(gray); 74 | 75 | Radius: radius of the filtering window; 76 | 77 | Eps: just like the bilateral filter value. range: (0,1); 78 | 79 | Thresh: As Described in the paper. range: (0,1); 80 | 81 | Iter: Iterative times for iterative filtering. 82 | 83 | 4) Mat Image::Filtering(Mat target) 84 | 85 | Parameters: 86 | 87 | target: must be CV_32FC1, one-channel float mat; 88 | 89 | To use this function, you must first initialize the SGF once using: 90 | 91 | void Image::initial(Mat guid, int radius, float EPS, float Thresh); 92 | 93 | the four parameters are similar to these in FilteringGray and FilteringColor. 94 | 95 | Running the Demo 96 | ================ 97 | 98 | You can directly run the exe file on windows by 99 | 100 | $SGF.exe [guid image] [target image] [output file] [radius] [eps] [thresh] [iterations] 101 | 102 | value range: (see the paper for details about these parameters) 103 | 104 | eps: (0~0.3] float, 105 | 106 | thresh: (0~1] float 107 | 108 | iterations: iterative filtering times. guid image and target image must be same if >1. 109 | 110 | The last two parameters can be neglected. Default: 1 111 | 112 | Examples: 113 | 114 | $SGF.exe 1.png 2.png 3.png 16 0.1 115 | 116 | $SGF.exe 1.png 1.png 3.png 16 0.1 0.1 3 117 | 118 | Or on Linux: 119 | $./SGF [guid image] [target image] [output file] [radius] [eps] [thresh] [iterations] 120 | 121 | We provide some matlab scripts to run the demo in the paper. 122 | 123 | 1) demo_abs: the image abstraction demo. Inputs and outputs are in the "abs" 124 | 125 | 2) demo_depth: depth map denoising and depth map upsampling(8 times). Inputs and outputs are in the "depth". For the application of depth map upsampling, fistly, generate the seed map and then, use the guidance image to filter the seed map. "depth/shrink.m" provides an example to generate the seed map by just setting all the other pixels(except the seed pixel) to zero. 126 | 127 | 3) demo_iterative: demo super iterative SGF, the inputs will be filtering for 10~30 times. Inputs and outputs are in "iterative" 128 | 129 | 4) demo_smooth: demo for image smooth (noise/details removing). Inputs and outputs are include in "smooth" 130 | 131 | 5) demo_texture: demo for texture removing. Inputs and outputs are in "texture". 132 | 133 | Notice 134 | ======== 135 | 1) Currently the implement is a slow version which can be sped up for 5 times. We will soon release the speed-up version. 136 | 137 | 2) The parameters used in the demo are slightly different with the paper. This is caused by the image size differences. 138 | 139 | Citation 140 | ======== 141 | 142 | If you find this project, data or code useful, we would be happy if you cite us: 143 | 144 | @inproceedings{zhang2015segment, 145 | 146 | title={Segment Graph Based Image Filtering: Fast Structure-Preserving Smoothing}, 147 | 148 | author={Zhang, Feihu and Dai, Longquan and Xiang, Shiming and Zhang, Xiaopeng}, 149 | 150 | booktitle={Proceedings of the IEEE International Conference on Computer Vision}, 151 | 152 | pages={361--369}, 153 | 154 | year={2015} 155 | } 156 | -------------------------------------------------------------------------------- /SGF-ICCV2015/SGF.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/SGF-ICCV2015/SGF.exe -------------------------------------------------------------------------------- /SGF-ICCV2015/VisualMap.m: -------------------------------------------------------------------------------- 1 | function VisualMap(data,Title) 2 | 3 | 4 | data=double(data(:,:,1)); 5 | data=flipud(data); 6 | Handle = pcolor( data ); 7 | %figure; 8 | %set('name',title,'Numbertitle','off'); 9 | title(Title); 10 | set( Handle , 'EdgeColor' , 'none'); 11 | caxis([min(data(:)),max(data(:))]); 12 | colormap jet; 13 | -------------------------------------------------------------------------------- /SGF-ICCV2015/abstraction.m: -------------------------------------------------------------------------------- 1 | function abstraction(imgname,radius,eps,thresh,iter) 2 | 3 | format=imgname(length(imgname)-3:length(imgname)); 4 | file=imgname(1:length(imgname)-4); 5 | outfile=strcat(file,'_smooth',format); 6 | 7 | %%%%%%if you use windows please use the following command. 8 | %command=sprintf('SGF.exe %s %s %s %d %.2f %.2f %d',imgname, imgname,outfile, radius,eps,thresh,iter); 9 | %%%%%%for linux 10 | command=sprintf('./SGF %s %s %s %d %.2f %.2f %d',imgname, imgname,outfile, radius,eps,thresh,iter); 11 | dos(command); 12 | scale=6; 13 | I=imread(outfile); 14 | if(size(I,3)>1) 15 | II=double(rgb2gray(I)); 16 | else 17 | II=double(I); 18 | end 19 | [Gx,Gy]=gradient(II); 20 | G=sqrt(Gx.*Gx+Gy.*Gy); 21 | J=zeros(size(II,1),size(II,2)); 22 | J(:)=255; 23 | %K=find(G>=70); 24 | %J(K)=0; 25 | 26 | 27 | J=uint8(J-G*scale); 28 | imwrite(J,strcat(file,'_grad',format)); 29 | %e=edge(II,'canny'); 30 | e=double(J)<180; 31 | %temp=imfilter(double(e),ones(5,5),'same'); 32 | e=imfilter(double(e),ones(2,1),'same'); 33 | tag=e>0; 34 | for i=1:size(I,3) 35 | p=I(:,:,i); 36 | p(tag)=0; 37 | I(:,:,i)=p; 38 | end 39 | imwrite(I,strcat(file,'_abs',format)); 40 | return; -------------------------------------------------------------------------------- /SGF-ICCV2015/demo_abs.m: -------------------------------------------------------------------------------- 1 | for index=1:7 2 | filename=sprintf('abs/%d.png',index); 3 | eps=0.1; 4 | radius=16; 5 | if(index>4) 6 | eps=0.05; 7 | radius=8; 8 | end 9 | abstraction(filename,radius,eps,0.1,3); 10 | end 11 | -------------------------------------------------------------------------------- /SGF-ICCV2015/demo_depth.m: -------------------------------------------------------------------------------- 1 | close all; 2 | 3 | guidfile='depth/guid.png'; 4 | 5 | targetfile='depth/noise.png'; 6 | outfile='depth/denoise.png'; 7 | %%%%%%if you use windows please use the following command. 8 | command=sprintf('./SGF %s %s %s %d %.2f %.2f %d',guidfile, targetfile,outfile, 32,0.04,0.4,1); 9 | %%%%%%for linux 10 | %command=sprintf('./SGF %s %s %s %d %.2f %.2f %d',guidfile, targetfile,outfile, 32,0.05,0.05,1); 11 | dos(command); 12 | img=imread(outfile); 13 | img=img(:,:,1); 14 | temp=medfilt2(img,[5,5]); 15 | img(3:size(img,1)-2,3:size(img,2)-2)=temp(3:size(img,1)-2,3:size(img,2)-2); 16 | imwrite(img,outfile); 17 | 18 | temp=imread(targetfile); 19 | VisualMap(temp,'noisy depth map as input'); 20 | figure; 21 | VisualMap(img,'denoising result'); 22 | figure; 23 | 24 | targetfile='depth/seedmap.png'; 25 | outfile='depth/upsampling.png'; 26 | %%%%%%if you use windows please use the following command. 27 | command=sprintf('./SGF %s %s %s %d %.2f %.2f %d',guidfile, targetfile,outfile, 32,0.025,0.25,1); 28 | %%%%%%for linux 29 | %command=sprintf('./SGF %s %s %s %d %.2f %.2f %d',guidfile, targetfile,outfile, 32,0.05,0.05,1); 30 | dos(command); 31 | img=imread(outfile); 32 | img=img(:,:,1); 33 | temp=medfilt2(img,[5,5]); 34 | img(3:size(img,1)-2,3:size(img,2)-2)=temp(3:size(img,1)-2,3:size(img,2)-2); 35 | imwrite(img,outfile); 36 | VisualMap(img,'8 times depth upsampling result'); 37 | figure; 38 | temp=imread('depth/ground.png'); 39 | temp=medfilt2(img,[5,5]); 40 | VisualMap(temp,'ground truth'); 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /SGF-ICCV2015/demo_iterative.m: -------------------------------------------------------------------------------- 1 | dos('./SGF iterative/1.png iterative/1.png iterative/1_30iter.png 16 0.1 0.1 30'); 2 | dos('./SGF iterative/2.png iterative/2.png iterative/2_8iter.png 16 0.1 0.1 8'); 3 | dos('./SGF iterative/3.png iterative/3.png iterative/3_20iter.png 16 0.1 0.1 20'); 4 | dos('./SGF iterative/4.png iterative/4.png iterative/4_20iter.png 16 0.1 0.1 20'); 5 | -------------------------------------------------------------------------------- /SGF-ICCV2015/demo_smooth.m: -------------------------------------------------------------------------------- 1 | close all; 2 | index=0; 3 | imgname=sprintf('smooth/%d.png',index); 4 | format=imgname(length(imgname)-3:length(imgname)); 5 | file=imgname(1:length(imgname)-4); 6 | outfile=strcat(file,'_denoise',format); 7 | radius=12; 8 | eps=0.05; 9 | thresh=0.1; 10 | iter=3; 11 | command=sprintf('./SGF %s %s %s %d %.2f %.2f %d',imgname, imgname,outfile, radius,eps,thresh,iter); 12 | %%%%%%for linux 13 | %command=sprintf('./SGF %s %s %s %d %.2f %.2f %d',imgname, imgname,outfile, radius,eps,thresh,iter); 14 | dos(command); 15 | img=imread(imgname); 16 | VisualMap(img,'input'); 17 | figure; 18 | img=imread(outfile); 19 | VisualMap(img,'denoising result'); 20 | figure; 21 | outfile=strcat(file,'_smooth',format); 22 | radius=25; 23 | eps=0.06; 24 | thresh=0.2; 25 | iter=8; 26 | command=sprintf('./SGF %s %s %s %d %.2f %.2f %d',imgname, imgname,outfile, radius,eps,thresh,iter); 27 | %%%%%%for linux 28 | %command=sprintf('./SGF %s %s %s %d %.2f %.2f %d',imgname, imgname,outfile, radius,eps,thresh,iter); 29 | dos(command); 30 | img=imread(outfile); 31 | VisualMap(img,'smooth effects'); 32 | 33 | command=sprintf('./SGF %s %s %s %d %.2f %.2f %d',imgname, imgname,outfile, radius,eps,thresh,iter); 34 | %%%%%%for linux 35 | %command=sprintf('./SGF %s %s %s %d %.2f %.2f %d',imgname, imgname,outfile, radius,eps,thresh,iter); 36 | dos('./SGF smooth/1.png smooth/1.png smooth/1_smooth.png 12 0.1 0.2 3'); 37 | dos('./SGF smooth/2.png smooth/2.png smooth/2_smooth.png 16 0.05 0.1 3'); 38 | dos('./SGF smooth/3.png smooth/3.png smooth/3_smooth.png 8 0.05 0.2 3'); 39 | %} 40 | -------------------------------------------------------------------------------- /SGF-ICCV2015/demo_smooth_JX.m: -------------------------------------------------------------------------------- 1 | %% Edge-preserving smoothing example 2 | close all; 3 | clc; 4 | 5 | Original_image_dir = '/home/csjunxu/Github/data/dataset/origin_images'; 6 | fpath = fullfile(Original_image_dir, '*.png'); 7 | im_dir = dir(fpath); 8 | im_num = length(im_dir); 9 | 10 | method = 'SGF'; 11 | for i = 1:im_num 12 | I = imread(fullfile(Original_image_dir, im_dir(i).name)); 13 | S = regexp(im_dir(i).name, '\.', 'split'); 14 | file = S{1}; 15 | format = S{2}; 16 | outname = sprintf(['/home/csjunxu/Github/data/dataset/results/' S{1} '_' method '.png']); 17 | radius=12; 18 | eps=0.05; 19 | thresh=0.1; 20 | iter=3; 21 | %%%%%%for windows 22 | command=sprintf('SGF.exe %s %s %s %d %.2f %.2f %d',file,file,outname,radius,eps,thresh,iter); 23 | %%%%%%for linux 24 | %command=sprintf('./SGF %s %s %s %d %.2f %.2f %d',imgname, imgname,outfile, radius,eps,thresh,iter); 25 | dos(command); 26 | fprintf('%s is done!\n', im_dir(i).name); 27 | end 28 | -------------------------------------------------------------------------------- /SGF-ICCV2015/demo_texture.m: -------------------------------------------------------------------------------- 1 | dos('SGF.exe texture/1.png texture/1.png texture/1_smooth.png 10 0.065 0.1 6'); 2 | dos('SGF.exe texture/2.png texture/2.png texture/2_smooth.png 12 0.065 0.1 6'); 3 | dos('SGF.exe texture/3.png texture/3.png texture/3_smooth.png 16 0.065 0.1 4'); 4 | dos('SGF.exe texture/4.png texture/4.png texture/4_smooth.png 12 0.065 0.1 4'); 5 | dos('SGF.exe texture/5.png texture/5.png texture/5_smooth.png 12 0.065 0.1 3'); 6 | dos('SGF.exe texture/6.png texture/6.png texture/6_smooth.png 12 0.065 0.1 6'); 7 | dos('SGF.exe texture/7.png texture/7.png texture/7_smooth.png 12 0.065 0.1 6'); -------------------------------------------------------------------------------- /SGF-ICCV2015/depth/shrink.m: -------------------------------------------------------------------------------- 1 | function shrink(file,scale) 2 | %file: filename of the original depth map; 3 | %scale: shrink scale to generate the seedmap. 4 | img=imread(file); 5 | [m,n,p]=size(img); 6 | img=img(:,:,1); 7 | m1=floor(m/scale); 8 | n1=floor(n/scale); 9 | I=uint8(zeros(m1,n1)); 10 | new=uint8(zeros(m,n)); 11 | for row=1:m 12 | for col=1:n 13 | if mod(row,scale)==0&mod(col,scale)==0 14 | I(row/scale,col/scale)=img(row,col); 15 | new(row,col)=img(row,col); 16 | end 17 | end 18 | end 19 | imwrite(I,'shrink.png'); 20 | imwrite(new,'seedmap.png'); 21 | 22 | 23 | -------------------------------------------------------------------------------- /SGF-ICCV2015/exe/VisualMap.m: -------------------------------------------------------------------------------- 1 | function VisualMap(data,Title) 2 | 3 | 4 | data=double(data(:,:,1)); 5 | data=flipud(data); 6 | Handle = pcolor( data ); 7 | %figure; 8 | %set('name',title,'Numbertitle','off'); 9 | title(Title); 10 | set( Handle , 'EdgeColor' , 'none'); 11 | caxis([min(data(:)),max(data(:))]); 12 | colormap jet; 13 | -------------------------------------------------------------------------------- /SGF-ICCV2015/exe/abstraction.m: -------------------------------------------------------------------------------- 1 | function abstraction(imgname,radius,eps,thresh,iter) 2 | 3 | format=imgname(length(imgname)-3:length(imgname)); 4 | file=imgname(1:length(imgname)-4); 5 | outfile=strcat(file,'_smooth',format); 6 | 7 | %%%%%%if you use windows please use the following command. 8 | command=sprintf('SGF.exe %s %s %s %d %.2f %.2f %d',imgname, imgname,outfile, radius,eps,thresh,iter); 9 | %%%%%%for linux 10 | %command=sprintf('./SGF %s %s %s %d %.2f %.2f %d',imgname, imgname,outfile, radius,eps,thresh,iter); 11 | dos(command); 12 | scale=6; 13 | I=imread(outfile); 14 | if(size(I,3)>1) 15 | II=double(rgb2gray(I)); 16 | else 17 | II=double(I); 18 | end 19 | [Gx,Gy]=gradient(II); 20 | G=sqrt(Gx.*Gx+Gy.*Gy); 21 | J=zeros(size(II,1),size(II,2)); 22 | J(:)=255; 23 | %K=find(G>=70); 24 | %J(K)=0; 25 | 26 | 27 | J=uint8(J-G*scale); 28 | imwrite(J,strcat(file,'_grad',format)); 29 | %e=edge(II,'canny'); 30 | e=double(J)<180; 31 | %temp=imfilter(double(e),ones(5,5),'same'); 32 | e=imfilter(double(e),ones(2,1),'same'); 33 | tag=e>0; 34 | for i=1:size(I,3) 35 | p=I(:,:,i); 36 | p(tag)=0; 37 | I(:,:,i)=p; 38 | end 39 | imwrite(I,strcat(file,'_abs',format)); 40 | return; -------------------------------------------------------------------------------- /SGF-ICCV2015/exe/demo_abs.m: -------------------------------------------------------------------------------- 1 | for index=1:7 2 | filename=sprintf('abs/%d.png',index); 3 | eps=0.1; 4 | radius=16; 5 | if(index>4) 6 | eps=0.05; 7 | radius=8; 8 | end 9 | abstraction(filename,radius,eps,0.1,3); 10 | end 11 | -------------------------------------------------------------------------------- /SGF-ICCV2015/exe/demo_depth.m: -------------------------------------------------------------------------------- 1 | close all; 2 | 3 | guidfile='depth/guid.png'; 4 | 5 | targetfile='depth/noise.png'; 6 | outfile='depth/denoise.png'; 7 | %%%%%%if you use windows please use the following command. 8 | command=sprintf('SGF.exe %s %s %s %d %.2f %.2f %d',guidfile, targetfile,outfile, 32,0.04,0.4,1); 9 | %%%%%%for linux 10 | %command=sprintf('./SGF %s %s %s %d %.2f %.2f %d',guidfile, targetfile,outfile, 32,0.05,0.05,1); 11 | dos(command); 12 | img=imread(outfile); 13 | img=img(:,:,1); 14 | temp=medfilt2(img,[5,5]); 15 | img(3:size(img,1)-2,3:size(img,2)-2)=temp(3:size(img,1)-2,3:size(img,2)-2); 16 | imwrite(img,outfile); 17 | 18 | temp=imread(targetfile); 19 | VisualMap(temp,'noisy depth map as input'); 20 | figure; 21 | VisualMap(img,'denoising result'); 22 | figure; 23 | 24 | targetfile='depth/seedmap.png'; 25 | outfile='depth/upsampling.png'; 26 | %%%%%%if you use windows please use the following command. 27 | command=sprintf('SGF.exe %s %s %s %d %.2f %.2f %d',guidfile, targetfile,outfile, 32,0.025,0.25,1); 28 | %%%%%%for linux 29 | %command=sprintf('./SGF %s %s %s %d %.2f %.2f %d',guidfile, targetfile,outfile, 32,0.05,0.05,1); 30 | dos(command); 31 | img=imread(outfile); 32 | img=img(:,:,1); 33 | temp=medfilt2(img,[5,5]); 34 | img(3:size(img,1)-2,3:size(img,2)-2)=temp(3:size(img,1)-2,3:size(img,2)-2); 35 | imwrite(img,outfile); 36 | VisualMap(img,'8 times depth upsampling result'); 37 | figure; 38 | temp=imread('depth/ground.png'); 39 | temp=medfilt2(img,[5,5]); 40 | VisualMap(temp,'ground truth'); 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /SGF-ICCV2015/exe/demo_iterative.m: -------------------------------------------------------------------------------- 1 | dos('SGF.exe iterative/1.png iterative/1.png iterative/1_30iter.png 16 0.1 0.1 30'); 2 | dos('SGF.exe iterative/2.png iterative/2.png iterative/2_8iter.png 16 0.1 0.1 8'); 3 | dos('SGF.exe iterative/3.png iterative/3.png iterative/3_20iter.png 16 0.1 0.1 20'); 4 | dos('SGF.exe iterative/4.png iterative/4.png iterative/4_20iter.png 16 0.1 0.1 20'); 5 | -------------------------------------------------------------------------------- /SGF-ICCV2015/exe/demo_smooth.m: -------------------------------------------------------------------------------- 1 | close all; 2 | index=0; 3 | imgname=sprintf('smooth/%d.png',index); 4 | format=imgname(length(imgname)-3:length(imgname)); 5 | file=imgname(1:length(imgname)-4); 6 | outfile=strcat(file,'_denoise',format); 7 | radius=12; 8 | eps=0.05; 9 | thresh=0.1; 10 | iter=3; 11 | command=sprintf('SGF.exe %s %s %s %d %.2f %.2f %d',imgname, imgname,outfile, radius,eps,thresh,iter); 12 | %%%%%%for linux 13 | %command=sprintf('./SGF %s %s %s %d %.2f %.2f %d',imgname, imgname,outfile, radius,eps,thresh,iter); 14 | dos(command); 15 | img=imread(imgname); 16 | VisualMap(img,'input'); 17 | figure; 18 | img=imread(outfile); 19 | VisualMap(img,'denoising result'); 20 | figure; 21 | outfile=strcat(file,'_smooth',format); 22 | radius=25; 23 | eps=0.06; 24 | thresh=0.2; 25 | iter=8; 26 | command=sprintf('SGF.exe %s %s %s %d %.2f %.2f %d',imgname, imgname,outfile, radius,eps,thresh,iter); 27 | %%%%%%for linux 28 | %command=sprintf('./SGF %s %s %s %d %.2f %.2f %d',imgname, imgname,outfile, radius,eps,thresh,iter); 29 | dos(command); 30 | img=imread(outfile); 31 | VisualMap(img,'smooth effects'); 32 | 33 | command=sprintf('SGF.exe %s %s %s %d %.2f %.2f %d',imgname, imgname,outfile, radius,eps,thresh,iter); 34 | %%%%%%for linux 35 | %command=sprintf('./SGF %s %s %s %d %.2f %.2f %d',imgname, imgname,outfile, radius,eps,thresh,iter); 36 | dos('SGF.exe smooth/1.png smooth/1.png smooth/1_smooth.png 12 0.1 0.2 3'); 37 | dos('SGF.exe smooth/2.png smooth/2.png smooth/2_smooth.png 16 0.05 0.1 3'); 38 | dos('SGF.exe smooth/3.png smooth/3.png smooth/3_smooth.png 8 0.05 0.2 3'); 39 | %} 40 | -------------------------------------------------------------------------------- /SGF-ICCV2015/exe/demo_texture.m: -------------------------------------------------------------------------------- 1 | dos('SGF.exe texture/1.png texture/1.png texture/1_smooth.png 10 0.065 0.1 6'); 2 | dos('SGF.exe texture/2.png texture/2.png texture/2_smooth.png 12 0.065 0.1 6'); 3 | dos('SGF.exe texture/3.png texture/3.png texture/3_smooth.png 16 0.065 0.1 4'); 4 | dos('SGF.exe texture/4.png texture/4.png texture/4_smooth.png 12 0.065 0.1 4'); 5 | dos('SGF.exe texture/5.png texture/5.png texture/5_smooth.png 12 0.065 0.1 3'); 6 | dos('SGF.exe texture/6.png texture/6.png texture/6_smooth.png 12 0.065 0.1 6'); 7 | dos('SGF.exe texture/7.png texture/7.png texture/7_smooth.png 12 0.065 0.1 6'); -------------------------------------------------------------------------------- /SGF-ICCV2015/exe/depth/shrink.m: -------------------------------------------------------------------------------- 1 | function shrink(file,scale) 2 | img=imread(file); 3 | [m,n,p]=size(img); 4 | img=img(:,:,1); 5 | m1=floor(m/scale); 6 | n1=floor(n/scale); 7 | I=uint8(zeros(m1,n1)); 8 | new=uint8(zeros(m,n)); 9 | for row=1:m 10 | for col=1:n 11 | if mod(row,scale)==0&mod(col,scale)==0 12 | I(row/scale,col/scale)=img(row,col); 13 | new(row,col)=img(row,col); 14 | end 15 | end 16 | end 17 | imwrite(I,'shrink.png'); 18 | imwrite(new,'seedmap.png'); 19 | 20 | 21 | -------------------------------------------------------------------------------- /SGF-ICCV2015/exe/readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/SGF-ICCV2015/exe/readme.txt -------------------------------------------------------------------------------- /SGF-ICCV2015/opencv_core248.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/SGF-ICCV2015/opencv_core248.dll -------------------------------------------------------------------------------- /SGF-ICCV2015/opencv_highgui248.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/SGF-ICCV2015/opencv_highgui248.dll -------------------------------------------------------------------------------- /SGF-ICCV2015/opencv_imgproc248.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/SGF-ICCV2015/opencv_imgproc248.dll -------------------------------------------------------------------------------- /SGF-ICCV2015/src/Image.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/SGF-ICCV2015/src/Image.h -------------------------------------------------------------------------------- /SGF-ICCV2015/src/SGF.cpp: -------------------------------------------------------------------------------- 1 | #include "Image.h" 2 | /* 3 | guid: can be CV_8UC3(color) or CV_8UC1(gray) image; 4 | target: must be CV_8UC3(color) image; 5 | Radius: radius of the filtering window; 6 | Eps: just like the bilateral filter value. range: (0,1) 7 | Thresh: As Described in the paper. range: (0,1) 8 | */ 9 | Mat Image::FilteringColor(Mat &guid, Mat &target, int Radius, float Eps, float Thresh) 10 | { 11 | initial(guid,Radius, Eps,Thresh); 12 | float *cost=new float[width*height]; 13 | float * out=new float[width*height]; 14 | float * normal=new float[width*height]; 15 | for(int i=0;i(i/width,i%width)[0]+target.at(i/width,i%width)[1]+target.at(i/width,i%width)[2]>1e-6) 18 | cost[i]=1; 19 | else 20 | cost[i]=0; 21 | } 22 | 23 | LocalFilter(cost,normal); 24 | cv::Mat save(height, width, CV_8UC3); 25 | for(int k=0;k<3;k++) 26 | { 27 | for(int i=0;i(i/width,i%width)[k]); 30 | } 31 | 32 | LocalFilter(cost,out); 33 | 34 | for(int i=0;i(i/width,i%width)[k]=(int)max(0,min(255,(int)(out[i]/normal[i]+0.5))); 38 | } 39 | } 40 | 41 | delete [] cost; 42 | delete [] normal; 43 | delete [] out; 44 | FreeMem(); 45 | return save; 46 | } 47 | /* 48 | target: must be CV_32FC1, one-channel float mat; 49 | 50 | To use this function, you must first Initialize the SGF by: 51 | initial(guid,Radius, Eps, Thresh); 52 | Parameters are similar to FilteringGray and FilteringColor; 53 | 54 | */ 55 | Mat Image::Filtering(Mat target) 56 | { 57 | float *cost=new float[width*height]; 58 | float * out=new float[width*height]; 59 | float * normal=new float[width*height]; 60 | for(int i=0;i(i/width,i%width)>1e-6) 63 | cost[i]=1; 64 | else 65 | cost[i]=0; 66 | } 67 | LocalFilter(cost,normal); 68 | cv::Mat save(height, width, CV_32FC1); 69 | for(int i=0;i(i/width,i%width)); 71 | 72 | LocalFilter(cost,out); 73 | 74 | for(int i=0;i(i/width,i%width)=max(0,min(255,(int)(out[i]/normal[i]+0.5))); 76 | delete [] cost; 77 | delete [] normal; 78 | delete [] out; 79 | return save; 80 | 81 | } 82 | /* 83 | guid: can be CV_8UC3(color) or CV_8UC1(gray) image; 84 | target: must be CV_8UC1(gray) image; 85 | Radius: radius of the filtering window; 86 | Eps: just like the bilateral filter value. range: (0,1) 87 | Thresh: As Described in the paper. range: (0,1) 88 | */ 89 | Mat Image::FilteringGray(Mat guid, Mat target, int Radius,float Eps, float Thresh) 90 | { 91 | 92 | initial(guid,Radius, Eps, Thresh); 93 | float *cost=new float[width*height]; 94 | float * out=new float[width*height]; 95 | float * normal=new float[width*height]; 96 | for(int i=0;i(i/width,i%width)>0) 99 | cost[i]=1; 100 | else 101 | cost[i]=0; 102 | } 103 | LocalFilter(cost,normal); 104 | cv::Mat save(height, width, CV_8UC1); 105 | for(int i=0;i(i/width,i%width)); 107 | 108 | LocalFilter(cost,out); 109 | 110 | for(int i=0;i(i/width,i%width)=max(0,min(255,(int)(out[i]/normal[i]+0.5))); 112 | delete [] cost; 113 | delete [] normal; 114 | delete [] out; 115 | FreeMem(); 116 | return save; 117 | } 118 | /* 119 | 120 | guid and target must be can be the same image, CV_8UC3(color) or CV_8UC1(gray); 121 | Radius: radius of the filtering window; 122 | Eps: just like the bilateral filter value. range: (0,1); 123 | Thresh: As Described in the paper. range: (0,1); 124 | Iter: Iterative times for iterative filtering. 125 | */ 126 | Mat Image::IterFiltering(Mat&guid,Mat &target,int radius, float eps, float thresh,int Iter) 127 | { 128 | Mat temp; 129 | Mat out; 130 | guid.copyTo(temp); 131 | for(int i=0;i=3) 135 | { 136 | 137 | out=FilteringColor(guid,target,radius,eps,thresh); 138 | } 139 | else 140 | out=FilteringGray(guid,target,radius,eps,thresh); 141 | if((i+1)%3==0) 142 | { 143 | out.copyTo(target); 144 | if(target.channels()>=3) 145 | out=FilteringColor(temp,target,radius,0.025,thresh); 146 | else 147 | out=FilteringGray(temp,target,radius,0.025,thresh); 148 | } 149 | out.copyTo(guid); 150 | out.copyTo(target); 151 | 152 | } 153 | return out; 154 | } 155 | -------------------------------------------------------------------------------- /SGF-ICCV2015/src/SLIC.h: -------------------------------------------------------------------------------- 1 | #if !defined(_SLIC_H_INCLUDED_) 2 | #define _SLIC_H_INCLUDED_ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | 11 | class SLIC 12 | { 13 | public: 14 | SLIC(); 15 | virtual ~SLIC(); 16 | //============================================================================ 17 | // Superpixel segmentation for a given step size (superpixel size ~= step*step) 18 | //============================================================================ 19 | void DoSuperpixelSegmentation_ForGivenSuperpixelSize( 20 | const unsigned int* ubuff,//Each 32 bit unsigned int contains ARGB pixel values. 21 | const int width, 22 | const int height, 23 | int*& klabels, 24 | int& numlabels, 25 | const int& superpixelsize, 26 | const double& compactness); 27 | //============================================================================ 28 | // Superpixel segmentation for a given number of superpixels 29 | //============================================================================ 30 | void DoSuperpixelSegmentation_ForGivenNumberOfSuperpixels( 31 | const unsigned int* ubuff, 32 | const int width, 33 | const int height, 34 | int*& klabels, 35 | int& numlabels, 36 | const int& K,//required number of superpixels 37 | const double& compactness);//10-20 is a good value for CIELAB space 38 | //============================================================================ 39 | // Supervoxel segmentation for a given step size (supervoxel size ~= step*step*step) 40 | //============================================================================ 41 | void DoSupervoxelSegmentation( 42 | unsigned int**& ubuffvec, 43 | const int& width, 44 | const int& height, 45 | const int& depth, 46 | int**& klabels, 47 | int& numlabels, 48 | const int& supervoxelsize, 49 | const double& compactness); 50 | //============================================================================ 51 | // Save superpixel labels in a text file in raster scan order 52 | //============================================================================ 53 | void SaveSuperpixelLabels( 54 | // const int*& labels, 55 | int*& labels, 56 | const int& width, 57 | const int& height, 58 | const string& filename, 59 | const string& path); 60 | //============================================================================ 61 | // Save supervoxel labels in a text file in raster scan, depth order 62 | //============================================================================ 63 | void SaveSupervoxelLabels( 64 | const int**& labels, 65 | const int& width, 66 | const int& height, 67 | const int& depth, 68 | const string& filename, 69 | const string& path); 70 | //============================================================================ 71 | // Function to draw boundaries around superpixels of a given 'color'. 72 | // Can also be used to draw boundaries around supervoxels, i.e layer by layer. 73 | //============================================================================ 74 | void DrawContoursAroundSegments( 75 | unsigned int*& segmentedImage, 76 | int*& labels, 77 | const int& width, 78 | const int& height, 79 | const unsigned int& color ); 80 | 81 | private: 82 | //============================================================================ 83 | // The main SLIC algorithm for generating superpixels 84 | //============================================================================ 85 | void PerformSuperpixelSLIC( 86 | vector& kseedsl, 87 | vector& kseedsa, 88 | vector& kseedsb, 89 | vector& kseedsx, 90 | vector& kseedsy, 91 | int*& klabels, 92 | const int& STEP, 93 | const vector& edgemag, 94 | const double& m = 10.0); 95 | //============================================================================ 96 | // The main SLIC algorithm for generating supervoxels 97 | //============================================================================ 98 | void PerformSupervoxelSLIC( 99 | vector& kseedsl, 100 | vector& kseedsa, 101 | vector& kseedsb, 102 | vector& kseedsx, 103 | vector& kseedsy, 104 | vector& kseedsz, 105 | int**& klabels, 106 | const int& STEP, 107 | const double& compactness); 108 | //============================================================================ 109 | // Pick seeds for superpixels when step size of superpixels is given. 110 | //============================================================================ 111 | void GetLABXYSeeds_ForGivenStepSize( 112 | vector& kseedsl, 113 | vector& kseedsa, 114 | vector& kseedsb, 115 | vector& kseedsx, 116 | vector& kseedsy, 117 | const int& STEP, 118 | const bool& perturbseeds, 119 | const vector& edgemag); 120 | //============================================================================ 121 | // Pick seeds for supervoxels 122 | //============================================================================ 123 | void GetKValues_LABXYZ( 124 | vector& kseedsl, 125 | vector& kseedsa, 126 | vector& kseedsb, 127 | vector& kseedsx, 128 | vector& kseedsy, 129 | vector& kseedsz, 130 | const int& STEP); 131 | //============================================================================ 132 | // Move the superpixel seeds to low gradient positions to avoid putting seeds 133 | // at region boundaries. 134 | //============================================================================ 135 | void PerturbSeeds( 136 | vector& kseedsl, 137 | vector& kseedsa, 138 | vector& kseedsb, 139 | vector& kseedsx, 140 | vector& kseedsy, 141 | const vector& edges); 142 | //============================================================================ 143 | // Detect color edges, to help PerturbSeeds() 144 | //============================================================================ 145 | void DetectLabEdges( 146 | const double* lvec, 147 | const double* avec, 148 | const double* bvec, 149 | const int& width, 150 | const int& height, 151 | vector& edges); 152 | //============================================================================ 153 | // sRGB to XYZ conversion; helper for RGB2LAB() 154 | //============================================================================ 155 | void RGB2XYZ( 156 | const int& sR, 157 | const int& sG, 158 | const int& sB, 159 | double& X, 160 | double& Y, 161 | double& Z); 162 | //============================================================================ 163 | // sRGB to CIELAB conversion (uses RGB2XYZ function) 164 | //============================================================================ 165 | void RGB2LAB( 166 | const int& sR, 167 | const int& sG, 168 | const int& sB, 169 | double& lval, 170 | double& aval, 171 | double& bval); 172 | //============================================================================ 173 | // sRGB to CIELAB conversion for 2-D images 174 | //============================================================================ 175 | void DoRGBtoLABConversion( 176 | const unsigned int*& ubuff, 177 | double*& lvec, 178 | double*& avec, 179 | double*& bvec); 180 | //============================================================================ 181 | // sRGB to CIELAB conversion for 3-D volumes 182 | //============================================================================ 183 | void DoRGBtoLABConversion( 184 | unsigned int**& ubuff, 185 | double**& lvec, 186 | double**& avec, 187 | double**& bvec); 188 | //============================================================================ 189 | // Post-processing of SLIC segmentation, to avoid stray labels. 190 | //============================================================================ 191 | void EnforceLabelConnectivity( 192 | const int* labels, 193 | const int width, 194 | const int height, 195 | int*& nlabels,//input labels that need to be corrected to remove stray labels 196 | int& numlabels,//the number of labels changes in the end if segments are removed 197 | const int& K); //the number of superpixels desired by the user 198 | //============================================================================ 199 | // Post-processing of SLIC supervoxel segmentation, to avoid stray labels. 200 | //============================================================================ 201 | void EnforceSupervoxelLabelConnectivity( 202 | int**& labels,//input - previous labels, output - new labels 203 | const int& width, 204 | const int& height, 205 | const int& depth, 206 | int& numlabels, 207 | const int& STEP); 208 | 209 | private: 210 | int m_width; 211 | int m_height; 212 | int m_depth; 213 | 214 | double* m_lvec; 215 | double* m_avec; 216 | double* m_bvec; 217 | 218 | double** m_lvecvec; 219 | double** m_avecvec; 220 | double** m_bvecvec; 221 | }; 222 | 223 | #endif // !defined(_SLIC_H_INCLUDED_) 224 | -------------------------------------------------------------------------------- /SGF-ICCV2015/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include"Image.h" 2 | int main( int argc, char *argv[]) 3 | { 4 | char guidfile[200]; 5 | char dstfile[200]; 6 | char outfile[200]; 7 | int radius; 8 | float thresh=1; 9 | float eps; 10 | int Iter=1; 11 | Mat guid; 12 | Mat target; 13 | Mat out; 14 | #if 1 15 | if(argc<6||argc>8) 16 | { 17 | cout<<"SGF command format:"<=6) 23 | { 24 | sprintf(guidfile,"%s",argv[1]); 25 | sprintf(dstfile,"%s",argv[2]); 26 | sprintf(outfile,"%s",argv[3]); 27 | radius=atoi(argv[4]); 28 | eps=atof(argv[5]); 29 | } 30 | if(argc>=7) 31 | { 32 | thresh=atof(argv[6]); 33 | } 34 | if(argc==8) 35 | { 36 | Iter=atoi(argv[7]); 37 | } 38 | #else 39 | sprintf(guidfile,"1.png"); 40 | sprintf(dstfile,"1.png"); 41 | sprintf(outfile,"out.png"); 42 | radius=25; 43 | eps=0.06; 44 | Iter=10; 45 | #endif 46 | Image img; 47 | guid=imread(guidfile,1); 48 | //imwrite("guid.png",guid); 49 | 50 | target=imread(dstfile,-1); 51 | //cout<=3) 53 | target=imread(dstfile,1); 54 | if(Iter==1) 55 | { 56 | if(target.channels()>=3) 57 | out=img.FilteringColor(guid,target,radius,eps,thresh); 58 | else 59 | out=img.FilteringGray(guid,target,radius,eps,thresh); 60 | } 61 | else 62 | { 63 | if(strcmp(guidfile,dstfile)!=0) 64 | { 65 | cout<<"Warning: the guidance and the target should be the same image for iterative filtering."; 66 | cout<<" Therefore, guidance image is neglected ..."<> mex splitBregmanROF.c 14 | *This file has been tested under windows using lcc, and under SUSE Unix using gcc. 15 | *Once the file is compiled, the command "splitBregmanROF" can be used just like any 16 | *other MATLAB m-file. 17 | * 18 | * HOW TO USE THIS CODE 19 | * An image is denoised using the following command 20 | * 21 | * SplitBregmanROF(image,mu,tol); 22 | * 23 | * where: 24 | * - "image" is a 2d array containing the noisy image. 25 | * - "mu" is the weighting parameter for the fidelity term 26 | * (usually a value between 0.01 and 0.5 works well for images with 27 | * pixels on the 0-255 scale). 28 | * - "tol" is the stopping tolerance for the iteration. "tol"=0.001 is reasonable for 29 | * most applications. 30 | * 31 | */ 32 | 33 | #include 34 | #include "mex.h" 35 | #include 36 | #include 37 | typedef double num; 38 | 39 | 40 | /*A method for isotropic TV*/ 41 | void rof_iso(num** u, num** f, num** x, num** y, num** bx, num** by , 42 | double mu, double lambda, int nGS, int nBreg, int width, int height); 43 | 44 | /*A method for Anisotropic TV*/ 45 | void rof_an(num** u, num** f, num** x, num** y, num** bx, num** by , 46 | double mu, double lambda, int nGS, int nBreg, int width, int height); 47 | 48 | /*****************Minimization Methods*****************/ 49 | void gs_an(num** u, num** f, num** x, num** y, num** bx, num** by , double mu, double lambda, int width, int height, int iter); 50 | void gs_iso(num** u, num** f, num** x, num** y, num** bx, num** by , double mu, double lambda, int width, int height, int iter); 51 | 52 | /******************Relaxation Methods*****************/ 53 | void gsU(num** u, num** f, num** x, num** y, num** bx, num** by , double mu, double lambda, int width, int height); 54 | void gsX(num** u, num** x, num** bx , double lambda, int width, int height); 55 | void gsY(num** u, num** y, num** by , double lambda, int width, int height); 56 | void gsSpace(num** u, num** x, num** y, num** bx, num** by, double lambda, int width, int height); 57 | 58 | /************************Bregman***********************/ 59 | void bregmanX(num** x,num** u, num** bx, int width, int height); 60 | void bregmanY(num** y,num** u, num** by, int width, int height); 61 | 62 | /**********************Memory************/ 63 | 64 | num** newMatrix(int rows, int cols); 65 | void deleteMatrix(num ** a); 66 | double** get2dArray(const mxArray *mx, int isCopy); 67 | double copy(double** source, double** dest, int rows, int cols); 68 | 69 | /***********************The MEX Interface to rof_iso()***************/ 70 | 71 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 72 | { 73 | /* get the size of the image*/ 74 | int rows = mxGetN(prhs[0]); 75 | int cols = mxGetM(prhs[0]); 76 | 77 | /* get the fidelity and convergence parameters*/ 78 | double mu = (double)(mxGetScalar(prhs[1])); 79 | double lambda = 2*mu; 80 | double tol = (double)(mxGetScalar(prhs[2])); 81 | 82 | /* get the image, and declare memory to hold the auxillary variables*/ 83 | double **f = get2dArray(prhs[0],0); 84 | double **u = newMatrix(rows,cols); 85 | double **x = newMatrix(rows-1,cols); 86 | double **y = newMatrix(rows,cols-1); 87 | double **bx = newMatrix(rows-1,cols); 88 | double **by = newMatrix(rows,cols-1); 89 | 90 | double** uOld; 91 | double *outArray; 92 | double diff; 93 | int count; 94 | int i,j; 95 | 96 | /***********Check Conditions******/ 97 | if (nrhs != 3) {mexErrMsgTxt("Three input arguments required.");} 98 | if (nlhs > 1){mexErrMsgTxt("Too many output arguments.");} 99 | if (!(mxIsDouble(prhs[0]))) {mexErrMsgTxt("Input array must be of type double.");} 100 | 101 | /* Use a copy of the image as an initial guess*/ 102 | for(i=0;itol && count<1000) || count<5 ); 117 | 118 | /* copy denoised image to output vector*/ 119 | plhs[0] = mxCreateDoubleMatrix(cols, rows, mxREAL); /*mxReal is our data-type*/ 120 | outArray = mxGetPr(plhs[0]); 121 | 122 | for(i=0;iflux) {x[w][h] = base-flux; continue;} 342 | if(baseflux) {y[w][h] = base-flux; continue;} 349 | if(baseflux) {xw[h] = base-flux; continue;} 373 | if(baseflux) {yw[h] = base-flux; continue;} 395 | if(base255) = 255; g_hat(g_hat<0) = 0; 23 | t1 = toc; 24 | fprintf('Done. Runtime = %f sec\n\n', t1); 25 | 26 | % Brute-force filter 27 | fprintf('Running brute-force filter...\n'); 28 | tic; 29 | g = abf_bruteforce(f,rho,sigma_r,f+zeta); 30 | g(g>255) = 255; g(g<0) = 0; 31 | t2 = toc; 32 | fprintf('Done. Runtime = %f sec\n\n', t2); 33 | 34 | fprintf('PSNR (bruteforce vs. fast) = %f dB\n', psnr(g_hat,g,255)); 35 | 36 | figure, imshow(uint8(g)); title('Output using brute-force filter'); drawnow; pause(0.1); 37 | figure, imshow(uint8(g_hat)); title('Output using fast algorithm'); drawnow; pause(0.1); 38 | -------------------------------------------------------------------------------- /fastABF-TIP2019/demo_smooth.m: -------------------------------------------------------------------------------- 1 | 2 | clearvars; close all; 3 | clc; 4 | 5 | %% Edge-preserving smoothing example 6 | clear,close; 7 | 8 | Original_image_dir = '/home/csjunxu/Github/data/dataset/origin_images'; 9 | fpath = fullfile(Original_image_dir, '*.png'); 10 | im_dir = dir(fpath); 11 | im_num = length(im_dir); 12 | 13 | method = 'fastABF'; 14 | addpath('./fastABF/'); 15 | rho_smooth = 2; % Spatial kernel parameter for smoothing step 16 | 17 | for i = 1:im_num 18 | I = imread(fullfile(Original_image_dir, im_dir(i).name)); 19 | S = regexp(im_dir(i).name, '\.', 'split'); 20 | I = double(I); 21 | 22 | % Set pixelwise sigma (range kernel parameters) for smoothing 23 | M = mrtv(I,5); 24 | sigma_smooth = linearMap(1-M,[0,1],[30,70]); 25 | sigma_smooth = imdilate(sigma_smooth,strel('disk',2,4)); % Clean up the fine noise 26 | % Apply fast algorithm to smooth textures 27 | sI = I; 28 | tic; 29 | for it = 1:2 30 | out = nan(size(I)); 31 | for k = 1:size(I,3) 32 | out(:,:,k) = fastABF(sI(:,:,k),rho_smooth,sigma_smooth,[],4); 33 | end 34 | sI = out; 35 | sigma_smooth = sigma_smooth*0.8; 36 | end 37 | fprintf('%s is done!\n', im_dir(i).name); 38 | outname = sprintf(['/home/csjunxu/Github/data/dataset/results/' S{1} '_' method '.png']); 39 | imwrite(sI/255, outname); 40 | end -------------------------------------------------------------------------------- /fastABF-TIP2019/demo_texture.m: -------------------------------------------------------------------------------- 1 | 2 | clearvars; close all; 3 | clc; 4 | 5 | input_image = './fish.jpg'; 6 | rho_smooth = 2; % Spatial kernel parameter for smoothing step 7 | rho_sharp = 4; % Spatial kernel parameter for sharpening step 8 | 9 | f = imread(input_image); 10 | f = double(f); 11 | 12 | addpath('./fastABF/'); 13 | 14 | % Set pixelwise sigma (range kernel parameters) for smoothing 15 | M = mrtv(f,5); 16 | sigma_smooth = linearMap(1-M,[0,1],[30,70]); 17 | sigma_smooth = imdilate(sigma_smooth,strel('disk',2,4)); % Clean up the fine noise 18 | 19 | % Apply fast algorithm to smooth textures 20 | g = f; 21 | tic; 22 | for it = 1:2 23 | out = nan(size(f)); 24 | for k = 1:size(f,3) 25 | out(:,:,k) = fastABF(g(:,:,k),rho_smooth,sigma_smooth,[],4); 26 | end 27 | g = out; 28 | sigma_smooth = sigma_smooth*0.8; 29 | end 30 | 31 | % Apply fast algorithm to sharpen edges 32 | % Large variation in sigma is not required for this step 33 | g_gray = double(rgb2gray(uint8(g))); 34 | [zeta,sigma_sharp] = logClassifier(g_gray,rho_sharp,[30,31]); 35 | for it = 1:2 % Run more iterations for greater sharpening 36 | for k = 1:size(f,3) 37 | g(:,:,k) = fastABF(g(:,:,k),rho_sharp,sigma_sharp,g(:,:,k)+zeta,5); 38 | end 39 | end 40 | toc; 41 | 42 | figure, imshow(uint8(f)); title('Input'); drawnow; pause(0.01); 43 | figure, imshow(uint8(g)); title('Output'); drawnow; pause(0.01); 44 | -------------------------------------------------------------------------------- /fastABF-TIP2019/fastABF/MinMaxFilter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: MinMaxFilter.cpp 5 | * 6 | * Description: 7 | * 8 | * Version: 1.0 9 | * Created: Thursday 05 October 2017 04:03:22 IST 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: Ruturaj Gavaskar (), 14 | * Organization: 15 | * 16 | * ===================================================================================== 17 | */ 18 | 19 | #ifndef MINMAXFILTER_CPP 20 | #define MINMAXFILTER_CPP 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | void applyPostReplicatePadding(double* in, int rows, int cols, int rowpad, int colpad, double* out) 28 | { 29 | double *src, *dst; 30 | if(colpad==0) 31 | { 32 | std::memcpy(out,in,rows*cols*sizeof(double)); 33 | } 34 | else 35 | { 36 | for(int i=0; i Lmin,Rmin,Lmax,Rmax; 68 | int k,p,q; 69 | double rmax,lmax,rmin,lmin; 70 | double *tminptr, *tmaxptr; 71 | 72 | /* Scan along rows */ 73 | Lmax.resize(n); Lmin.resize(n); 74 | Rmax.resize(n); Rmin.resize(n); 75 | for(int ii=1; ii<=minput; ii++) 76 | { 77 | tmaxptr = templateMax+(ii-1)*n; 78 | tminptr = templateMin+(ii-1)*n; 79 | Lmax[0] = tmaxptr[0]; Lmin[0] = tminptr[0]; 80 | Rmax[n-1] = tmaxptr[n-1]; Rmin[n-1] = tminptr[n-1]; 81 | for(k=2; k<=n; k++) 82 | { 83 | if((k-1)%w==0) 84 | { 85 | Lmax[k-1] = tmaxptr[k-1]; 86 | Rmax[n-k] = tmaxptr[n-k]; 87 | Lmin[k-1] = tminptr[k-1]; 88 | Rmin[n-k] = tminptr[n-k]; 89 | } 90 | else 91 | { 92 | Lmax[k-1] = (Lmax[k-2]>tmaxptr[k-1]) ? Lmax[k-2] : tmaxptr[k-1]; 93 | Rmax[n-k] = (Rmax[n-k+1]>tmaxptr[n-k]) ? Rmax[n-k+1] : tmaxptr[n-k]; 94 | Lmin[k-1] = (Lmin[k-2]::infinity() : Rmin[p-1]; 104 | lmax = (q>n) ? -1 : Lmax[q-1]; 105 | lmin = (q>n) ? std::numeric_limits::infinity() : Lmin[q-1]; 106 | tmaxptr[k-1] = (rmax>lmax) ? rmax : lmax; 107 | tminptr[k-1] = (rmintmaxptr[(k-1)*n]) ? Lmax[k-2] : tmaxptr[(k-1)*n]; 132 | Rmax[m-k] = (Rmax[m-k+1]>tmaxptr[(m-k)*n]) ? Rmax[m-k+1] : tmaxptr[(m-k)*n]; 133 | Lmin[k-1] = (Lmin[k-2]::infinity() : Rmin[p-1]; 143 | lmax = (q>m) ? -1 : Lmax[q-1]; 144 | lmin = (q>m) ? std::numeric_limits::infinity() : Lmin[q-1]; 145 | if(k<=minput) 146 | { 147 | fmax[(k-1)*ninput+jj-1] = (rmax>lmax) ? rmax : lmax; 148 | fmin[(k-1)*ninput+jj-1] = (rmin(mxGetScalar(WINSIZE)); 190 | if(w%2==0) { mexErrMsgTxt("w must be odd"); } 191 | 192 | const mwSize* size; 193 | size = mxGetDimensions(IMAGE_IN); 194 | int rows = static_cast(size[0]); 195 | int columns = static_cast(size[1]); 196 | 197 | double* f = mxGetPr(IMAGE_IN); 198 | ALPHA = mxCreateDoubleMatrix(rows, columns, mxREAL); 199 | BETA = mxCreateDoubleMatrix(rows, columns, mxREAL); 200 | double* alpha = mxGetPr(ALPHA); 201 | double* beta = mxGetPr(BETA); 202 | 203 | /* Matlab stores a matrix in column-major form. Convert it to 204 | row-major form first. */ 205 | double* F = new double[rows*columns]; 206 | matTranspose(f,columns,rows,F); 207 | 208 | double* alpha_temp = new double[rows*columns]; 209 | double* beta_temp = new double[rows*columns]; 210 | minmaxFilter(F,rows,columns,w,alpha_temp,beta_temp); 211 | matTranspose(alpha_temp,rows,columns,alpha); 212 | matTranspose(beta_temp,rows,columns,beta); 213 | 214 | delete [] F; 215 | delete [] alpha_temp; 216 | delete [] beta_temp; 217 | } 218 | 219 | #endif /* MATLAB_MEX_FILE */ 220 | 221 | #endif /* MINMAXFILTER_CPP */ 222 | 223 | -------------------------------------------------------------------------------- /fastABF-TIP2019/fastABF/MinMaxFilter.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/fastABF-TIP2019/fastABF/MinMaxFilter.mexa64 -------------------------------------------------------------------------------- /fastABF-TIP2019/fastABF/compInt.m: -------------------------------------------------------------------------------- 1 | function [ I ] = compInt( N,lambda,t0 ) 2 | %COMPINT 3 | % Compute integrals using recursion 4 | % N = Degree of polynomial 5 | % lambda = Parameter of shifted Gaussian (see paper) 6 | % t0 = Center of shifted Gaussian (see paper) 7 | % I = Cell array (output) containing integrals 8 | 9 | I = cell(1,N+1); 10 | zero = 1; 11 | rootL = sqrt(lambda); 12 | Ulim = lambda.*(1-t0).*(1-t0); 13 | expU = exp(-Ulim); 14 | 15 | % Compute I_0 and I_1 directly 16 | I{zero} = 0.5 * sqrt(pi./lambda) .* ... 17 | ( erf(rootL.*(1-t0)) - erf(-rootL.*t0) ); 18 | I{zero+1} = t0.*I{zero} - ... 19 | (expU - exp(-lambda.*t0.*t0))./(2*lambda); 20 | 21 | for k = 2:N % Use recurrence relation for k>1 22 | I{zero+k} = t0.*I{zero+k-1} + ... 23 | ((k-1)*I{zero+k-2} - expU)./(2*lambda); 24 | end 25 | 26 | end 27 | 28 | -------------------------------------------------------------------------------- /fastABF-TIP2019/fastABF/fastABF.m: -------------------------------------------------------------------------------- 1 | function [ g_hat ] = fastABF( f,rho,sigma_r,theta,N,filtertype ) 2 | %FASTABF Fast adaptive bilateral filter for grayscale images 3 | % 4 | % g_hat = fastABF(f,rho,sigma_r) filters the input image f using the 5 | % Gaussian spatial kernel parameter rho and pixelwise Gaussian range kernel 6 | % parameters sigma_r. The centering parameters theta are equal to f by 7 | % default. 8 | % 9 | % g_hat = fastABF(f,rho,sigma_r,theta) filters the input image f using the 10 | % Gaussian spatial kernel parameter rho, pixelwise Gaussian range kernel 11 | % parameters sigma_r, and pixelwise centering parameters theta (see paper 12 | % for details). 13 | % 14 | % g_hat = fastABF(f,rho,sigma_r,theta,N) performs the same operation as 15 | % above, with N being the degree of the polynomial (N=5 by default). 16 | % It is recommended to not set N greater than 6. 17 | % 18 | % g_hat = fastABF(f,rho,sigma_r,theta,N,filtertype) performs the same 19 | % operation as above with the spatial filter type specified by the final 20 | % argument, which can be either 'gaussian' (default) or 'box'. All results 21 | % in the paper are using the Gaussian spatial kernel. If filtertype is 22 | % 'box', then rho specifies the half-width of the box kernel 23 | % (kernel length = 2*rho+1). 24 | % 25 | % Input arguments: 26 | % f = m-by-n Input image (grayscale, double type) 27 | % rho = Standard deviation of Gaussian spatial kernel OR radius of box 28 | % kernel 29 | % sigma_r = m-by-n matrix of pixelwise standard deviations of Gaussian 30 | % range kernels (scale [0,255]) 31 | % theta = m-by-n Centering image (double type) 32 | % N = Degree of polynomial to fit 33 | % filtertype = Spatial filter type, 'gaussian' (default) or 'box' 34 | % Output arguments: 35 | % g_hat = Output image using the fast algorithm 36 | % 37 | % Ref. R. G. Gavaskar and K. N. Chaudhury, "Fast Adaptive Bilateral Filtering", 38 | % IEEE Transactions on Image Processing, vol. 28, no. 2, pp. 779-790, 2019. 39 | % 40 | % Author: Ruturaj G. Gavaskar 41 | % Email: ruturajg@iisc.ac.in 42 | % This code has been tested on Matlab 9.1.0 (R2016b). 43 | % An up-to-date version of this software is available at: 44 | % https://github.com/rgavaska/Fast-Adaptive-Bilateral-Filtering. 45 | % 46 | 47 | if(~exist('theta','var') || isempty(theta)) 48 | theta = f; 49 | end 50 | if(~exist('N','var') || isempty(N)) 51 | N = 5; 52 | end 53 | if(~exist('filtertype','var') || isempty(filtertype)) 54 | filtertype = 'gaussian'; 55 | end 56 | 57 | [rr,cc] = size(f); 58 | f = f/255; 59 | theta = theta/255; 60 | sigma_r = sigma_r/255; 61 | 62 | % Compute local histogram range 63 | if(strcmp(filtertype,'gaussian')) 64 | [Alpha,Beta] = MinMaxFilter(f,6*rho+1); 65 | elseif(strcmp(filtertype,'box')) 66 | [Alpha,Beta] = MinMaxFilter(f,2*rho+1); 67 | else 68 | error('Invalid filter type'); 69 | end 70 | mask = (Alpha~=Beta); % Mask for pixels with Alpha~=Beta 71 | a = nan(rr,cc); 72 | a(mask) = 1./(Beta(mask)-Alpha(mask)); 73 | 74 | % Compute polynomial coefficients at every pixel 75 | C = fitPolynomial(f,rho,N,Alpha,Beta,filtertype); 76 | 77 | % Pre-compute integrals at every pixel 78 | zero = 1; 79 | t0 = (theta(mask)-Alpha(mask))./(Beta(mask)-Alpha(mask)); 80 | lambda = 1./(2*sigma_r(mask).*sigma_r(mask).*a(mask).*a(mask)); 81 | I = compInt(N+1,lambda,t0); 82 | 83 | % Compute numerator and denominator 84 | Num = zeros(nnz(mask),1); 85 | Den = Num; 86 | for k = 0:N 87 | Ck = C(:,zero+k); 88 | Num = Num + Ck.*I{zero+k+1}; 89 | Den = Den + Ck.*I{zero+k}; 90 | end 91 | 92 | % Undo shifting & scaling to get output (eq. 29 in paper) 93 | g_hat = nan(rr,cc); 94 | g_hat(mask) = Alpha(mask) + (Beta(mask)-Alpha(mask)).*Num./Den; 95 | g_hat(~mask) = f(~mask); 96 | g_hat = 255*g_hat; 97 | 98 | end 99 | 100 | -------------------------------------------------------------------------------- /fastABF-TIP2019/fastABF/fitPolynomial.m: -------------------------------------------------------------------------------- 1 | function [ C ] = fitPolynomial( f,rho,N,Alpha,Beta,filtertype ) 2 | %FITPOLYNOMIAL 3 | % Fit a polynomial on the local histogram at every pixel by moment-matching 4 | % Input args: 5 | % f = m-by-n input image (double precision) 6 | % sigma_s = S.D. of Gaussian spatial kernel OR half-width of box kernel 7 | % N = Degree of polynomial 8 | % Alpha = m-by-n array containing pixelwise local minimum in window 9 | % Beta = m-by-n array containing pixelwise local maximum in window 10 | % filtertype = Type of spatial filter, 'box' or 'gaussian' 11 | % Output args: 12 | % C = L-by-(N+1) matrix of polynomial coefficients, where L is the number 13 | % of pixels for which Alpha~=Beta 14 | 15 | if(strcmp(filtertype,'gaussian')) 16 | spker = fspecial('gaussian',6*rho+1,rho); 17 | else 18 | spker = fspecial('average',2*rho+1); 19 | end 20 | 21 | % Find pixels where Alpha=Beta or Alpha=0 22 | mask = (Alpha~=Beta); 23 | num_pixels = nnz(mask); 24 | Alpha = Alpha(mask); Beta = Beta(mask); 25 | Alpha0_mask = (Alpha==0); 26 | Alpha_non0 = Alpha(~Alpha0_mask); 27 | Beta_non0 = Beta(~Alpha0_mask); 28 | 29 | % Filter powers of f 30 | fpow_filt = zeros(nnz(mask),1,N+1); 31 | fpow = ones(size(f)); 32 | zero = 1; 33 | fpow_filt(:,:,zero) = 1; 34 | for k = 1:N 35 | fpow = fpow.*f; 36 | fbar = imfilter(fpow,spker,'symmetric'); 37 | fpow_filt(:,:,zero+k) = fbar(mask); 38 | end 39 | 40 | % Compute moments of the shifted histograms (using numerically stable recursion) 41 | zero = 1; 42 | M = nan(num_pixels,N+1); 43 | M(:,zero) = 1; % 0th moment is always 1 44 | multiplier = ones(nnz(~Alpha0_mask),1); 45 | Beta_k = ones(nnz(Alpha0_mask),1); 46 | for k = 1:N 47 | Beta_k = Beta_k.*Beta(Alpha0_mask); 48 | multiplier = multiplier.*(-Alpha_non0./(Beta_non0-Alpha_non0)); 49 | prevTerm = multiplier; 50 | non0_mom = prevTerm; 51 | for r = 1:k 52 | temp1 = fpow_filt(:,:,zero+r); 53 | temp2 = fpow_filt(:,:,zero+r-1); 54 | nextTerm = ((r-k-1)/r) *... 55 | ( temp1(~Alpha0_mask)./... 56 | (Alpha_non0.*temp2(~Alpha0_mask)) ) .*... 57 | prevTerm; 58 | non0_mom = non0_mom + nextTerm; 59 | prevTerm = nextTerm; 60 | end 61 | mom_k = zeros(num_pixels,1); 62 | mom_k(~Alpha0_mask) = non0_mom; 63 | temp = fpow_filt(:,:,zero+k); 64 | mom_k(Alpha0_mask) = temp(Alpha0_mask)./(Beta_k); 65 | M(:,zero+k) = mom_k; 66 | end 67 | M = M'; 68 | 69 | % Compute polynomial coefficients 70 | Hinv = invhilb(N+1); 71 | C = Hinv*M; 72 | C = C'; 73 | 74 | end 75 | -------------------------------------------------------------------------------- /fastABF-TIP2019/linearMap.m: -------------------------------------------------------------------------------- 1 | function [ Y ] = linearMap( X,xrange,yrange ) 2 | %LINEARMAP 3 | % Linearly map values in the interval [xrange(1),xrange(2)] to [yrange(1),yrange(2)] 4 | % X = Input image 5 | 6 | x1 = xrange(1); 7 | x2 = xrange(2); 8 | y1 = yrange(1); 9 | y2 = yrange(2); 10 | m = (y2-y1)/(x2-x1); 11 | c = (x2*y1-x1*y2)/(x2-x1); 12 | Y = m*X + c; 13 | 14 | end 15 | 16 | -------------------------------------------------------------------------------- /fastABF-TIP2019/logClassifier.m: -------------------------------------------------------------------------------- 1 | function [ zeta,sigma_r ] = logClassifier( f,rho,sigma_interval ) 2 | %LOGCLASSIFIER 3 | % Simulate LoG classifier to set pixelwise sigma values 4 | % Idea based on the following paper: 5 | % B. Zhang and J. P. Allebach, "Adaptive bilateral filter for sharpness 6 | % enhancement and noise removal," IEEE Transactions on Image Processing, 7 | % vol. 17, no. 5, pp. 664–678, 2008. 8 | % 9 | % Input arguments: 10 | % f = Input image 11 | % rho = Gaussian spatial kernel parameter 12 | % sigma_interval = Interval which should contain sigma values 13 | % Output arguments: 14 | % zeta = Offset image (see above paper for explanation) 15 | % sigma_r = Pixelwise range kernel parameters, set using LoG classifier 16 | 17 | h_log = fspecial('log',9,9/6); 18 | f_log = imfilter(f,h_log,'symmetric'); % LoG filter the image 19 | L = zeros(size(f)); 20 | L(f_log>60) = 60; 21 | L(f_log<-60) = -60; 22 | mask = (f_log>-60 & f_log<60); 23 | L(mask) = f_log(mask); 24 | L = round(L*2)/2; 25 | 26 | % Map LoG class values to sigma_r values 27 | sigma_r = linearMap(abs(L),[0,max(abs(L(:)))],[sigma_interval(2),sigma_interval(1)]); 28 | 29 | % Compute offset image 30 | fbar = imfilter(f,ones(6*rho+1)/((6*rho+1)^2),'symmetric'); 31 | zeta = f - fbar; % Offset image 32 | 33 | end 34 | 35 | -------------------------------------------------------------------------------- /fastABF-TIP2019/mrtv.m: -------------------------------------------------------------------------------- 1 | function [ M ] = mrtv( I,k ) 2 | %Normalized MRTV 3 | % Idea based on the following paper: 4 | % H. Cho, H. Lee, H. Kang, and S. Lee, "Bilateral texture filtering," ACM 5 | % Transactions on Graphics, vol. 33, no. 4, p. 128, 2014. 6 | % 7 | % Input arguments: 8 | % I = Input image (double) 9 | % k = Window length 10 | % Output arguments: 11 | % M = MRTV (values normalized between 0 and 1) 12 | 13 | if(size(I,3)==3) 14 | I = double(rgb2gray(uint8(I))); 15 | end 16 | 17 | I = imfilter(I,ones(5)/25,'symmetric'); 18 | 19 | [Imin,Imax] = MinMaxFilter(double(I),k); 20 | Delta = Imax - Imin; 21 | 22 | % Compute MRTV 23 | [gradI,~] = imgradient(I,'centralDifference'); 24 | [~,num] = MinMaxFilter(gradI,k); 25 | den = imfilter(gradI,ones(k),'symmetric'); 26 | M = Delta.*num./(den + 1e-9); 27 | M(den==0) = 0; 28 | M = M/max(M(:)); 29 | 30 | end 31 | 32 | -------------------------------------------------------------------------------- /fastABF-TIP2019/peppers_degraded.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csjunxu/Image-Smoothing-State-of-the-art/32ad0e6884e3ee71d83d463bd67dfd9b5cdc0245/fastABF-TIP2019/peppers_degraded.tif -------------------------------------------------------------------------------- /fastABF-TIP2019/sigmaJPEG.m: -------------------------------------------------------------------------------- 1 | function [ sigma_r ] = sigmaJPEG( f,sigma_min,k0 ) 2 | %SIGMAJPEG 3 | % Compute pixelwise sigma values for deblocking JPEG image 4 | % Idea based on the following paper: 5 | % M. Zhang and B. K. Gunturk, "Compression artifact reduction with 6 | % adaptive bilateral filtering," Proc. SPIE Visual Communications and 7 | % Image Processing, vol. 7257, 2009. 8 | % 9 | % Input arguments: 10 | % f = Input image containing blocking artifatcs 11 | % sigma_min = Minimum value of sigma 12 | % k0 = Amplification factor (see above paper for details) 13 | % Output arguments: 14 | % sigma_r = Pixelwise range kernel parameters 15 | 16 | [M,N] = size(f); 17 | 18 | [bmask,vmask,hmask,cornermask,centermask] = edgeMask(M,N); 19 | [R,C] = find(bmask); 20 | 21 | % Find discontinuities at block boundaries 22 | bV = imfilter(f,[-1,0,1],'symmetric'); 23 | bH = imfilter(f,[-1,0,1]','symmetric'); 24 | 25 | V = nan(M,N); 26 | V(cornermask) = max(abs(bV(cornermask)),abs(bH(cornermask))); 27 | V(vmask) = abs(bV(vmask)); 28 | V(hmask) = abs(bH(hmask)); 29 | V(centermask) = 0; 30 | 31 | Vdata = V(bmask); 32 | F = scatteredInterpolant(R,C,Vdata); 33 | [RR,CC] = find(true(size(f))); 34 | BDmap = F(RR,CC); % Block discontinuity map 35 | BDmap = reshape(BDmap,size(f)); 36 | sigma_r = max(sigma_min,k0*BDmap); 37 | 38 | end 39 | 40 | function [ bmask,vmask,hmask,cornermask,centermask ] = edgeMask(M,N) 41 | Br = floor(M/8); 42 | Bc = floor(N/8); 43 | 44 | vtile = false(8); 45 | vtile(2:7,[1,8]) = true; 46 | 47 | htile = false(8); 48 | htile([1,8],2:7) = true; 49 | 50 | crtile = false(8); 51 | crtile(1,1) = true; 52 | crtile(1,8) = true; 53 | crtile(8,1) = true; 54 | crtile(8,8) = true; 55 | 56 | cntile = false(8); 57 | cntile(4:5,4:5) = true; 58 | 59 | btile = vtile | htile | crtile | cntile; 60 | 61 | vmask = repmat(vtile,Br+1,Bc+1); 62 | vmask = vmask(1:M,1:N); 63 | hmask = repmat(htile,Br+1,Bc+1); 64 | hmask = hmask(1:M,1:N); 65 | cornermask = repmat(crtile,Br+1,Bc+1); 66 | cornermask = cornermask(1:M,1:N); 67 | centermask = repmat(cntile,Br+1,Bc+1); 68 | centermask = centermask(1:M,1:N); 69 | bmask = repmat(btile,Br+1,Bc+1); 70 | bmask = bmask(1:M,1:N); 71 | 72 | end 73 | 74 | 75 | 76 | --------------------------------------------------------------------------------