├── 2021-CVPR-Rankone.pdf ├── README.md ├── TPAMI_Rankone Prior.pdf └── rankoneplus ├── demo_Rank1.m ├── demo_Rank1plus.m └── images ├── hazy1.png ├── sandstorm1.png └── underw1.jpg /2021-CVPR-Rankone.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junliumath/ROP/1b8e99a826e758eead7b89d7cf66db99d7163d92/2021-CVPR-Rankone.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ROP - Rank-One Prior: Real-time Scene Recovery 2 | Description 3 | ----- 4 | The Code is created based on the method described in the following papers: 5 | 6 | [1] "Rank-One Prior: Toward Real-Time Scene Recovery", Jun Liu, Ryan Wen Liu, Jianing Sun, Tieyong Zeng, IEEE International Conference on Computer Vision (CVPR), 2021, 14802-14810. 7 | https://openaccess.thecvf.com/content/CVPR2021/papers/Liu_Rank-One_Prior_Toward_Real-Time_Scene_Recovery_CVPR_2021_paper.pdf 8 | 9 | [2] "Rank-One Prior: Real-time Scene Recovery", Jun Liu, Ryan Wen Liu, Jianing Sun, Tieyong Zeng, IEEE Transaction on Pattern Analysis and Machine Intelligence, 2023, 45(7): 8845–8860. 10 | https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=9969127 11 | 12 | The code and the algorithm are for non-commercial use only. 13 | 14 | If you are inteseted in commercial purpose, please comply with the patent: ZL 202011281893.3 and contact the authors, thank you! 15 | 16 | 17 | Authors: 18 | 19 | Jianing Sun (sunjn118@nenu.edu.cn) 20 | 21 | Jun Liu (liuj292@nenu.edu.cn) 22 | 23 | Version : 1.1 24 | 25 | The collected dataset including Real Underwater, Sand dust, and Hazy images (RUSH) can be reached from BaiduNetDisk: 26 | 链接: 链接: https://pan.baidu.com/s/11FM4Cct9nyvpOwJYZZ9DJg?pwd=1126 提取码: 1126 27 | -------------------------------------------------------------------------------- /TPAMI_Rankone Prior.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junliumath/ROP/1b8e99a826e758eead7b89d7cf66db99d7163d92/TPAMI_Rankone Prior.pdf -------------------------------------------------------------------------------- /rankoneplus/demo_Rank1.m: -------------------------------------------------------------------------------- 1 | function demo_Rank1 2 | % Rank1 - Rank-One Prior: toward Real-Time Scene Recovery 3 | % DEMO of RANK1; Matlab 2018a and higher verision 4 | % @ ImageType is the type of the input image 5 | % @ 1: hazy image; 6 | % @ 2: sandstorm image; 7 | % @ 3: underwaterimage 8 | % 9 | % The Code is created based on the method described in the following paper 10 | % [1] "Rank-One Prior: Toward Real-Time Scene Recovery", Jun Liu, Ryan Wen Liu, Jianing Sun, Tieyong Zeng, IEEE International Conference on Computer Vision (CVPR), 2021, 14802-14810. 11 | % 12 | % Author: Jianing Sun (sunjn118@nenu.edu.cn), Jun Liu (liuj292@nenu.edu.cn) 13 | % Version : 1.0 14 | % 15 | % The code and the algorithm are for non-commercial use only. 16 | % 17 | % If you are inteseted in commercial purpose, please comply with the patent: ZL 202011281893.3 and contact the authors, thank you! 18 | 19 | omega = 0.8; 20 | 21 | dir = 'images'; 22 | imgname = 'hazy1.png'; % underw1.jpg hazy1.png sandstorm1.png 23 | img = im2double(imread([dir '/' imgname])); 24 | if gpuDeviceCount 25 | img = gpuArray(img); % use GPU to save much more time for an image of big size 26 | end 27 | 28 | 29 | tic 30 | [J,s_tildeT,tildeT] = rank1_enhancement(img,omega); 31 | toc 32 | 33 | 34 | figure('NumberTitle','off','name','Enhancement'); 35 | imshow( [ uint8(img*255), J ] ); 36 | title('degraded image vs enhanced image');truesize(); 37 | 38 | % save the results 39 | if gpuDeviceCount 40 | imwrite(gather(J),['results/' imgname(1:end-4) '-Rank1.png']); 41 | else 42 | imwrite( J,['results/' imgname(1:end-4) '-Rank1.png'],'png'); % recovered scene 43 | imwrite( s_tildeT,['results/' imgname(1:end-4) '-sT-Rank1.png'],'png'); % resampled T 44 | imwrite( tildeT,['results/' imgname(1:end-4) '-T-Rank1.png'],'png'); % T0 45 | end 46 | 47 | 48 | function [Jr_ini,s_tildeT,tildeT] = rank1_enhancement(img,omega) 49 | % for CVPR 2021 50 | % % % Optimize the scattering light 51 | 52 | imgvec = reshape(img, size(img,1)*size(img,2), 3); 53 | 54 | x_RGB(1 ,1, 1:3) = mean(imgvec,1); % unified spectrum 55 | % %%%%%% direction difference 56 | x_mean = repmat( x_RGB,[ size(img,1) size(img,2) 1 ] ); % unified spectrum in each pixel 57 | %%%%%%%%%%% 58 | scat_basis = x_mean ./max( sqrt(sum(x_mean.^2,3)), 0.001); % normalization 59 | fog_basis = img ./max( sqrt(sum(img.^2,3)), 0.001); % normalization 60 | cs_sim = repmat( (((sum( scat_basis .* fog_basis,3) ))),[1 1 3] ); % cos similarity 61 | % %%%%%% scattering_light_estimation 62 | scattering_light = (cs_sim) .* (sum(img,3)./max( sum(x_mean,3), 0.001)).*x_mean; 63 | 64 | intial_img = img; 65 | %%% get_atmosphere 66 | [ atmosphere, scattering_light ] = get_atmosphere( intial_img, scattering_light); 67 | %%% get_transmission_estimate 68 | T = 1 - omega * scattering_light ; % T = 1 - \tilde{t} 69 | T_ini = scattering_mask_sample( T ); 70 | 71 | %%% dehaze 72 | ShowR_d = ( intial_img - atmosphere ) ./max( T_ini ,0.001 ) + atmosphere; % Winv.* 73 | 74 | 75 | 76 | % % Postprocessing; module for luminance adjustment, 77 | % % For some thick-fog scenes, this operation is not recommended; 78 | mi = prctile2019(ShowR_d,1,[1 2]); 79 | ma = prctile2019(ShowR_d,99,[1 2]); 80 | Jr_ini = ( ShowR_d - mi)./(ma-mi); 81 | 82 | 83 | Jr_ini = gamma0( uint8( Jr_ini*255 ) ); 84 | 85 | tildeT = 1 - T; 86 | s_tildeT = 1 - T_ini; 87 | 88 | 89 | function [ atmosphere, scatterlight ] = get_atmosphere( image,scatterlight ) 90 | 91 | for i = 1:1 92 | scatter_est = sum(scatterlight,3); 93 | n_pixels = numel(scatter_est); 94 | n_search_pixels = floor( n_pixels * 0.001); 95 | image_vec = reshape(image, n_pixels, 3); 96 | [~, indices] = sort(scatter_est(:), 'descend'); 97 | atmosphere = mean( image_vec( indices(1:n_search_pixels), : ), 1); 98 | 99 | atmos(1,1,:) = atmosphere; 100 | atmosphere = repmat( atmos, [ size(scatter_est) 1 ] ); 101 | 102 | sek = scatter_est(indices(n_search_pixels)); 103 | 104 | scatterlight = scatterlight .* repmat( scatter_est <= sek, [ 1 1 3] ) + ... 105 | ( 2/3 * sek -scatterlight ) .* repmat( scatter_est > sek, [ 1 1 3] ); 106 | end 107 | end 108 | end 109 | 110 | 111 | %% 112 | 113 | function img = gamma0(img) 114 | i = 0 : 255; 115 | f = ((i + 0.5)./256 ).^(5/6); 116 | LUT(i+1) = uint8( f.*256 -0.5 ); 117 | 118 | %%%% rgb2hsv - hsv2rgb rgb2ycbcr-ycbcr2rgb 119 | img = rgb2ycbcr(img); 120 | img(:,:,1) = LUT( img(:,:,1) + 1 ); 121 | img = ycbcr2rgb(img); 122 | 123 | end 124 | 125 | 126 | function F = scattering_mask_sample(I) 127 | mSize = min(size(I,1),size(I,2)); 128 | if mSize < 800 129 | r = 0.02; 130 | elseif mSize >= 800 && mSize < 1500 131 | r = 0.01; 132 | else 133 | r = 0.005; 134 | end 135 | I0 = imresize(I,r); 136 | F = imresize(I0,[size(I,1),size(I,2)],'bicubic'); 137 | end 138 | 139 | 140 | function y = prctile2019(varargin) 141 | par = inputParser(); 142 | par.addRequired('x'); 143 | par.addRequired('p'); 144 | par.addOptional('dim',1,@(x) isnumeric(x) || validateDimAll(x)); 145 | par.addParameter('Delta',1e3); 146 | par.addParameter('RandStream',[]); 147 | 148 | par.parse(varargin{:}); 149 | 150 | x = par.Results.x; 151 | p = par.Results.p; 152 | dim = par.Results.dim; 153 | delta = par.Results.Delta; 154 | rs = par.Results.RandStream; 155 | 156 | 157 | % Figure out which dimension prctile will work along. 158 | sz = size(x); 159 | 160 | 161 | % Permute the array so that the requested dimension is the first dim. 162 | if ~isequal(dim,1) 163 | nDimsX = ndims(x); 164 | dim = sort(dim); 165 | perm = [dim setdiff(1:max(nDimsX,max(dim)),dim)]; 166 | x = permute(x, perm); 167 | end 168 | sz = size(x); 169 | dimArgGiven = true; 170 | 171 | 172 | 173 | % Drop X's leading singleton dims, and combine its trailing dims. This 174 | % leaves a matrix, and we can work along columns. 175 | work_dim = 1:numel(dim); 176 | 177 | work_dim = work_dim(work_dim <= numel(sz)); 178 | nrows = prod(sz(work_dim)); 179 | ncols = numel(x) ./ nrows; 180 | x = reshape(x, nrows, ncols); 181 | 182 | x = sort(x,1); 183 | n = sum(~isnan(x), 1); % Number of non-NaN values in each column 184 | 185 | % For columns with no valid data, set n=1 to get nan in the result 186 | n(n==0) = 1; 187 | 188 | % If the number of non-nans in each column is the same, do all cols at once. 189 | if all(n == n(1)) 190 | n = n(1); 191 | if isequal(p,50) % make the median fast 192 | if rem(n,2) % n is odd 193 | y = x((n+1)/2,:); 194 | else % n is even 195 | y = (x(n/2,:) + x(n/2+1,:))/2; 196 | end 197 | else 198 | y = interpColsSame(x,p,n); 199 | end 200 | 201 | else 202 | % Get percentiles of the non-NaN values in each column. 203 | y = interpColsDiffer(x,p,n); 204 | end 205 | 206 | 207 | % Reshape Y to conform to X's original shape and size. 208 | szout = sz; 209 | szout(work_dim) = 1; 210 | szout(work_dim(1)) = numel(p); 211 | y = reshape(y,szout); 212 | 213 | % undo the DIM permutation 214 | if dimArgGiven && ~isequal(dim,1) 215 | y = ipermute(y,perm); 216 | end 217 | 218 | 219 | 220 | function y = interpColsSame(x, p, n) 221 | 222 | if isrow(p) 223 | p = p'; 224 | end 225 | 226 | % Form the vector of index values (numel(p) x 1) 227 | r = (p/100)*n; 228 | k = floor(r+0.5); % K gives the index for the row just before r 229 | kp1 = k + 1; % K+1 gives the index for the row just after r 230 | r = r - k; % R is the ratio between the K and K+1 rows 231 | 232 | % Find indices that are out of the range 1 to n and cap them 233 | k(k<1 | isnan(k)) = 1; 234 | kp1 = bsxfun( @min, kp1, n ); 235 | 236 | % Use simple linear interpolation for the valid percentages 237 | y = (0.5+r).*x(kp1,:)+(0.5-r).*x(k,:); 238 | 239 | % Make sure that values we hit exactly are copied rather than interpolated 240 | exact = (r==-0.5); 241 | if any(exact) 242 | y(exact,:) = x(k(exact),:); 243 | end 244 | 245 | % Make sure that identical values are copied rather than interpolated 246 | same = (x(k,:)==x(kp1,:)); 247 | if any(same(:)) 248 | x = x(k,:); % expand x 249 | y(same) = x(same); 250 | end 251 | end 252 | 253 | function y = interpColsDiffer(x, p, n) 254 | %INTERPCOLSDIFFER A simple 1-D linear interpolation of columns that can 255 | %deal with columns with differing numbers of valid entries (vector n). 256 | 257 | [nrows, ncols] = size(x); 258 | 259 | % Make p a column vector. n is already a row vector with ncols columns. 260 | if isrow(p) 261 | p = p'; 262 | end 263 | 264 | % Form the grid of index values (numel(p) x numel(n)) 265 | r = (p/100)*n; 266 | k = floor(r+0.5); % K gives the index for the row just before r 267 | kp1 = k + 1; % K+1 gives the index for the row just after r 268 | r = r - k; % R is the ratio between the K and K+1 rows 269 | 270 | % Find indices that are out of the range 1 to n and cap them 271 | k(k<1 | isnan(k)) = 1; 272 | kp1 = bsxfun( @min, kp1, n ); 273 | 274 | % Convert K and Kp1 into linear indices 275 | offset = nrows*(0:ncols-1); 276 | k = bsxfun( @plus, k, offset ); 277 | kp1 = bsxfun( @plus, kp1, offset ); 278 | 279 | % Use simple linear interpolation for the valid percentages. 280 | % Note that NaNs in r produce NaN rows. 281 | y = (0.5-r).*x(k) + (0.5+r).*x(kp1); 282 | 283 | % Make sure that values we hit exactly are copied rather than interpolated 284 | exact = (r==-0.5); 285 | if any(exact(:)) 286 | y(exact) = x(k(exact)); 287 | end 288 | 289 | % Make sure that identical values are copied rather than interpolated 290 | same = (x(k)==x(kp1)); 291 | if any(same(:)) 292 | x = x(k); % expand x 293 | y(same) = x(same); 294 | end 295 | end 296 | 297 | function bool = validateDimAll(dim) 298 | bool = ((ischar(dim) && isrow(dim)) || ... 299 | (isstring(dim) && isscalar(dim) && (strlength(dim) > 0))) && ... 300 | strncmpi(dim,'all',max(strlength(dim), 1)); 301 | end 302 | end 303 | end 304 | -------------------------------------------------------------------------------- /rankoneplus/demo_Rank1plus.m: -------------------------------------------------------------------------------- 1 | function demo_Rank1plus 2 | % rank1plus - Rank-One Prior: Real-Time Scene Recovery 3 | % DEMO of RANK1+; Matlab 2019 is required. 4 | % @ ImageType is the type of the input image 5 | % @ 1: hazy image; 6 | % @ 2: sandstorm image; 7 | % @ 3: underwaterimage 8 | % 9 | % The Code is created based on the method described in the following paper 10 | % [1] "Rank-One Prior: Toward Real-Time Scene Recovery", Jun Liu, Ryan Wen Liu, Jianing Sun, Tieyong Zeng, IEEE International Conference on Computer Vision (CVPR), 2021, 14802-14810. 11 | % [2] "Rank-one prior: Real-time Scene Recovery", Jun Liu, Ryan Wen Liu, Jianing Sun, Tieyong Zeng, IEEE Transaction on Pattern Analysis and Machine Intelligence, accepted, 2022. 12 | % 13 | % The code and the algorithm are for non-commercial use only. 14 | % 15 | % If you are inteseted in commercial purpose, please comply with the patent: ZL 202011281893.3 and contact the authors, thank you! 16 | % 17 | 18 | % 19 | % Author: Jianing Sun (sunjn118@nenu.edu.cn) 20 | % Jun Liu (junliucd@nenu.edu.cn) 21 | % Version : 1.1 22 | 23 | %%%%================================================== 24 | 25 | close all 26 | ImageType = 3; 27 | param = defaultParamSetting(ImageType); 28 | 29 | dir = 'images'; 30 | imgname = 'hazy1.png'; % underw1.jpg hazy1.png sandstorm1.png 31 | img = im2double(imread([dir '/' imgname])); 32 | % img = imcrop(img); 33 | 34 | if gpuDeviceCount 35 | img = gpuArray(img); 36 | end 37 | 38 | 39 | %%% 40 | imgvec = reshape(img, size(img,1)*size(img,2), 3); % vectorization 41 | %%% Update the unified spectrum 42 | selectedpixel = ones( size(imgvec) ); 43 | previous_basis(1,1,1:3) = [1 1 1]; % initialization of spectrum basis 44 | for step = 1 : 20 45 | % unified spectrum 46 | x_RGB(1 ,1, 1:3) = mean(imgvec( selectedpixel,: ),1); 47 | % unified spectrum in each pixel 48 | x_mean = repmat( x_RGB,[ size(img,1) size(img,2) 1 ] ); 49 | % vectorial normalization, 50 | spec_basis = x_mean ./max( sqrt(sum(x_mean.^2,3)), 0.001); 51 | % normalization 52 | imag_nmlzed = img./max( sqrt(sum(img.^2,3)) , 0.001); % 53 | % direction difference 54 | % projection similarity 55 | % cos<\alpha, \beta> 56 | proj_sim = repmat( (((sum( spec_basis .* imag_nmlzed,3) ))),[1 1 3] ); 57 | % scattering_light_estimation 58 | if sum( abs(spec_basis(1,1,1:3) - previous_basis),3 ) ~= 0 59 | previous_basis = spec_basis(1,1,1:3); 60 | boots = reshape(proj_sim, size(img,1)*size(img,2), 3); 61 | selectedpixel = boots(:,1)>0.99; 62 | else 63 | break; 64 | end 65 | end 66 | 67 | % S_nu: unified_spectrum of \tilde{t} 68 | S_nu = x_mean./max(sum(x_mean,3), 0.001); 69 | % \tilde{t} is initialized. 70 | tilde_T = proj_sim .* sum(img,3).* S_nu; 71 | 72 | intial_img = img; 73 | % get_atmosphere 74 | [ atmosphere, tilde_T ] = get_atmosphere( intial_img, tilde_T); 75 | %%% T = 1 - omega * \tilde{t} 76 | T_ini = 1 - param.omega * tilde_T ; 77 | 78 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 79 | % Rank1+: Transmission Optimization 80 | % 81 | [Jr, T_tv ] = TransRefine( atmosphere, intial_img, T_ini, param ); 82 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 83 | % postprocessing; 84 | % For some thick-fog scenes, this operation is not recommended; 85 | mi = prctile(Jr,param.mi,[1 2]); 86 | ma = prctile(Jr,param.ma,[1 2]); 87 | Jr = ( Jr - mi)./(ma-mi); 88 | 89 | % % 90 | Jr = uint8( Jr*255 ); 91 | Jr = gamma0( Jr ); 92 | % 93 | 94 | 95 | % figure(); imshow([ uint8(img*255) Jr uint8((tilde_T)*255) uint8((1-T_tv)*255)]); 96 | % title('Rank1+ scenery recovery');truesize(); 97 | 98 | figure(); imshow([ uint8(img*255) Jr]); title('Left: Degraded image; Right: Recoverd image') 99 | 100 | 101 | % save the output 102 | imwrite(Jr, ['results/' imgname(1:end-4) '-rank1plus.png']) 103 | 104 | 105 | imwrite( 1-T_tv,['results/' imgname(1:end-4) '-sT-rank1plus.png'],'png'); % Refined tilde_T 106 | imwrite( 1-T_ini,['results/' imgname(1:end-4) '-T-rank1plus.png'],'png'); % initial tilde_T 107 | 108 | 109 | 110 | % tt = imgvec; 111 | % tt(boots(:, 1)<=0.99,:)= 0; 112 | % imgselect = reshape(tt, size(img,1),size(img,2), 3); 113 | % % pause 114 | % figure(21), imshow([img,imgselect]),title(['step=' num2str(step)]) 115 | % imwrite(imgselect, ['results/' imgname(1:end-4) '-selectedregion' num2str(step) '.png']) 116 | 117 | end 118 | 119 | 120 | function img = gamma0(img) 121 | i = 0 : 255; 122 | f = ((i + 0.5)./256 ).^(5/6); 123 | LUT(i+1) = uint8( f.*256 -0.5 ); 124 | 125 | %%%% rgb2hsv - hsv2rgb rgb2ycbcr-ycbcr2rgb 126 | img = rgb2ycbcr(img); 127 | img(:,:,1) = LUT( img(:,:,1) + 1 ); 128 | img = ycbcr2rgb(img); 129 | end 130 | 131 | function [ atmosphere, tilde_T ] = get_atmosphere( image, tilde_T ) 132 | scatter_est = sum(tilde_T,3); 133 | n_pixels = numel(scatter_est); 134 | n_search_pixels = floor( n_pixels * 0.01); 135 | 136 | image_vec = reshape(image, n_pixels, 3); 137 | [~, indices] = sort(scatter_est(:), 'descend'); 138 | atmosphere = mean( image_vec( indices(1:n_search_pixels), : ), 1); 139 | 140 | atmos(1,1,:) = atmosphere; 141 | atmosphere = repmat( atmos, [ size(scatter_est) 1 ] ); 142 | 143 | %%% To prevent over-brightness 144 | sek = scatter_est(indices(n_search_pixels)); 145 | sek_vec = repmat( sek .* tilde_T(1,1,:)./max(scatter_est(1,1),0.001), [ size(scatter_est) 1 ]); 146 | tilde_T = tilde_T .* repmat( scatter_est <= sek, [ 1 1 3] ) + ... 147 | ( 2 * sek_vec -tilde_T ) .* repmat( scatter_est > sek, [ 1 1 3] ); 148 | end 149 | 150 | 151 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 152 | %%%% To refine transmission map of t 153 | function [ Jr, T ] = TransRefine( atmosphere, I, t0, param) 154 | % - Note that this code is a little bit different from that presented in our 155 | % paper; 156 | % - C0 is the intensity of the transmission map T 157 | % - SnuT is the unified spectrum of the transimssion map T 158 | % - SnuT = T(1,1,:)/sum(T(1,1,:),3) 159 | % Initializing 160 | Coeff = getCoeff; 161 | [D,Dt] = defDDt; 162 | MaxIter = param.iternum; 163 | gamma = param.gamma; 164 | %%%%% 165 | lambda1 = 5; %% lambda1 50 for 0016_0.8_0.08.jpg 0001_0.8_0.2.jpg default:5; 166 | lambda2 = 5e-1; %% lambda2 default 5e-1; 5 for purplehaze 2,3 167 | lambda3 = 5e-1; %% lambda3 这个对结果有影响 兰州亭子,用 lambda3 = 5e-1, 198.png 168 | % lambda3 default 5 169 | beta = 10; %% beta1 & beta2 default 10 170 | %%%%% Lagrange Multipliers 171 | [ m,n,ch ] = size(t0); 172 | Lxi1 = zeros(m,n,ch); Lxi2 = Lxi1; 173 | Leta1 = zeros(m,n); Leta2 = Leta1; 174 | %%%%%% 175 | SolRE = 5e-4; 176 | tao = 1.618; 177 | 178 | % diff 179 | [D1I,D2I] = D(I); 180 | C0 = mean(t0,3 ); 181 | 182 | % SnuT: unified spectrum of transmission map T 183 | SnuT = t0(1,1,:)/sum(t0(1,1,:),3); 184 | 185 | 186 | 187 | [D1tG,D2tG] = D(C0); 188 | D1t = SnuT.* repmat( D1tG,[1 1 3] ); 189 | D2t = SnuT.* repmat( D2tG,[1 1 3] ); 190 | 191 | C = C0; 192 | 193 | cont = 1; 194 | k = 0; 195 | while cont 196 | k = k + 1; 197 | 198 | % X-subproblem 199 | Xterm1 = D1t - D1I + Lxi1./beta; 200 | Xterm2 = D2t - D2I + Lxi2./beta; 201 | Xterm = sqrt(Xterm1.^2 + Xterm2.^2); 202 | W = exp(-gamma * (abs(D1I) + abs(D2I))); 203 | Xterm = max(Xterm - (W .* lambda1)/beta, 0) ./ (Xterm + eps); 204 | Xmg1 = Xterm1 .* Xterm; 205 | Xmg2 = Xterm2 .* Xterm; 206 | 207 | % Z-subproblem 208 | Zterm1 = D1tG + Leta1./beta; 209 | Zterm2 = D2tG + Leta2./beta; 210 | Zterm = sqrt(Zterm1.^2 + Zterm2.^2); 211 | %Zterm(Zterm == 0) = 1; 212 | Zterm = max(Zterm - lambda2/beta, 0) ./ (Zterm + eps); 213 | Zmg1 = Zterm1 .* Zterm; 214 | Zmg2 = Zterm2 .* Zterm; 215 | % 216 | 217 | % C-subproblem 218 | zeta1X = Xmg1 + D1I - Lxi1./beta; 219 | zeta1Y = Xmg2 + D2I- Lxi2./beta; 220 | zeta2X = Zmg1 - Leta1./beta; 221 | zeta2Y = Zmg2 - Leta2./beta; 222 | %%%%% 223 | ttem = fft2( lambda3*C0 ) + ... 224 | beta* sum(fft2(Dt(SnuT.*zeta1X, SnuT.*zeta1Y)),3) +... 225 | beta*fft2(Dt(zeta2X, zeta2Y)); 226 | ttemp = lambda3 + beta * ( sum(SnuT.^2 .* Coeff.eigsDtD,3) + Coeff.eigsDtD2 ); 227 | Cnew = real(ifft2(ttem./(ttemp + eps))); 228 | Cnew(Cnew <= 0) = 0; 229 | Cnew(Cnew >= 1) = 1; 230 | 231 | [D1tG,D2tG] = D(Cnew); 232 | D1t = SnuT.* repmat( D1tG,[1 1 3] ); 233 | D2t = SnuT.* repmat( D2tG,[1 1 3] ); 234 | 235 | % Updating Lagrange multipliers 236 | Lxi1 = Lxi1 - tao * beta * ( Xmg1 - (D1t - D1I) ); 237 | Lxi2 = Lxi2 - tao * beta * ( Xmg2 - (D2t - D2I) ); 238 | Leta1 = Leta1 - tao * beta * ( Zmg1 - D1tG ); 239 | Leta2 = Leta2 - tao * beta * ( Zmg2 - D2tG ); 240 | 241 | % 242 | re = norm(Cnew(:) - C(:),'fro') / norm(C(:),'fro'); 243 | C = Cnew; 244 | cont = (k < MaxIter) && (re > SolRE); 245 | % 246 | end 247 | 248 | figure,imshow(C,[]),title('intensity C'), pause(0.01) 249 | T = SnuT.*repmat(C, [1 1 3]); 250 | Jr = ( I - atmosphere )./max(T,0.01) + atmosphere; 251 | 252 | 253 | 254 | 255 | 256 | % % Nested function 257 | function Coeff = getCoeff 258 | sizeF = size(t0); 259 | % psf2otf: computes the Fast Fourier Transform (FFT) of the point-spread function (PSF) 260 | Coeff.eigsD1 = psf2otf([1,-1], sizeF); 261 | Coeff.eigsD2 = psf2otf([1;-1], sizeF); 262 | Coeff.eigsDtD = abs(Coeff.eigsD1).^2 + abs(Coeff.eigsD2).^2; 263 | 264 | Coeff.eigsD21 = psf2otf([1,-1], [sizeF(1) sizeF(2)]); 265 | Coeff.eigsD22 = psf2otf([1;-1], [sizeF(1) sizeF(2)]); 266 | Coeff.eigsDtD2 = abs(Coeff.eigsD21).^2 + abs(Coeff.eigsD22).^2; 267 | end 268 | function [D,Dt] = defDDt 269 | % defines finite difference operator D 270 | % and its transpose operator 271 | % referring to FTVD code 272 | D = @(U) ForwardD(U); 273 | Dt = @(X,Y) Dive(X,Y); 274 | end 275 | function [Dux,Duy] = ForwardD(U) %diff 276 | %%% Forward finite difference operator 277 | Dux = [diff(U,1,2), U(:,1,:) - U(:,end,:)]; 278 | Duy = [diff(U,1,1); U(1,:,:) - U(end,:,:)]; 279 | end 280 | function DtXY = Dive(X,Y) %Dt=-div 281 | % Transpose of the forward finite difference operator 282 | DtXY = [X(:,end,:) - X(:, 1,:), -diff(X,1,2)]; 283 | DtXY = DtXY + [Y(end,:,:) - Y(1, :,:); -diff(Y,1,1)]; 284 | end 285 | end 286 | 287 | function param = defaultParamSetting(ImageType) 288 | % Set the necessary parameters 289 | % Note that the default paramameters do not mean the best parameter 290 | % setting. If you are not satisfied with the recovered result, try to ajust the 291 | % parameters accordingly. 292 | if ImageType == 1 293 | param.omega = 0.99; 294 | param.mi = 1; 295 | param.ma = 95; 296 | param.gamma = 5e1; 297 | elseif ImageType == 2 298 | %%%% Although the sandstorm image looks dim, 299 | %%%% it is bright enough. 300 | %%%% The consistency of the spectrum is good 301 | param.omega = 0.8; 302 | param.mi = 1; 303 | param.ma = 95; 304 | param.gamma = 3e1; 305 | elseif ImageType == 3 306 | %%%% The underwater image is very dark, 307 | %%%% but the consistency of the spectrum is good. 308 | param.omega = 0.75; 309 | param.mi = 1; 310 | param.ma = 95; 311 | param.gamma = 5e1; 312 | elseif ImageType == 4 313 | param.omega = 0.7; 314 | param.mi = 2; 315 | param.ma = 99.6; 316 | param.gamma = 1e2; 317 | end 318 | param.iternum = 10; 319 | end 320 | -------------------------------------------------------------------------------- /rankoneplus/images/hazy1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junliumath/ROP/1b8e99a826e758eead7b89d7cf66db99d7163d92/rankoneplus/images/hazy1.png -------------------------------------------------------------------------------- /rankoneplus/images/sandstorm1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junliumath/ROP/1b8e99a826e758eead7b89d7cf66db99d7163d92/rankoneplus/images/sandstorm1.png -------------------------------------------------------------------------------- /rankoneplus/images/underw1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junliumath/ROP/1b8e99a826e758eead7b89d7cf66db99d7163d92/rankoneplus/images/underw1.jpg --------------------------------------------------------------------------------