├── .gitignore ├── README.md ├── boxplot.jpg ├── demo.m ├── example.jpg ├── experiments.m ├── lowlight ├── BIMEF.m ├── BIMEF.p ├── LIME │ └── LIME.p ├── MF │ ├── demo.m │ └── multi_fusion.p ├── NPE │ ├── BLT.p │ ├── BiFltL.p │ ├── NPEA.p │ ├── Post.p │ ├── cbright.p │ ├── getextpic.p │ └── getlocalmax.p ├── README.md ├── SRIE │ └── processing.p ├── colorBalance.m ├── dong.m ├── lime.m ├── mf.m ├── multiscaleRetinex.m ├── npe.m └── srie.m ├── quality ├── VIF │ ├── ind2wtree.m │ ├── readme.txt │ ├── refparams_vecgsm.m │ ├── vifsub_est_M.m │ └── vifvec.m ├── loe100x100.m └── vif.m ├── startup.m └── util ├── Cd.m ├── Require.m ├── TestImage.m ├── TestReport.m ├── callerFile.m ├── colorspace.m ├── eachfile.m ├── ezFig.m ├── ezPath.m ├── globalVar.m ├── imload.m ├── install.m ├── loaddefault.m └── rename.m /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.zip 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BIMEF 2 | 3 | ![](https://img.shields.io/badge/MATLAB-R2016b-green.svg) 4 | 5 | ![](https://img.shields.io/badge/OS-Win10-green.svg) 6 | 7 | Code for our paper "A Bio-Inspired Multi-Exposure Fusion Framework for Low-light Image Enhancement" 8 | 9 | * The code for the comparison method is also provided, see [lowlight](https://github.com/baidut/BIMEF/tree/master/lowlight) 10 | * Downloads: [google Drive](https://drive.google.com/drive/folders/0B_FjaR958nw_djVQanJqeEhUM1k?usp=sharing) (Just unzip data to current folder) 11 | * Datasets `VV, LIME, NPE, NPE-ex1, NPE-ex2, NPE-ex3, DICM, MEF` 12 | * Since some methods are quite time-consuming, we also provide their results (e.g. `results__dong@VV.zip`) 13 | * Since some metrics are quite time-consuming, we also provide their results (`TestReport.zip`) 14 | * All the experiments can be reproduced easily by running `experiments.m` 15 | 16 | ![tcyb2017_moreExamples](example.jpg) 17 | 18 | From left to right: input images, results of MSRCR, Dong, NPE, LIME, MF, SRIE, and BIMEF(ours). 19 | 20 | ## Datasets 21 | 22 | - [VV](https://sites.google.com/site/vonikakis/datasets) (**Busting image enhancement and tone-mapping algorithms: **A collection of the most challenging cases) 23 | - [LIME-data](http://cs.tju.edu.cn/orgs/vision/~xguo/LIME.htm) 24 | - [NPE-data, NPE-ex1, NPE-ex2, NPE-ex3](http://blog.sina.com.cn/s/blog_a0a06f190101cvon.html) 25 | - DICM —— 69 captured images from commercial digital cameras: [Download (15.3 MB)](http://mcl.korea.ac.kr/projects/LDR/LDR_TEST_IMAGES_DICM.zip) 26 | - [MEF](https://ece.uwaterloo.ca/~k29ma/) [dataset](http://ivc.uwaterloo.ca/database/MEF/MEF-Database.php) 27 | 28 | ## Prerequisites 29 | 30 | * Original code is tested on *Matlab 2016b* 64bit, Windows 10. 31 | * [matlabPyrTools](https://github.com/gregfreeman/matlabPyrTools) is required to run VIF metric (`vif.m`). 32 | 33 | ## Setup 34 | 35 | Run `startup.m` to add required path, then you are able to try the following demo. 36 | 37 | ```matlab 38 | I = imread('yellowlily.jpg'); 39 | J = BIMEF(I); 40 | subplot 121; imshow(I); title('Original Image'); 41 | subplot 122; imshow(J); title('Enhanced Result'); 42 | ``` 43 | 44 | Replace `BIMEF` with other methods you want to test. 45 | 46 | ## Directory Structure 47 | 48 | ``` 49 | . 50 | ├── data # put your datasets here 51 | │ ├── MEF # dataset name (VV, LIME, NPE...) 52 | │ ├── out 53 | │ │ ├── loe100x100 # LOE visualization results 54 | │ │ ├── TestReport.csv # results of metrics 55 | │ │ ├── TestReport__xxxx.csv # backups of TestReport 56 | │ │ └── xxx__method.PNG # output images 57 | │ └── xxx.jpg # input images 58 | │ 59 | ├── lowlight # lowlight image enhancement methods 60 | ├── quality # image quality metrics (blind or full-reference) 61 | ├── util # provide commonly used utility functions 62 | │ 63 | ├── demo.m # simple demo of lowlight enhancement 64 | ├── experiments.m # reproduce our experiments 65 | └── startup.m # for installation 66 | ``` 67 | 68 | ## Usage 69 | 70 | Run experiments. 71 | 72 | ```matlab 73 | % specify datasets 74 | dataset = {'VV' 'LIME' 'NPE' 'NPE-ex1' 'NPE-ex2' 'NPE-ex3' 'MEF' 'DICM'}; 75 | dataset = strcat('data', filesep, dataset, filesep, '*.*'); 76 | 77 | % specify methods and metrics 78 | method = {@multiscaleRetinex @dong @npe @lime @mf @srie @BIMEF}; 79 | metric = {@loe100x100 @vif}; 80 | 81 | for d = dataset, data = d{1}; 82 | data, 83 | Test = TestImage(data); 84 | Test.Method = method; 85 | Test.Metric = metric; 86 | 87 | % run test and display results 88 | Test, 89 | 90 | % save test to a .csv file 91 | save(Test); 92 | end 93 | ``` 94 | 95 | Show test reports. 96 | 97 | ```matlab 98 | % table 99 | TestReport('TestReport__VV.csv'), 100 | 101 | % boxplot 102 | TestReport('TestReport__MEF.csv').boxplot; 103 | ``` 104 | 105 | Our method (BIMEF) has the lowest LOE and the highest VIF. 106 | 107 | ![boxplot](boxplot.jpg) -------------------------------------------------------------------------------- /boxplot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baidut/BIMEF/509f0411a57111859e1f767b4d91b33631fb2e7a/boxplot.jpg -------------------------------------------------------------------------------- /demo.m: -------------------------------------------------------------------------------- 1 | startup 2 | 3 | I = imread('yellowlily.jpg'); 4 | J = BIMEF(I); 5 | subplot 121; imshow(I); title('Original Image'); 6 | subplot 122; imshow(J); title('Enhanced Result'); -------------------------------------------------------------------------------- /example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baidut/BIMEF/509f0411a57111859e1f767b4d91b33631fb2e7a/example.jpg -------------------------------------------------------------------------------- /experiments.m: -------------------------------------------------------------------------------- 1 | startup 2 | 3 | % specify your paths to the datasets 4 | name = {'VV' 'LIME' 'NPE' 'NPE-ex1' 'NPE-ex2' 'NPE-ex3' 'MEF' 'DICM'}; 5 | dataset = strcat('data', filesep, name, filesep, '*.*'); 6 | 7 | % specify methods and metrics 8 | method = {@multiscaleRetinex @dong @npe @lime @mf @srie @BIMEF}; 9 | metric = {@loe100x100}; 10 | % metric = {@loe100x100 @vif}; % NOTE matlabPyrTools is required to run VIF metric (vif.m). 11 | 12 | for n = 1:numel(dataset); data = dataset{n}; 13 | data, 14 | Test = TestImage(data); 15 | Test.Method = method; 16 | Test.Metric = metric; 17 | 18 | % run test and display results 19 | Test, 20 | 21 | % save test to a .csv file 22 | save(Test); % %save(Test, ['TestReport__' name{n} '.csv']); 23 | end -------------------------------------------------------------------------------- /lowlight/BIMEF.m: -------------------------------------------------------------------------------- 1 | function fused = BIMEF(I, mu, k, a, b) 2 | %% 3 | % @article{ying2017bio, 4 | % title={A Bio-Inspired Multi-Exposure Fusion Framework for Low-light Image Enhancement}, 5 | % author={Ying, Zhenqiang and Li, Ge and Gao, Wen}, 6 | % journal={arXiv preprint arXiv:1711.00591}, 7 | % year={2017} 8 | % } 9 | % % @inproceedings{ying2017new, 10 | % % title={A New Image Contrast Enhancement Algorithm Using Exposure Fusion Framework}, 11 | % author={Ying, Zhenqiang and Li, Ge and Ren, Yurui and Wang, Ronggang and Wang, Wenmin}, 12 | % booktitle={International Conference on Computer Analysis of Images and Patterns}, 13 | % pages={36--46}, 14 | % year={2017}, 15 | % organization={Springer} 16 | % } 17 | %USAGE 18 | % I = imread('yellowlily.jpg'); 19 | % J = BIMEF(I); 20 | % subplot 121; imshow(I); title('Original Image'); 21 | % subplot 122; imshow(J); title('Enhanced Result'); 22 | % 23 | %INPUTS 24 | % I: image data (of an RGB or grayscale image) 25 | % mu: enhancement ratio 26 | % k: exposure ratio 27 | % a, b: camera response model params 28 | % 29 | %OUTPUTS 30 | % fused: enhanced result 31 | % 32 | % Please feel free to contact me (yingzhenqiang-at-gmail-dot-com) if you 33 | % have any questions or concerns. 34 | 35 | if ~exist( 'mu', 'var' ) 36 | mu = 0.5; 37 | end 38 | 39 | if ~exist( 'a', 'var' ) 40 | a = -0.3293; 41 | end 42 | 43 | if ~exist( 'b', 'var' ) 44 | b = 1.1258; 45 | end 46 | 47 | if ~isfloat(I) 48 | I = im2double( I ); 49 | end 50 | 51 | lambda = 0.5; 52 | sigma = 5; 53 | 54 | %% t: scene illumination map 55 | t_b = max( I, [], 3 ); % also work for single-channel image 56 | t_our = imresize( tsmooth( imresize( t_b, 0.5 ), lambda, sigma ), size( t_b ) ); 57 | 58 | %% k: exposure ratio 59 | if ~exist( 'k', 'var' ) || isempty(k) 60 | isBad = t_our < 0.5; 61 | J = maxEntropyEnhance(I, isBad); 62 | else 63 | J = applyK(I, k, a, b); %k 64 | J = min(J, 1); % fix overflow 65 | end 66 | 67 | %% W: Weight Matrix 68 | t = repmat(t_our, [1 1 size(I,3)]); 69 | W = t.^mu; 70 | 71 | I2 = I.*W; 72 | J2 = J.*(1-W); 73 | 74 | fused = I2 + J2; 75 | 76 | function J = maxEntropyEnhance(I, isBad) 77 | Y = rgb2gm(real(max(imresize(I, [50 50]), 0))); % max - avoid complex number 78 | 79 | if exist('isBad', 'var') 80 | isBad = (imresize(isBad, [50 50])); 81 | Y = Y(isBad); 82 | end 83 | 84 | if isempty(Y) 85 | J = I; % no enhancement k = 1 86 | return; 87 | end 88 | 89 | opt_k = fminbnd(@(k) ( -entropy(applyK(Y, k)) ),1, 7); 90 | J = applyK(I, opt_k, a, b) - 0.01; 91 | 92 | end 93 | end 94 | 95 | function I = rgb2gm(I) 96 | if size(I,3) == 3 97 | I = im2double(max(0,I)); % negative double --> complex double 98 | I = ( I(:,:,1).*I(:,:,2).*I(:,:,3) ).^(1/3); 99 | end 100 | end 101 | 102 | function J = applyK(I, k, a, b) 103 | 104 | if ~exist( 'a', 'var' ) 105 | a = -0.3293; 106 | end 107 | 108 | if ~exist( 'b', 'var' ) 109 | b = 1.1258; 110 | end 111 | 112 | f = @(x)exp((1-x.^a)*b); 113 | beta = f(k); 114 | gamma = k.^a; 115 | J = I.^gamma.*beta; 116 | end 117 | 118 | function S = tsmooth( I, lambda, sigma, sharpness) 119 | if ( ~exist( 'lambda', 'var' ) ) 120 | lambda = 0.01; 121 | end 122 | if ( ~exist( 'sigma', 'var' ) ) 123 | sigma = 3.0; 124 | end 125 | if ( ~exist( 'sharpness', 'var' ) ) 126 | sharpness = 0.001; 127 | end 128 | I = im2double( I ); 129 | x = I; 130 | [ wx, wy ] = computeTextureWeights( x, sigma, sharpness); 131 | S = solveLinearEquation( I, wx, wy, lambda ); 132 | end 133 | 134 | function [ W_h, W_v ] = computeTextureWeights( fin, sigma, sharpness) 135 | 136 | dt0_v = [diff(fin,1,1);fin(1,:)-fin(end,:)]; 137 | dt0_h = [diff(fin,1,2)';fin(:,1)'-fin(:,end)']'; 138 | 139 | gauker_h = filter2(ones(1,sigma),dt0_h); 140 | gauker_v = filter2(ones(sigma,1),dt0_v); 141 | W_h = 1./(abs(gauker_h).*abs(dt0_h)+sharpness); 142 | W_v = 1./(abs(gauker_v).*abs(dt0_v)+sharpness); 143 | 144 | end 145 | 146 | function OUT = solveLinearEquation( IN, wx, wy, lambda ) 147 | [ r, c, ch ] = size( IN ); 148 | k = r * c; 149 | dx = -lambda * wx( : ); 150 | dy = -lambda * wy( : ); 151 | tempx = [wx(:,end),wx(:,1:end-1)]; 152 | tempy = [wy(end,:);wy(1:end-1,:)]; 153 | dxa = -lambda *tempx(:); 154 | dya = -lambda *tempy(:); 155 | tempx = [wx(:,end),zeros(r,c-1)]; 156 | tempy = [wy(end,:);zeros(r-1,c)]; 157 | dxd1 = -lambda * tempx(:); 158 | dyd1 = -lambda * tempy(:); 159 | wx(:,end) = 0; 160 | wy(end,:) = 0; 161 | dxd2 = -lambda * wx(:); 162 | dyd2 = -lambda * wy(:); 163 | 164 | Ax = spdiags( [dxd1,dxd2], [-k+r,-r], k, k ); 165 | Ay = spdiags( [dyd1,dyd2], [-r+1,-1], k, k ); 166 | 167 | D = 1 - ( dx + dy + dxa + dya); 168 | A = (Ax+Ay) + (Ax+Ay)' + spdiags( D, 0, k, k ); 169 | 170 | if exist( 'ichol', 'builtin' ) 171 | L = ichol( A, struct( 'michol', 'on' ) ); 172 | OUT = IN; 173 | for ii = 1:ch 174 | tin = IN( :, :, ii ); 175 | [ tout, ~ ] = pcg( A, tin( : ), 0.1, 50, L, L' ); 176 | OUT( :, :, ii ) = reshape( tout, r, c ); 177 | end 178 | else 179 | OUT = IN; 180 | for ii = 1:ch 181 | tin = IN( :, :, ii ); 182 | tout = A\tin( : ); 183 | OUT( :, :, ii ) = reshape( tout, r, c ); 184 | end 185 | end 186 | end 187 | 188 | -------------------------------------------------------------------------------- /lowlight/BIMEF.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baidut/BIMEF/509f0411a57111859e1f767b4d91b33631fb2e7a/lowlight/BIMEF.p -------------------------------------------------------------------------------- /lowlight/LIME/LIME.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baidut/BIMEF/509f0411a57111859e1f767b4d91b33631fb2e7a/lowlight/LIME/LIME.p -------------------------------------------------------------------------------- /lowlight/MF/demo.m: -------------------------------------------------------------------------------- 1 | clc; 2 | clear all; 3 | 4 | 5 | input = imread('.\test images\9.jpg'); 6 | 7 | output = multi_fusion(input); 8 | 9 | figure,imshow(input),title('original image'); 10 | figure,imshow(output),title('enhanced image'); -------------------------------------------------------------------------------- /lowlight/MF/multi_fusion.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baidut/BIMEF/509f0411a57111859e1f767b4d91b33631fb2e7a/lowlight/MF/multi_fusion.p -------------------------------------------------------------------------------- /lowlight/NPE/BLT.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baidut/BIMEF/509f0411a57111859e1f767b4d91b33631fb2e7a/lowlight/NPE/BLT.p -------------------------------------------------------------------------------- /lowlight/NPE/BiFltL.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baidut/BIMEF/509f0411a57111859e1f767b4d91b33631fb2e7a/lowlight/NPE/BiFltL.p -------------------------------------------------------------------------------- /lowlight/NPE/NPEA.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baidut/BIMEF/509f0411a57111859e1f767b4d91b33631fb2e7a/lowlight/NPE/NPEA.p -------------------------------------------------------------------------------- /lowlight/NPE/Post.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baidut/BIMEF/509f0411a57111859e1f767b4d91b33631fb2e7a/lowlight/NPE/Post.p -------------------------------------------------------------------------------- /lowlight/NPE/cbright.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baidut/BIMEF/509f0411a57111859e1f767b4d91b33631fb2e7a/lowlight/NPE/cbright.p -------------------------------------------------------------------------------- /lowlight/NPE/getextpic.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baidut/BIMEF/509f0411a57111859e1f767b4d91b33631fb2e7a/lowlight/NPE/getextpic.p -------------------------------------------------------------------------------- /lowlight/NPE/getlocalmax.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baidut/BIMEF/509f0411a57111859e1f767b4d91b33631fb2e7a/lowlight/NPE/getlocalmax.p -------------------------------------------------------------------------------- /lowlight/README.md: -------------------------------------------------------------------------------- 1 | Lowlight enhancement algorithms, including 2 | 3 | * LIME 4 | * Dong 5 | * MF 6 | * MSRCR `MultiscaleRetinex.m` 7 | * NPE 8 | * SRIE 9 | 10 | ``` 11 | I = imread('yellowlily.jpg'); % a color image 12 | J = lime(I); % or other method 13 | subplot 121; imshow(I); title('Original Image'); 14 | subplot 122; imshow(J); title('Enhanced Result'); 15 | ``` 16 | 17 | Please contact me if you want the source code of our method (BIMEF) . 18 | 19 | Email: yingzhenqiang(at)gmail(dot)com -------------------------------------------------------------------------------- /lowlight/SRIE/processing.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baidut/BIMEF/509f0411a57111859e1f767b4d91b33631fb2e7a/lowlight/SRIE/processing.p -------------------------------------------------------------------------------- /lowlight/colorBalance.m: -------------------------------------------------------------------------------- 1 | function [OUT] = colorBalance(I, algorithm, varargin) 2 | % whitebalance 3 | 4 | if nargin == 0 5 | I = imload; %('toysnoflash.png'); 6 | tic, J = colorBalance(I, 'grayworld'); toc; 7 | tic, J2 = colorBalance(I, 'simplest'); toc; 8 | 9 | %25 100 240 10 | ezFig I J J2 11 | return; 12 | end 13 | 14 | [m,n,k]=size(I); 15 | if ~isfloat(I), I = im2double(I); end 16 | 17 | switch (algorithm) 18 | case {'gain_offset'} 19 | 20 | 21 | case {'grayworld'} 22 | Rmean = sum(sum(I(:,:,1)))/(m*n); 23 | Gmean = sum(sum(I(:,:,2)))/(m*n); 24 | Bmean = sum(sum(I(:,:,3)))/(m*n); 25 | Avg = mean([Rmean Gmean Bmean]); 26 | Kr = Avg/Rmean; 27 | Kg = Avg/Gmean; 28 | Kb = Avg/Bmean; 29 | OUT(:,:,1) = Kr*double(I(:,:,1)); 30 | OUT(:,:,2) = Kg*double(I(:,:,2)); 31 | OUT(:,:,3) = Kb*double(I(:,:,3)); 32 | 33 | case {'grayworld_spedup'} 34 | % forces the average image color to be gray 35 | % REF: 36 | % http://www.mathworks.com/matlabcentral/fileexchange/41089-color-balance-demo-with-gpu-computing/content/GPUDemoCode/whitebalance.m 37 | % 38 | % Find the average values for each channel 39 | pageSize = size(I,1) * size(I,2); 40 | avg_rgb = mean( reshape(I, [pageSize,3]) ); 41 | 42 | % Find the average gray value and compute the scaling array 43 | avg_all = mean(avg_rgb); 44 | scaleArray = max(avg_all, 0.5)./avg_rgb; 45 | scaleArray = reshape(scaleArray,1,1,3); 46 | 47 | % Adjust the image to the new gray value 48 | OUT = bsxfun(@times,I,scaleArray); 49 | 50 | case {'grayworld_gpu'} 51 | pageSize = size(I,1) * size(I,2); 52 | avg_rgb = mean( reshape(I, [pageSize,3]) ); 53 | 54 | % Find the average gray value and compute the scaling array 55 | avg_all = mean(avg_rgb); 56 | scaleArray = max(avg_all, 0.5)./avg_rgb; 57 | scaleArray = reshape(scaleArray,1,1,3); 58 | 59 | % Adjust the image to the new gray value 60 | I = gpuArray(I); 61 | OUT = bsxfun(@times,I,scaleArray); 62 | 63 | case {'grayworld_cuda'} 64 | % Find the average values for each channel 65 | pageSize = size(imageData,1) * size(imageData,2); 66 | avg_rgb = mean( reshape(imageData, [pageSize,3]) ); 67 | 68 | % Find the average gray value and compute the scaling factor 69 | avg_all = mean(avg_rgb); 70 | factor = max(avg_all, 0.5)./avg_rgb; 71 | factor = reshape(factor,1,1,3); 72 | 73 | % Load the kernel and set up threads 74 | kernel = parallel.gpu.CUDAKernel('whitebalanceKernel.ptxw64','whitebalanceKernel.cu' ); 75 | [nRows, nCols,~] = size(imageData); 76 | blockSize = 256; 77 | kernel.ThreadBlockSize = [blockSize, 1, 3]; 78 | kernel.GridSize = [ceil(nRows/blockSize), nCols]; 79 | 80 | % Copy image data to the GPU and allocate and initialize return data 81 | imageDataGPU = gpuArray(imageData); 82 | OUT = gpuArray.zeros( size(imageData), 'uint8'); 83 | 84 | % Adjust the image to the new gray value 85 | OUT = feval( kernel, OUT, imageDataGPU, factor, nRows, nCols ); 86 | 87 | case 'gaussian' 88 | if ~isempty(varargin) 89 | b = varargin{1}; 90 | else 91 | b = 2.3; 92 | end 93 | OUT = zeros(size(I)); 94 | for c = 1:k 95 | channel_mean=mean2(I(:,:,c)); 96 | channel_var=std2(I(:,:,c)); 97 | channel_max=channel_mean+b*channel_var; 98 | channel_min=channel_mean-b*channel_var; 99 | OUT(:,:,c)=(I(:,:,c)-channel_min)./(channel_max-channel_min); 100 | end 101 | case 'simplest', OUT = simplest(I, varargin{:}); 102 | otherwise 103 | OUT=I; disp('Unknown alogrithm, please check name.'); 104 | algorithm 105 | end 106 | 107 | end 108 | 109 | function OUT = simplest(I, s1, s2) 110 | % Multiscale Retinex [IPOL] 111 | % In all the outputs we applied a simplest color balance with 1% pixel clipping 112 | % on either side of the dynamical range. 113 | 114 | if ~exist('s1', 'var'), s1 = 1.5; end 115 | if ~exist('s2', 'var'), s2 = 1.5; end 116 | 117 | Tol = [s1/100, 1-s2/100]; 118 | for c = 1:size(I,3) 119 | Low_High = stretchlim(I(:,:,c),Tol); 120 | OUT(:,:,c) = imadjust(I(:,:,c),Low_High,[]); 121 | end 122 | end -------------------------------------------------------------------------------- /lowlight/dong.m: -------------------------------------------------------------------------------- 1 | function d = Dong( im ,w ) 2 | if max(im(:)) > 1 3 | im = im2double(im); 4 | end 5 | isize = size(im); 6 | im = padarray(im,[2*5,2*5,0],'replicate'); 7 | if (~exist('w','var') || w<=0) 8 | w = 0.8; 9 | end 10 | 11 | R = 1 - im; 12 | % [Rd,~] = dehaze(R,w); 13 | Ir = R(:,:,1); 14 | Ig = R(:,:,2); 15 | Ib = R(:,:,3); 16 | 17 | Ir1 = Ir(:); 18 | Ig1 = Ig(:); 19 | Ib1 = Ib(:); 20 | Il = (Ir1+Ig1+Ib1)./3; 21 | n = length(Il); 22 | N = floor(n*0.002); 23 | 24 | Ir_d = ordfilt2(Ir,1,ones(7,7)); 25 | Ig_d = ordfilt2(Ig,1,ones(7,7)); 26 | Ib_d = ordfilt2(Ib,1,ones(7,7)); 27 | darkc = min(min(Ir_d(:),Ig_d(:)),Ib_d(:)); 28 | [~, i] = sort(darkc,1,'descend'); 29 | temp = Il(i(1:N)); 30 | [~,j] = sort(temp,1,'descend'); 31 | Ar = Ir1(i(j(1))); 32 | Ag = Ig1(i(j(1))); 33 | Ab = Ib1(i(j(1))); 34 | % exp(log()) 35 | t = max(1-w.*min(min(Ir_d./Ar,Ig_d./Ag),Ib_d./Ab),10^(-7)); 36 | lc = t<0.5; 37 | t(lc) = 2 * t(lc).^2; 38 | 39 | Sr = (Ir - Ar)./t +Ar; 40 | Sg = (Ig - Ag)./t +Ag; 41 | Sb = (Ib - Ab)./t +Ab; 42 | 43 | Rd = cat(3,Sr,Sg,Sb); 44 | d = 1-Rd(11:isize(1)+10,11:isize(2)+10,:); 45 | end 46 | 47 | -------------------------------------------------------------------------------- /lowlight/lime.m: -------------------------------------------------------------------------------- 1 | function [I, T_ini,T_ref] = lime(L,para,post) 2 | % A wrapper of LIME 3 | % LIME: A Method for Low-light IMage Enhancement 4 | % 5 | % INPUTS 6 | % para: parameter 7 | % post: true if do post-processing (denoise) 8 | % OUTPUTS 9 | % I - result image 10 | % ------------------------------------------------------------------------- 11 | % @article{guo2016lime, 12 | % title={LIME: A Method for Low-light IMage Enhancement}, 13 | % author={Guo, Xiaojie}, 14 | % journal={arXiv preprint arXiv:1605.05034}, 15 | % year={2016} 16 | % } 17 | % ------------------------------------------------------------------------- 18 | % 19 | % Zhenqiang Ying 20 | % 2016-11-02 21 | 22 | if nargin == 0 23 | I = imload(uigetimagefile); 24 | [J, T_ini,T_ref] = lime(I); 25 | T = repmat(T_ref, [1 1 3]); 26 | ezFig I J I./(T.^0.6) I./(T.^0.8) T_ini T_ref 27 | clear I; 28 | return; 29 | end 30 | 31 | Require LIME 32 | 33 | if nargin < 2 34 | para.lambda = 0.15; 35 | para.sigma = 2; 36 | para.gamma = 0.8; 37 | if nargin < 3 38 | post = false; 39 | end 40 | end 41 | 42 | if ~isfloat(L), L = im2double(L); end 43 | 44 | tic 45 | [I, T_ini,T_ref] = LIME(L,para); 46 | toc 47 | 48 | % figure(1);imshow(L);title('Input'); 49 | % figure(2);imshow(I);title('LIME'); 50 | 51 | % figure(3);imshow(T_ini,[]);colormap hot;title('Initial T'); 52 | % figure(4);imshow(T_ref,[]);colormap hot;title('Refined T'); 53 | %% Post Processing 54 | if post 55 | %addpath(genpath('+existingMethods\+LIME\BM3D')); 56 | %import filter.BM3D.* 57 | 58 | YUV = rgb2ycbcr(I); 59 | Y = YUV(:,:,1); 60 | 61 | Y_d = BM3D(Y); 62 | 63 | I_d = ycbcr2rgb(cat(3,Y_d,YUV(:,:,2:3))); 64 | I_f = (I).*repmat(T_ref,[1,1,3])+I_d.*repmat(1-T_ref,[1,1,3]); 65 | 66 | % figure(5);imshow(I_d);title('Denoised '); 67 | % figure(6);imshow(I_f);title('Recomposed'); 68 | I = I_f; 69 | end 70 | 71 | end 72 | 73 | 74 | %% DEMO 75 | % clc;close all;clear all;addpath(genpath('./')); 76 | % %% 77 | % filename = '1.bmp'; 78 | % L = (im2double(imread(filename))); 79 | % 80 | % post = true; 81 | % 82 | % para.lambda = 0.15; 83 | % para.sigma = 2; 84 | % para.gamma = 0.8; 85 | % tic 86 | % [I, T_ini,T_ref] = LIME(L,para); 87 | % toc 88 | % 89 | % figure(1);imshow(L);title('Input'); 90 | % figure(2);imshow(I);title('LIME'); 91 | % figure(3);imshow(T_ini,[]);colormap hot;title('Initial T'); 92 | % figure(4);imshow(T_ref,[]);colormap hot;title('Refined T'); 93 | % %% Post Processing 94 | % if post 95 | % YUV = rgb2ycbcr(I); 96 | % Y = YUV(:,:,1); 97 | % 98 | % sigma_BM3D = 50; 99 | % [~, Y_d] = BM3D(Y,Y,sigma_BM3D,'lc',0); 100 | % 101 | % I_d = ycbcr2rgb(cat(3,Y_d,YUV(:,:,2:3))); 102 | % I_f = (I).*repmat(T_ref,[1,1,3])+I_d.*repmat(1-T_ref,[1,1,3]); 103 | % 104 | % figure(5);imshow(I_d);title('Denoised '); 105 | % figure(6);imshow(I_f);title('Recomposed'); 106 | % end -------------------------------------------------------------------------------- /lowlight/mf.m: -------------------------------------------------------------------------------- 1 | function [output] = mf(input) 2 | % A wrapper of MF (Multi-deviation Fusion method) 3 | % 4 | % ------------------------------------------------------------------------- 5 | % @article{fu2016mf, 6 | % title={A fusion-based enhancing method for weakly illuminated images}, 7 | % author={Fu, Xueyang and Zeng, Delu and Huang, Yue and Liao, Yinghao and Ding, Xinghao and Paisley, John}, 8 | % journal={Signal Processing}, 9 | % volume={129}, 10 | % pages={82--96}, 11 | % year={2016}, 12 | % publisher={Elsevier} 13 | % } 14 | % ------------------------------------------------------------------------- 15 | % 16 | % OpenCE https://github.com/baidut/OpenCE 17 | % Author: Zhenqiang Ying 18 | % 2017-5-12 19 | 20 | if nargin == 0 21 | I = imload; % imread('yellowlily.jpg'); % 22 | J = mf(I); 23 | ezFig(I,J); 24 | return; 25 | end 26 | 27 | Require MF 28 | 29 | if ~isfloat(input), input = im2double(input); end 30 | if isfloat(input), input = (input)*255; end 31 | 32 | output = multi_fusion(input); 33 | end -------------------------------------------------------------------------------- /lowlight/multiscaleRetinex.m: -------------------------------------------------------------------------------- 1 | function OUT = multiscaleRetinex(I, method, varargin) 2 | 3 | if nargin == 0 4 | % I = imload; %imread(imgetfile); %imread('office_1.jpg'); 5 | % J = multiscaleRetinex(I, 'MSRCR'); 6 | % ezFig I J 7 | % return; 8 | 9 | I = imload; %imread(imgetfile); %('office_1.jpg'); 10 | method = Popupmenu({'MSRCR','MSR','SSR'}); 11 | J = ImCtrl(@multiscaleRetinex, I, method); 12 | ezFig I J 13 | end 14 | 15 | if nargin == 1 16 | method = 'MSRCR'; 17 | end 18 | 19 | I = im2double(I).*255+1; % +1 to avoid Inf 20 | SSR = @SSRlog; % @SSR; % 21 | 22 | % TODO: gray or RGB 23 | 24 | switch (method) 25 | case {'SSR' 'single scale retinex'}, f = SSR; 26 | case {'MSR' 'multi scale retinex'}, f = @MSR; 27 | case 'MSRCR', f = @MSRCR; 28 | %case 'MSRCP', f = @MSRCP; 29 | otherwise 30 | return; 31 | %f = str2func(method); 32 | end 33 | 34 | OUT = f(I, varargin{:}); 35 | 36 | end 37 | 38 | function OUT = SSR(I, varargin) 39 | T = imgaussfilt(I, varargin{:}); 40 | OUT = I./(T); % avoid NaN 41 | end 42 | 43 | function OUT = SSRlog(I, varargin) 44 | T = imgaussfilt(I, varargin{:}); 45 | OUT = log(I) - log(T+1) + 0.5; 46 | end 47 | 48 | function OUT = MSR(I, varargin) 49 | if numel(varargin) == 0 50 | varargin = {25 100 240}; 51 | end 52 | OUT = 0; N = numel(varargin); 53 | for n = 1:N 54 | OUT = OUT + (1/N)* multiscaleRetinex(I,'SSR',varargin{n}); 55 | end 56 | end 57 | 58 | function OUT = MSRCR(I, lowScale, medScale, highScale, leftChop, rightChop) 59 | if ~exist('lowScale', 'var'), lowScale = 15; end 60 | if ~exist('MedScale', 'var'), medScale = 80; end 61 | if ~exist('HighScale', 'var'), highScale = 250; end 62 | if ~exist('s1', 'var'), leftChop = 1; end 63 | if ~exist('s2', 'var'), rightChop = 1; end 64 | 65 | MSR = multiscaleRetinex(I, 'MSR', lowScale, medScale, highScale); 66 | 67 | for c = 1:3 68 | CR = (log(125*I(:,:,c))-log(I(:,:,1)+I(:,:,2)+I(:,:,3))); 69 | OUT(:,:,c) = colorBalance(mat2gray(CR.*MSR(:,:,c)), 'simplest', leftChop, rightChop); 70 | end 71 | %OUT = max(0, min(1, OUT)); 72 | end 73 | -------------------------------------------------------------------------------- /lowlight/npe.m: -------------------------------------------------------------------------------- 1 | function I = npe(I) 2 | if nargin == 0 3 | file = imgetfile, 4 | I = imload(file); 5 | ezFig I lime(I) npe(I) 6 | %npe(I) 7 | clear I; 8 | return; 9 | end 10 | 11 | Require 'NPE' 12 | % Require ../#include/TIP13NPE\NPE code and database\NPE 13 | I=NPEA(I); 14 | 15 | end 16 | 17 | % function I = imread(I) % overload the imread in NPEA 18 | % end 19 | 20 | % Run the following code: 21 | % pic=NPEA('example.jpg'); 22 | % Then you can get the enhanced image. 23 | % figure imshow(pic); 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /lowlight/srie.m: -------------------------------------------------------------------------------- 1 | function [enhanced_result, R, L] = srie(input_image) 2 | % A wrapper of SRIE (Simultaneous Reflection and Illumination Estimation) 3 | % 4 | % ------------------------------------------------------------------------- 5 | % @inproceedings{fu2016srie, 6 | % title={A weighted variational model for simultaneous reflectance and illumination estimation}, 7 | % author={Fu, Xueyang and Zeng, Delu and Huang, Yue and Zhang, Xiao-Ping and Ding, Xinghao}, 8 | % booktitle={Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition}, 9 | % pages={2782--2790}, 10 | % year={2016} 11 | % } 12 | % ------------------------------------------------------------------------- 13 | % 14 | % OpenCE https://github.com/baidut/OpenCE 15 | % Author: Zhenqiang Ying 16 | % 2017-5-11 17 | 18 | if nargin == 0 19 | I = imread('yellowlily.jpg'); %imload; 20 | [J, R, L] = srie(I); 21 | ezFig(I,J,R,L); 22 | return; 23 | end 24 | 25 | Require SRIE 26 | 27 | if ~isfloat(input_image), input_image = im2double(input_image); end 28 | 29 | img = 255*input_image; 30 | 31 | if size(img,3)>1 32 | HSV = rgb2hsv(img); % RGB space to HSV space 33 | S = HSV(:,:,3); % V layer 34 | else 35 | S = img; % gray image 36 | end 37 | 38 | 39 | c_1 = 0.01; c_2 = 0.1; lambda = 1; % set parameters 40 | 41 | epsilon_stop = 1e-3; % stopping criteria 42 | 43 | [ R, L, epsilon_R, epsilon_L ] = processing( S, c_1, c_2, lambda, epsilon_stop ); 44 | 45 | 46 | %%% Gamma correction 47 | gamma = 2.2; 48 | L_gamma = 255 * ((L/255).^(1/gamma)); 49 | enhanced_V = R .* L_gamma; 50 | HSV(:,:,3) = enhanced_V; 51 | enhanced_result = hsv2rgb(HSV); 52 | 53 | % figure, 54 | % subplot(2,2,1),imshow(uint8(img)), title('input image'); 55 | % subplot(2,2,2),imshow(uint8(enhanced_result)),title('Gamma correction'); 56 | % subplot(2,2,3),imshow(uint8(L)), title('estimated illumination'); 57 | % subplot(2,2,4),imshow(R), title('estimated reflectance'); 58 | 59 | L = L/255; 60 | enhanced_result = enhanced_result/255; 61 | end -------------------------------------------------------------------------------- /quality/VIF/ind2wtree.m: -------------------------------------------------------------------------------- 1 | function wtree = ind2wtree(pyr, ind) 2 | 3 | %this function is called by vifvec.m 4 | % converts the output of Eero Simoncelli's pyramid routines into subbands in a cell array 5 | C=pyr; 6 | S=ind; 7 | 8 | offset=0; 9 | numsubs=size(ind,1); 10 | for i=1:numsubs 11 | wtree{numsubs-i+1}=reshape(C(offset+1:offset+prod(S(i,:))), S(i,1),S(i,2)); 12 | offset=offset+prod(S(i,:)); 13 | end 14 | -------------------------------------------------------------------------------- /quality/VIF/readme.txt: -------------------------------------------------------------------------------- 1 | % -----------COPYRIGHT NOTICE STARTS WITH THIS LINE------------ 2 | % Copyright (c) 2005 The University of Texas at Austin 3 | % All rights reserved. 4 | % 5 | % Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, 6 | % modify, and distribute this code (the source files) and its documentation for 7 | % any purpose, provided that the copyright notice in its entirety appear in all copies of this code, and the 8 | % original source of this code, Laboratory for Image and Video Engineering (LIVE, http://live.ece.utexas.edu) 9 | % at the University of Texas at Austin (UT Austin, 10 | % http://www.utexas.edu), is acknowledged in any publication that reports research using this code. The research 11 | % is to be cited in the bibliography as: 12 | % 13 | % H. R. Sheikh and A. C. Bovik, "Image Information and Visual Quality", IEEE Transactions on 14 | % Image Processing, (to appear). 15 | % 16 | % IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT AUSTIN BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, 17 | % OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS DATABASE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF TEXAS 18 | % AT AUSTIN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 19 | % 20 | % THE UNIVERSITY OF TEXAS AT AUSTIN SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | % WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE DATABASE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, 22 | % AND THE UNIVERSITY OF TEXAS AT AUSTIN HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23 | % 24 | % -----------COPYRIGHT NOTICE ENDS WITH THIS LINE------------ 25 | 26 | This software release consists of an implementation of the algorithm described in the paper: 27 | 28 | H. R. Sheikh and A. C. Bovik, "Image Information and Visual Quality"., IEEE Transactions on Image Processing, (to appear). 29 | Download manuscript draft from http://live.ece.utexas.edu in the Publications link. 30 | 31 | 32 | It consists of the following files: 33 | 34 | readme.txt: this file 35 | vifvec.m: main function, call this to evaluate image quality 36 | support .m files: ind2wtree.m, refparams_vecgsm.m, vifsub_est_M.m 37 | 38 | Prerequisites: The Steerable Pyramid toolbox. Available at 39 | http://www.cns.nyu.edu/~lcv/software.html 40 | 41 | Input : (1) img1: The reference image as a matrix 42 | (2) img2: The distorted image (order is important) 43 | 44 | Output: (1) VIF the visual information fidelity measure between the two images 45 | 46 | Default Usage: 47 | Given 2 test images img1 and img2, whose dynamic range is 0-255 48 | 49 | vif = vifvec(img1, img2); 50 | 51 | Advanced Usage: 52 | Users may want to modify the parameters in the code. 53 | (1) Modify sigma_nsq to find tune for your image dataset. 54 | (2) MxM is the block size that denotes the size of a vector used in the 55 | GSM model. 56 | (3) subbands included in the computation 57 | 58 | 59 | Please read the paper for more details on interpretation of the results. 60 | Email comments and bug reports to hamid.sheikh@ieee.org -------------------------------------------------------------------------------- /quality/VIF/refparams_vecgsm.m: -------------------------------------------------------------------------------- 1 | function [ssarr, l_arr, cu_arr]=refparams_vecgsm(org,subands,M) 2 | 3 | %This function computes the parameters of the reference image. This is 4 | %called by vifvec.m. 5 | 6 | for i=1:length(subands); 7 | sub=subands(i); 8 | y=org{sub}; 9 | 10 | sizey=floor(size(y)./M)*M; % crop to exact multiple size 11 | y=y(1:sizey(1),1:sizey(2)); 12 | 13 | 14 | % Collect MxM blocks. Rearrange each block into an 15 | % M^2 dimensional vector and collect all such vectors. 16 | % Collece ALL possible MXM blocks (even those overlapping) from the subband 17 | temp=[]; 18 | for j=1:M 19 | for k=1:M 20 | temp=cat(1,temp,reshape(y(k:end-(M-k), j:end-(M-j)),1,[])); 21 | end 22 | end 23 | 24 | % estimate mean and covariance 25 | mcu=mean(temp')'; 26 | cu=((temp-repmat(mcu,1,size(temp,2)))*(temp-repmat(mcu,1,size(temp,2)))')./size(temp,2); % covariance matrix for U 27 | 28 | % Collect MxM blocks as above. Use ONLY non-overlapping blocks to 29 | % calculate the S field 30 | temp=[]; 31 | for j=1:M 32 | for k=1:M 33 | temp=cat(1,temp,reshape(y(k:M:end, j:M:end),1,[])); 34 | end 35 | end 36 | 37 | % Calculate the S field 38 | ss=(inv(cu)*temp); 39 | ss=sum(ss.*temp)./(M*M); 40 | ss=reshape(ss,sizey/M); 41 | 42 | % Eigen-decomposition 43 | [v,d]=eig(cu); 44 | l_arr(sub,:)=diag(d)'; 45 | 46 | % rearrange for output 47 | ssarr{sub}=ss; 48 | temp=0; 49 | d=diag(d); 50 | cu_arr{sub}=cu; 51 | end 52 | 53 | -------------------------------------------------------------------------------- /quality/VIF/vifsub_est_M.m: -------------------------------------------------------------------------------- 1 | function [g_all, vv_all]=vifsub_est_M(org,dist, subbands, M); 2 | 3 | % uses convolution for determining the parameters of the distortion channel 4 | % Called by vifvec.m 5 | 6 | tol = 1e-15; % tolernace for zero variance. Variance below this is set to zero, and zero is set to this value to avoid numerical issues. 7 | 8 | 9 | for i=1:length(subbands) 10 | sub=subbands(i); 11 | y=org{sub}; 12 | yn=dist{sub}; 13 | 14 | % compute the size of the window used in the distortion channel estimation 15 | lev=ceil((sub-1)/6); 16 | winsize=2^lev+1; offset=(winsize-1)/2; 17 | win = ones(winsize); 18 | 19 | % force subband size to be multiple of M 20 | newsize=floor(size(y)./M)*M; 21 | y=y(1:newsize(1),1:newsize(2)); 22 | yn=yn(1:newsize(1),1:newsize(2)); 23 | 24 | % Correlation with downsampling. This is faster than downsampling after 25 | % computing full correlation. 26 | winstep=[M M]; 27 | winstart=[1 1].*floor(M/2)+1; 28 | winstop=size(y)-ceil(M/2)+1; 29 | 30 | % mean 31 | mean_x = corrDn(y,win/sum(win(:)),'reflect1',winstep, winstart,winstop); 32 | mean_y = corrDn(yn,win/sum(win(:)),'reflect1',winstep, winstart,winstop); 33 | % cov 34 | cov_xy = corrDn(y.*yn, win, 'reflect1',winstep, winstart,winstop) - sum(win(:)).*mean_x.*mean_y; 35 | % var 36 | ss_x = corrDn(y.^2,win, 'reflect1',winstep, winstart,winstop) - sum(win(:)).*mean_x.^2; 37 | ss_y = corrDn(yn.^2,win, 'reflect1',winstep, winstart,winstop) - sum(win(:)).*mean_y.^2; 38 | 39 | 40 | % get rid of numerical problems, very small negative numbers, or very 41 | % small positive numbers, or other theoretical impossibilities. 42 | ss_x(ss_x<0)=0; 43 | ss_y(ss_y<0)=0; 44 | 45 | % Regression 46 | g = cov_xy./(ss_x+tol); 47 | 48 | % Variance of error in regression 49 | vv = (ss_y - g.*cov_xy)/(sum(win(:))); 50 | 51 | % get rid of numerical problems, very small negative numbers, or very 52 | % small positive numbers, or other theoretical impossibilities. 53 | g (ss_x < tol) = 0; 54 | vv (ss_x < tol) = ss_y (ss_x < tol); 55 | ss_x(ss_x=rawL(r,c); 49 | mapResultOrder = enhanceResultL>=enhanceResultL(r,c); 50 | mapError = xor(mapRawOrder,mapResultOrder); 51 | error = error + sum(mapError(:)); 52 | mask(r,c) = sum(mapError(:)); 53 | end 54 | end 55 | 56 | %% save mask to file 57 | fileName = globalVar('TestImage_resultFile', 'tmp'); % Test_resultFile 58 | dirname = rename(fileName, '/loe100x100'); 59 | if ~exist(dirname,'dir'), mkdir(dirname); end 60 | figure; imshow(mask./5000, 'Border','tight','InitialMagnification',500); % colormap jet 61 | print(gcf, rename(fileName, '/loe100x100/loe100x100_'), '-djpeg'); close(gcf); 62 | 63 | 64 | lightOrderError = error / (N*N); %(size(raw,1)*size(raw,2)); 65 | 66 | end 67 | -------------------------------------------------------------------------------- /quality/vif.m: -------------------------------------------------------------------------------- 1 | function score=vif(imorg,imdist) 2 | if nargin ==0 3 | I = imread('peppers.png'); 4 | disp 'VIF = 1 : perfect' 5 | disp 'VIF = 0 : full of distortion' 6 | fprintf('VIF(I, I) = %f while VIF(I, I./2) = %f, VIF(I./2, I) = %f\n',vif(I, I),vif(I, I./2),vif(I./2, I)); 7 | return; 8 | end 9 | Require VIF; 10 | 11 | if size(imorg, 3) == 3 12 | imorg = rgb2gray(imorg); 13 | end 14 | 15 | if size(imdist, 3) == 3 16 | imdist = rgb2gray(imdist); 17 | end 18 | 19 | imorg = im2double(imorg); 20 | imdist = im2double(imdist); 21 | score=vifvec(imorg,imdist); 22 | % -----------COPYRIGHT NOTICE STARTS WITH THIS LINE------------ 23 | % Copyright (c) 2005 The University of Texas at Austin 24 | % All rights reserved. 25 | % 26 | % Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, 27 | % modify, and distribute this code (the source files) and its documentation for 28 | % any purpose, provided that the copyright notice in its entirety appear in all copies of this code, and the 29 | % original source of this code, Laboratory for Image and Video Engineering (LIVE, http://live.ece.utexas.edu) 30 | % at the University of Texas at Austin (UT Austin, 31 | % http://www.utexas.edu), is acknowledged in any publication that reports research using this code. The research 32 | % is to be cited in the bibliography as: 33 | % 34 | % H. R. Sheikh and A. C. Bovik, "Image Information and Visual Quality", IEEE Transactions on 35 | % Image Processing, (to appear). 36 | % 37 | % IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT AUSTIN BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, 38 | % OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS DATABASE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF TEXAS 39 | % AT AUSTIN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 | % 41 | % THE UNIVERSITY OF TEXAS AT AUSTIN SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 42 | % WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE DATABASE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, 43 | % AND THE UNIVERSITY OF TEXAS AT AUSTIN HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 44 | % 45 | % -----------COPYRIGHT NOTICE ENDS WITH THIS LINE------------ 46 | % 47 | %This is an implementation of the algorithm for calculating the 48 | %Visual Information Fidelity (VIF) measure (may also be known as the Sheikh 49 | %-Bovik Index) between two images. Please refer 50 | %to the following paper: 51 | % 52 | %H. R. Sheikh and A. C. Bovik "Image Information and Visual Quality" 53 | %IEEE Transactios on Image Processing, in publication, May 2005. 54 | %Download manuscript draft from http://live.ece.utexas.edu in the 55 | %Publications link 56 | % 57 | %This implementation is slightly differnet from the one used to report 58 | %results in the paper above. The modification have to do with using more 59 | %subands than those used in the paper, better handling of image boundaries, 60 | %and a window that automatically resizes itself based on the scale. 61 | % 62 | %Report bugfixes and comments to hamid.sheikh@ieee.org 63 | % 64 | %---------------------------------------------------------------------- 65 | % Prerequisites: The Steerable Pyramid toolbox. Available at 66 | % http://www.cns.nyu.edu/~lcv/software.html 67 | % 68 | %Input : (1) img1: The reference image 69 | % (2) img2: The distorted image (order is important) 70 | % 71 | %Output: (1) VIF te visual information fidelity measure between the two images 72 | 73 | %Default Usage: 74 | % Given 2 test images img1 and img2, whose dynamic range is 0-255 75 | % 76 | % vif = vifvec(img1, img2); 77 | % 78 | %Advanced Usage: 79 | % Users may want to modify the parameters in the code. 80 | % (1) Modify sigma_nsq to find tune for your image dataset. 81 | % (2) MxM is the block size that denotes the size of a vector used in the 82 | % GSM model. 83 | % (3) subbands included in the computation 84 | %======================================================================== -------------------------------------------------------------------------------- /startup.m: -------------------------------------------------------------------------------- 1 | function startup 2 | persistent done 3 | 4 | if isempty(done) 5 | clear global 6 | userpath(pwd) 7 | 8 | addpath(pwd, genpath([pwd, '\util'])); 9 | ezPath lowlight quality 10 | 11 | savepath 12 | 13 | dbstop if error 14 | done = 1; 15 | end -------------------------------------------------------------------------------- /util/Cd.m: -------------------------------------------------------------------------------- 1 | % t = TempDir 2 | % t = ThisDir 3 | 4 | classdef Cd < handle % delete 5 | %CD change current folder temporarily 6 | % dir = Cd; 7 | % dir = Cd('your_tmp_path'); 8 | 9 | properties 10 | path % old path 11 | end 12 | methods 13 | function this = Cd(path) 14 | caller = callerFile; 15 | curPath = caller.path; 16 | if nargin == 0 17 | path = curPath; 18 | end 19 | this.path = cd; 20 | cd(strrep(path, './', [curPath, '/'])); 21 | %fprintf('Current Folder Changed to %s Temporarily.\n', path); 22 | end 23 | function delete(this) 24 | cd(this.path); 25 | %fprintf('Current Folder Changed Back.\n') 26 | end 27 | function s = char(this) 28 | % dir = Cd; 29 | % fprintf('%s\n', dir); 30 | s = this.path; 31 | end 32 | end 33 | end -------------------------------------------------------------------------------- /util/Require.m: -------------------------------------------------------------------------------- 1 | classdef Require < handle 2 | %REQUIRE manage dependency. 3 | % Instead of using: 4 | % 5 | % required = {'path1', 'path2', 'path3'}; 6 | % addpath(required{:}); 7 | % % do something 8 | % rmpath(required{:}); 9 | % 10 | % Just use single line: 11 | % 12 | % r = Require('path1', 'path2', 'path3'); 13 | % Or 14 | % Require('path1', 'path2', 'path3'); 15 | % 16 | % The required path will be removed automatically. 17 | % To remove the path mannully: 18 | % 19 | % clear r; 20 | % 21 | % If you wana add path permenately, use `addpath` and `savepath` 22 | % instead. 23 | % 24 | % Add requirement in matlab cmd window: require folder1 folder2 25 | % the requirement will be removed automatically when ans is replaced or 26 | % cleared. 27 | 28 | properties 29 | path = {} 30 | fprintf 31 | end 32 | methods 33 | function this = Require(varargin) 34 | if nargout == 0 % be quiet, no information out 35 | this.fprintf = @(varargin)[]; 36 | else 37 | this.fprintf = @fprintf; 38 | end 39 | 40 | % this.path = varargin; 41 | % addpath(this.path{:}); 42 | inputPath = strjoin(varargin, ';'); 43 | pathList = strsplit(inputPath, ';'); 44 | 45 | %% 46 | try 47 | caller = callerFile; 48 | defaultPath = caller.path; 49 | catch 50 | defaultPath = cd; 51 | end 52 | 53 | for pathStr = pathList 54 | [p, func] = strsplit(pathStr{1}, '>');p = p{1}; 55 | if ~ismember(':', p) % is not fullpath 56 | p = [defaultPath filesep p]; 57 | end 58 | if isempty(func) || ~exist(func{1}, 'file') 59 | addpath(p); 60 | this.path{end+1} = p; 61 | end 62 | end 63 | %ezPath(struct('SavePath', false), varargin{:}); 64 | this.fprintf('Requirement Added.\n%s\n', strjoin(this.path,'\n')); 65 | end 66 | function delete(this) 67 | this.fprintf('Requirement Removed.'); 68 | if ~isempty(this.path), rmpath(this.path{:}); end 69 | end 70 | function add(this, varargin) 71 | addpath(varargin{:}); 72 | this.path = [this.path, varargin]; 73 | end 74 | function save(this) 75 | savepath % what about other Require? 76 | this.path = {}; 77 | end 78 | function disp(this) 79 | this.fprintf('%s\n', this.path{:}); 80 | end 81 | end 82 | end -------------------------------------------------------------------------------- /util/TestImage.m: -------------------------------------------------------------------------------- 1 | classdef TestImage < matlab.mixin.SetGet %handle 2 | %TestImage help you test the performance of image enhancement algorithms. 3 | %Example 4 | % Test = CE.TestImage('pout.tif'); % specify datasets 5 | % Test.Method = {@imadjust, @imsharpen}; % specify methods to evaluate 6 | % Test.Metric = {@psnr, @ssim}; % specify evaluate metrics 7 | % Test, % run test and show result 8 | % save(Test); % save results 9 | % 10 | % Test.addMethod(@histeq, @adapthisteq), 11 | % Test.delMethod(@imsharpen), 12 | % Test.addMetric(@runtime), 13 | % Test.delMetric(@ssim), 14 | % 15 | %For Developers 16 | % 17 | % TestImage provides global variables to get information about testing 18 | % 19 | % globalVar('TestImage_method'); 20 | % globalVar('TestImage_outFile'); 21 | % globalVar('TestImage_inFile'); 22 | 23 | properties 24 | Method % cellstr 25 | Metric % cellstr 26 | end 27 | 28 | methods 29 | function this = set.Method(this, val), this.Method = unique(this.CellStr(val), 'stable'); end 30 | function this = set.Metric(this, val), this.Metric = unique(this.CellStr(val), 'stable'); end 31 | end 32 | 33 | properties 34 | MethodCache = {} 35 | MetricCache = {} 36 | OutName = '__.PNG'; 37 | OutDir = '/out'; % output result images 38 | 39 | %append = true; % append result if true, overwrite result if false. 40 | 41 | %tbl 42 | Report % = CE.TestReport([]) 43 | Files 44 | DataDir % dataset folder 45 | 46 | LoadRaw = @(f)im2double(imread(f)) % filename 47 | LoadRes = @(f)im2double(imread(f)) 48 | LoadRef = @(f)im2double(imread(f)) % preprocessing file when evaluating 49 | end 50 | 51 | properties (Constant) 52 | ReportFile = '/out/TestReport.csv'; 53 | CellStr = @(cellFun)cellfun(@char, cellFun, 'UniformOutput', false); 54 | CellFun = @(cellStr)cellfun(@str2func, cellStr, 'UniformOutput', false); 55 | end 56 | 57 | methods(Access = public) 58 | function this = addMethod(this, varargin), this.Method = [this.Method this.CellStr(varargin)]; end 59 | function this = addMetric(this, varargin), this.Metric = [this.Metric this.CellStr(varargin)]; end 60 | function this = delMethod(this, varargin), this.Method = setdiff(this.Method, this.CellStr(varargin)); end 61 | function this = delMetric(this, varargin), this.Metric = setdiff(this.Metric, this.CellStr(varargin)); end 62 | 63 | function delResult(this, varargin) 64 | outDir = strrep(this.OutDir, '', this.DataDir); 65 | for n = 1:numel(varargin) 66 | outName = strrep(this.OutName, '', '*'); 67 | outName = strrep(outName, '', '*'); 68 | outName = strrep(outName, '', char(varargin{n})); 69 | eachfile([outDir filesep outName], @delete); 70 | end 71 | end 72 | end 73 | 74 | methods 75 | function this = TestImage(images, varargin) 76 | this.Files = eachfile(images); 77 | if isempty(this.Files) 78 | error 'no file found in this dataset.' 79 | else 80 | this.DataDir = fileparts(this.Files{1}); % images 81 | end 82 | 83 | % load configuation 84 | for n = 1:2:numel(varargin)-1 85 | this.(varargin{n}) = varargin{n+1}; 86 | end 87 | 88 | % load cached 89 | reportFile = strrep(this.ReportFile, '', this.DataDir); 90 | if exist(reportFile, 'file'), this.load(reportFile); end 91 | end 92 | 93 | function this = load(this, file) 94 | %import CE.TestReport 95 | 96 | fprintf('Loading... %s \n', file); 97 | this.Report = TestReport(file); 98 | disp 'Done Loading.' 99 | 100 | this.MethodCache = this.Report.Method; 101 | this.MetricCache = this.Report.Metric; 102 | this.Method = this.MethodCache; 103 | this.Metric = this.MetricCache; 104 | end 105 | 106 | function save(this, file) 107 | if nargin < 2 108 | file = strrep(this.ReportFile, '', this.DataDir); 109 | if exist(file, 'file') % backup 110 | movefile(file, rename(file, '/__%s.', datestr(now,'yyyy-mm-dd_HH-MM-SS.FFF'))); 111 | end 112 | end 113 | writetable(this.Report.Data, file); 114 | end 115 | 116 | function report = runtest(this, methods, metrics) 117 | % here methods and metrics are cell string 118 | %import CE.TestReport 119 | outDir = strrep(this.OutDir, '', this.DataDir); 120 | if ~isdir(outDir), mkdir(outDir); end 121 | 122 | reportFile = strrep([this.ReportFile '__tmp.txt'], '', this.DataDir); % tempfile 123 | %if ~isdir(fileparts(reportFile)), mkdir(fileparts(reportFile)); end 124 | 125 | fid = fopen(reportFile, 'w'); 126 | fprintf(fid, 'File\tMethod\t%s\n', strjoin(metrics, '\t')); % heading 127 | 128 | fprintf('Testing %s \n', this.DataDir); 129 | eachfile(this.Files, @onSingleFile); 130 | fprintf('Done Testing %s \n', this.DataDir); 131 | 132 | fclose(fid); 133 | fprintf('Benchmark Result see: %s\n', reportFile); 134 | report = TestReport(readtable(reportFile, 'Delimiter','\t')); 135 | 136 | function onSingleFile(inFile) 137 | %this.rawFile = inFile; 138 | globalVar('TestImage_inFile', inFile); 139 | % heading 140 | fprintf('Method\t\t\t'); fprintf('%9s\t', metrics{:}); fprintf('\n'); 141 | 142 | for m = methods(:)', method = m{1}; 143 | [~, name, ext] = fileparts(inFile); 144 | outName = strrep(this.OutName, '', name); 145 | outName = strrep(outName, '', ext(2:end)); 146 | outName = strrep(outName, '', char(method)); 147 | outFile = [outDir filesep outName]; 148 | 149 | % regenerate results if it is not exist 150 | if ~exist(outFile, 'file') 151 | fprintf('Regenerate file: %s\n', outFile); 152 | func = str2func(method); 153 | res = func(this.LoadRaw(inFile)); 154 | 155 | imwrite(im2double(res), outFile); 156 | end 157 | 158 | % load result file and compute metrics 159 | ref = this.LoadRef(inFile); 160 | res = this.LoadRes(outFile); 161 | 162 | globalVar('TestImage_method', method); 163 | globalVar('TestImage_outFile', outFile); 164 | 165 | fprintf(fid, '%s\t%s', [name, ext], method); fprintf('%8s\t', method); 166 | 167 | for n = metrics(:)', metric = n{1}; % if eval exist, then do it 168 | func = str2func(metric); 169 | try % allow two or one input 170 | marks = func(res, ref); 171 | catch ME 172 | switch ME.identifier 173 | case {'MATLAB:TooManyInputs', 'MATLAB:narginchk:tooManyInputs'} 174 | marks = func(res); 175 | otherwise 176 | ME.identifier, rethrow(ME) 177 | end 178 | end 179 | fprintf(fid, '\t%f', marks); fprintf('\t\t%.2f', marks); 180 | end 181 | fprintf(fid, '\n'); fprintf('\n'); 182 | end 183 | end 184 | end 185 | 186 | function disp(this) 187 | if isempty(this.Report) 188 | this.Report = this.runtest(this.Method, this.Metric); 189 | else 190 | [oldMethod,indexMethodCache] = intersect(this.MethodCache, this.Method); 191 | [oldMetric,indexMetricCache] = intersect(this.MetricCache, this.Metric); 192 | newMethod = setdiff(this.Method, this.MethodCache); 193 | newMetric = setdiff(this.Metric, this.MetricCache); 194 | 195 | this.Report = this.Report(indexMethodCache', indexMetricCache'); 196 | if ~isempty(newMethod) 197 | this.Report = vertcat(this.Report, this.runtest(newMethod, oldMetric)); end 198 | if ~isempty(newMetric) 199 | this.Report = horzcat(this.Report,this.runtest([oldMethod, newMethod], newMetric)); end 200 | 201 | % sort 202 | [~,indexMethod] = ismember(this.Method,this.Report.Method,'R2012a'); 203 | [~,indexMetric] = ismember(this.Metric,this.Report.Metric,'R2012a'); 204 | this.Report = this.Report(indexMethod, indexMetric); 205 | end 206 | 207 | this.MethodCache = this.Method; 208 | this.MetricCache = this.Metric; 209 | 210 | fprintf('Test Report: %s \n', this.DataDir); 211 | disp(this.Report); 212 | end 213 | end 214 | methods (Access = private) 215 | function outFile = getOutFileName(this, inFile, method) 216 | [~, name, ext] = fileparts(inFile); 217 | outName = strrep(this.OutName, '', name); 218 | outName = strrep(outName, '', ext(2:end)); 219 | outName = strrep(outName, '', char(method)); 220 | outFile = [outDir filesep outName]; 221 | end 222 | end 223 | end 224 | 225 | -------------------------------------------------------------------------------- /util/TestReport.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baidut/BIMEF/509f0411a57111859e1f767b4d91b33631fb2e7a/util/TestReport.m -------------------------------------------------------------------------------- /util/callerFile.m: -------------------------------------------------------------------------------- 1 | function out = callerFile(field) 2 | %CALLERFILE infor of current function's caller file 3 | %USAGE 4 | % s = callerFile 5 | % s 6 | % .name 7 | % .file 8 | % .line 9 | % .path 10 | % 11 | % c = callerFile(field) 12 | % 13 | % 14 | 15 | % carry with some debug info 16 | % st(1): funcName st(2): currently running function 17 | 18 | ST = dbstack('-completenames', 1); 19 | L = length(ST); 20 | 21 | if L < 2 22 | out.file = []; 23 | out.name = []; 24 | out.line = []; 25 | out.path = cd; 26 | else 27 | out = ST(2); 28 | out.path = fileparts(out.file); 29 | end 30 | 31 | if nargin ~= 0 32 | out = out.(field); 33 | end 34 | 35 | % carry with some debug info 36 | % st(1): funcName st(2): currently running function 37 | -------------------------------------------------------------------------------- /util/colorspace.m: -------------------------------------------------------------------------------- 1 | function varargout = colorspace(Conversion,varargin) 2 | %COLORSPACE Convert a color image between color representations. 3 | % B = COLORSPACE(S,A) converts the color representation of image A 4 | % where S is a string specifying the conversion. S tells the 5 | % source and destination color spaces, S = 'dest<-src', or 6 | % alternatively, S = 'src->dest'. Supported color spaces are 7 | % 8 | % 'RGB' R'G'B' Red Green Blue (ITU-R BT.709 gamma-corrected) 9 | % 'YPbPr' Luma (ITU-R BT.601) + Chroma 10 | % 'YCbCr'/'YCC' Luma + Chroma ("digitized" version of Y'PbPr) 11 | % 'YUV' NTSC PAL Y'UV Luma + Chroma 12 | % 'YIQ' NTSC Y'IQ Luma + Chroma 13 | % 'YDbDr' SECAM Y'DbDr Luma + Chroma 14 | % 'JPEGYCbCr' JPEG-Y'CbCr Luma + Chroma 15 | % 'HSV'/'HSB' Hue Saturation Value/Brightness 16 | % 'HSL'/'HLS'/'HSI' Hue Saturation Luminance/Intensity 17 | % 'XYZ' CIE XYZ 18 | % 'Lab' CIE L*a*b* (CIELAB) 19 | % 'Luv' CIE L*u*v* (CIELUV) 20 | % 'Lch' CIE L*ch (CIELCH) 21 | % 22 | % All conversions assume 2 degree observer and D65 illuminant. Color 23 | % space names are case insensitive. When R'G'B' is the source or 24 | % destination, it can be omitted. For example 'yuv<-' is short for 25 | % 'yuv<-rgb'. 26 | % 27 | % MATLAB uses two standard data formats for R'G'B': double data with 28 | % intensities in the range 0 to 1, and uint8 data with integer-valued 29 | % intensities from 0 to 255. As MATLAB's native datatype, double data is 30 | % the natural choice, and the R'G'B' format used by colorspace. However, 31 | % for memory and computational performance, some functions also operate 32 | % with uint8 R'G'B'. Given uint8 R'G'B' color data, colorspace will 33 | % first cast it to double R'G'B' before processing. 34 | % 35 | % If A is an Mx3 array, like a colormap, B will also have size Mx3. 36 | % 37 | % [B1,B2,B3] = COLORSPACE(S,A) specifies separate output channels. 38 | % COLORSPACE(S,A1,A2,A3) specifies separate input channels. 39 | 40 | % Pascal Getreuer 2005-2006 41 | 42 | %%% Input parsing %%% 43 | if nargin < 2, error('Not enough input arguments.'); end 44 | [SrcSpace,DestSpace] = parse(Conversion); 45 | 46 | if nargin == 2 47 | Image = varargin{1}; 48 | elseif nargin >= 3 49 | Image = cat(3,varargin{:}); 50 | else 51 | error('Invalid number of input arguments.'); 52 | end 53 | 54 | FlipDims = (size(Image,3) == 1); 55 | 56 | if FlipDims, Image = permute(Image,[1,3,2]); end 57 | if ~isa(Image,'double'), Image = double(Image)/255; end 58 | if size(Image,3) ~= 3, error('Invalid input size.'); end 59 | 60 | SrcT = gettransform(SrcSpace); 61 | DestT = gettransform(DestSpace); 62 | 63 | if ~ischar(SrcT) & ~ischar(DestT) 64 | % Both source and destination transforms are affine, so they 65 | % can be composed into one affine operation 66 | T = [DestT(:,1:3)*SrcT(:,1:3),DestT(:,1:3)*SrcT(:,4)+DestT(:,4)]; 67 | Temp = zeros(size(Image)); 68 | Temp(:,:,1) = T(1)*Image(:,:,1) + T(4)*Image(:,:,2) + T(7)*Image(:,:,3) + T(10); 69 | Temp(:,:,2) = T(2)*Image(:,:,1) + T(5)*Image(:,:,2) + T(8)*Image(:,:,3) + T(11); 70 | Temp(:,:,3) = T(3)*Image(:,:,1) + T(6)*Image(:,:,2) + T(9)*Image(:,:,3) + T(12); 71 | Image = Temp; 72 | elseif ~ischar(DestT) 73 | Image = rgb(Image,SrcSpace); 74 | Temp = zeros(size(Image)); 75 | Temp(:,:,1) = DestT(1)*Image(:,:,1) + DestT(4)*Image(:,:,2) + DestT(7)*Image(:,:,3) + DestT(10); 76 | Temp(:,:,2) = DestT(2)*Image(:,:,1) + DestT(5)*Image(:,:,2) + DestT(8)*Image(:,:,3) + DestT(11); 77 | Temp(:,:,3) = DestT(3)*Image(:,:,1) + DestT(6)*Image(:,:,2) + DestT(9)*Image(:,:,3) + DestT(12); 78 | Image = Temp; 79 | else 80 | Image = feval(DestT,Image,SrcSpace); 81 | end 82 | 83 | %%% Output format %%% 84 | if nargout > 1 85 | varargout = {Image(:,:,1),Image(:,:,2),Image(:,:,3)}; 86 | else 87 | if FlipDims, Image = permute(Image,[1,3,2]); end 88 | varargout = {Image}; 89 | end 90 | 91 | return; 92 | 93 | 94 | function [SrcSpace,DestSpace] = parse(Str) 95 | % Parse conversion argument 96 | 97 | if isstr(Str) 98 | Str = lower(strrep(strrep(Str,'-',''),' ','')); 99 | k = find(Str == '>'); 100 | 101 | if length(k) == 1 % Interpret the form 'src->dest' 102 | SrcSpace = Str(1:k-1); 103 | DestSpace = Str(k+1:end); 104 | else 105 | k = find(Str == '<'); 106 | 107 | if length(k) == 1 % Interpret the form 'dest<-src' 108 | DestSpace = Str(1:k-1); 109 | SrcSpace = Str(k+1:end); 110 | else 111 | error(['Invalid conversion, ''',Str,'''.']); 112 | end 113 | end 114 | 115 | SrcSpace = alias(SrcSpace); 116 | DestSpace = alias(DestSpace); 117 | else 118 | SrcSpace = 1; % No source pre-transform 119 | DestSpace = Conversion; 120 | if any(size(Conversion) ~= 3), error('Transformation matrix must be 3x3.'); end 121 | end 122 | return; 123 | 124 | 125 | function Space = alias(Space) 126 | Space = strrep(Space,'cie',''); 127 | 128 | if isempty(Space) 129 | Space = 'rgb'; 130 | end 131 | 132 | switch Space 133 | case {'ycbcr','ycc'} 134 | Space = 'ycbcr'; 135 | case {'hsv','hsb'} 136 | Space = 'hsv'; 137 | case {'hsl','hsi','hls'} 138 | Space = 'hsl'; 139 | case {'rgb','yuv','yiq','ydbdr','ycbcr','jpegycbcr','xyz','lab','luv','lch'} 140 | return; 141 | end 142 | return; 143 | 144 | 145 | function T = gettransform(Space) 146 | % Get a colorspace transform: either a matrix describing an affine transform, 147 | % or a string referring to a conversion subroutine 148 | switch Space 149 | case 'ypbpr' 150 | T = [0.299,0.587,0.114,0;-0.1687367,-0.331264,0.5,0;0.5,-0.418688,-0.081312,0]; 151 | case 'yuv' 152 | % R'G'B' to NTSC/PAL YUV 153 | % Wikipedia: http://en.wikipedia.org/wiki/YUV 154 | T = [0.299,0.587,0.114,0;-0.147,-0.289,0.436,0;0.615,-0.515,-0.100,0]; 155 | case 'ydbdr' 156 | % R'G'B' to SECAM YDbDr 157 | % Wikipedia: http://en.wikipedia.org/wiki/YDbDr 158 | T = [0.299,0.587,0.114,0;-0.450,-0.883,1.333,0;-1.333,1.116,0.217,0]; 159 | case 'yiq' 160 | % R'G'B' in [0,1] to NTSC YIQ in [0,1];[-0.595716,0.595716];[-0.522591,0.522591]; 161 | % Wikipedia: http://en.wikipedia.org/wiki/YIQ 162 | T = [0.299,0.587,0.114,0;0.595716,-0.274453,-0.321263,0;0.211456,-0.522591,0.311135,0]; 163 | case 'ycbcr' 164 | % R'G'B' (range [0,1]) to ITU-R BRT.601 (CCIR 601) Y'CbCr 165 | % Wikipedia: http://en.wikipedia.org/wiki/YCbCr 166 | % Poynton, Equation 3, scaling of R'G'B to Y'PbPr conversion 167 | T = [65.481,128.553,24.966,16;-37.797,-74.203,112.0,128;112.0,-93.786,-18.214,128]; 168 | case 'jpegycbcr' 169 | % Wikipedia: http://en.wikipedia.org/wiki/YCbCr 170 | T = [0.299,0.587,0.114,0;-0.168736,-0.331264,0.5,0.5;0.5,-0.418688,-0.081312,0.5]*255; 171 | case {'rgb','xyz','hsv','hsl','lab','luv','lch'} 172 | T = Space; 173 | otherwise 174 | error(['Unknown color space, ''',Space,'''.']); 175 | end 176 | return; 177 | 178 | 179 | function Image = rgb(Image,SrcSpace) 180 | % Convert to Rec. 709 R'G'B' from 'SrcSpace' 181 | switch SrcSpace 182 | case 'rgb' 183 | return; 184 | case 'hsv' 185 | % Convert HSV to R'G'B' 186 | Image = huetorgb((1 - Image(:,:,2)).*Image(:,:,3),Image(:,:,3),Image(:,:,1)); 187 | case 'hsl' 188 | % Convert HSL to R'G'B' 189 | L = Image(:,:,3); 190 | Delta = Image(:,:,2).*min(L,1-L); 191 | Image = huetorgb(L-Delta,L+Delta,Image(:,:,1)); 192 | case {'xyz','lab','luv','lch'} 193 | % Convert to CIE XYZ 194 | Image = xyz(Image,SrcSpace); 195 | % Convert XYZ to RGB 196 | T = [3.240479,-1.53715,-0.498535;-0.969256,1.875992,0.041556;0.055648,-0.204043,1.057311]; 197 | R = T(1)*Image(:,:,1) + T(4)*Image(:,:,2) + T(7)*Image(:,:,3); % R 198 | G = T(2)*Image(:,:,1) + T(5)*Image(:,:,2) + T(8)*Image(:,:,3); % G 199 | B = T(3)*Image(:,:,1) + T(6)*Image(:,:,2) + T(9)*Image(:,:,3); % B 200 | % Desaturate and rescale to constrain resulting RGB values to [0,1] 201 | AddWhite = -min(min(min(R,G),B),0); 202 | Scale = max(max(max(R,G),B)+AddWhite,1); 203 | R = (R + AddWhite)./Scale; 204 | G = (G + AddWhite)./Scale; 205 | B = (B + AddWhite)./Scale; 206 | % Apply gamma correction to convert RGB to Rec. 709 R'G'B' 207 | Image(:,:,1) = gammacorrection(R); % R' 208 | Image(:,:,2) = gammacorrection(G); % G' 209 | Image(:,:,3) = gammacorrection(B); % B' 210 | otherwise % Conversion is through an affine transform 211 | T = gettransform(SrcSpace); 212 | temp = inv(T(:,1:3)); 213 | T = [temp,-temp*T(:,4)]; 214 | R = T(1)*Image(:,:,1) + T(4)*Image(:,:,2) + T(7)*Image(:,:,3) + T(10); 215 | G = T(2)*Image(:,:,1) + T(5)*Image(:,:,2) + T(8)*Image(:,:,3) + T(11); 216 | B = T(3)*Image(:,:,1) + T(6)*Image(:,:,2) + T(9)*Image(:,:,3) + T(12); 217 | AddWhite = -min(min(min(R,G),B),0); 218 | Scale = max(max(max(R,G),B)+AddWhite,1); 219 | R = (R + AddWhite)./Scale; 220 | G = (G + AddWhite)./Scale; 221 | B = (B + AddWhite)./Scale; 222 | Image(:,:,1) = R; 223 | Image(:,:,2) = G; 224 | Image(:,:,3) = B; 225 | end 226 | 227 | % Clip to [0,1] 228 | Image = min(max(Image,0),1); 229 | return; 230 | 231 | 232 | function Image = xyz(Image,SrcSpace) 233 | % Convert to CIE XYZ from 'SrcSpace' 234 | WhitePoint = [0.950456,1,1.088754]; 235 | 236 | switch SrcSpace 237 | case 'xyz' 238 | return; 239 | case 'luv' 240 | % Convert CIE L*uv to XYZ 241 | WhitePointU = (4*WhitePoint(1))./(WhitePoint(1) + 15*WhitePoint(2) + 3*WhitePoint(3)); 242 | WhitePointV = (9*WhitePoint(2))./(WhitePoint(1) + 15*WhitePoint(2) + 3*WhitePoint(3)); 243 | L = Image(:,:,1); 244 | Y = (L + 16)/116; 245 | Y = invf(Y)*WhitePoint(2); 246 | U = Image(:,:,2)./(13*L + 1e-6*(L==0)) + WhitePointU; 247 | V = Image(:,:,3)./(13*L + 1e-6*(L==0)) + WhitePointV; 248 | Image(:,:,1) = -(9*Y.*U)./((U-4).*V - U.*V); % X 249 | Image(:,:,2) = Y; % Y 250 | Image(:,:,3) = (9*Y - (15*V.*Y) - (V.*Image(:,:,1)))./(3*V); % Z 251 | case {'lab','lch'} 252 | Image = lab(Image,SrcSpace); 253 | % Convert CIE L*ab to XYZ 254 | fY = (Image(:,:,1) + 16)/116; 255 | fX = fY + Image(:,:,2)/500; 256 | fZ = fY - Image(:,:,3)/200; 257 | Image(:,:,1) = WhitePoint(1)*invf(fX); % X 258 | Image(:,:,2) = WhitePoint(2)*invf(fY); % Y 259 | Image(:,:,3) = WhitePoint(3)*invf(fZ); % Z 260 | otherwise % Convert from some gamma-corrected space 261 | % Convert to Rec. 701 R'G'B' 262 | Image = rgb(Image,SrcSpace); 263 | % Undo gamma correction 264 | R = invgammacorrection(Image(:,:,1)); 265 | G = invgammacorrection(Image(:,:,2)); 266 | B = invgammacorrection(Image(:,:,3)); 267 | % Convert RGB to XYZ 268 | T = inv([3.240479,-1.53715,-0.498535;-0.969256,1.875992,0.041556;0.055648,-0.204043,1.057311]); 269 | Image(:,:,1) = T(1)*R + T(4)*G + T(7)*B; % X 270 | Image(:,:,2) = T(2)*R + T(5)*G + T(8)*B; % Y 271 | Image(:,:,3) = T(3)*R + T(6)*G + T(9)*B; % Z 272 | end 273 | return; 274 | 275 | 276 | function Image = hsv(Image,SrcSpace) 277 | % Convert to HSV 278 | Image = rgb(Image,SrcSpace); 279 | V = max(Image,[],3); 280 | S = (V - min(Image,[],3))./(V + (V == 0)); 281 | Image(:,:,1) = rgbtohue(Image); 282 | Image(:,:,2) = S; 283 | Image(:,:,3) = V; 284 | return; 285 | 286 | 287 | function Image = hsl(Image,SrcSpace) 288 | % Convert to HSL 289 | switch SrcSpace 290 | case 'hsv' 291 | % Convert HSV to HSL 292 | MaxVal = Image(:,:,3); 293 | MinVal = (1 - Image(:,:,2)).*MaxVal; 294 | L = 0.5*(MaxVal + MinVal); 295 | temp = min(L,1-L); 296 | Image(:,:,2) = 0.5*(MaxVal - MinVal)./(temp + (temp == 0)); 297 | Image(:,:,3) = L; 298 | otherwise 299 | Image = rgb(Image,SrcSpace); % Convert to Rec. 701 R'G'B' 300 | % Convert R'G'B' to HSL 301 | MinVal = min(Image,[],3); 302 | MaxVal = max(Image,[],3); 303 | L = 0.5*(MaxVal + MinVal); 304 | temp = min(L,1-L); 305 | S = 0.5*(MaxVal - MinVal)./(temp + (temp == 0)); 306 | Image(:,:,1) = rgbtohue(Image); 307 | Image(:,:,2) = S; 308 | Image(:,:,3) = L; 309 | end 310 | return; 311 | 312 | 313 | function Image = lab(Image,SrcSpace) 314 | % Convert to CIE L*a*b* (CIELAB) 315 | WhitePoint = [0.950456,1,1.088754]; 316 | 317 | switch SrcSpace 318 | case 'lab' 319 | return; 320 | case 'lch' 321 | % Convert CIE L*CH to CIE L*ab 322 | C = Image(:,:,2); 323 | Image(:,:,2) = cos(Image(:,:,3)*pi/180).*C; % a* 324 | Image(:,:,3) = sin(Image(:,:,3)*pi/180).*C; % b* 325 | otherwise 326 | Image = xyz(Image,SrcSpace); % Convert to XYZ 327 | % Convert XYZ to CIE L*a*b* 328 | X = Image(:,:,1)/WhitePoint(1); 329 | Y = Image(:,:,2)/WhitePoint(2); 330 | Z = Image(:,:,3)/WhitePoint(3); 331 | fX = f(X); 332 | fY = f(Y); 333 | fZ = f(Z); 334 | Image(:,:,1) = 116*fY - 16; % L* 335 | Image(:,:,2) = 500*(fX - fY); % a* 336 | Image(:,:,3) = 200*(fY - fZ); % b* 337 | end 338 | return; 339 | 340 | 341 | function Image = luv(Image,SrcSpace) 342 | % Convert to CIE L*u*v* (CIELUV) 343 | WhitePoint = [0.950456,1,1.088754]; 344 | WhitePointU = (4*WhitePoint(1))./(WhitePoint(1) + 15*WhitePoint(2) + 3*WhitePoint(3)); 345 | WhitePointV = (9*WhitePoint(2))./(WhitePoint(1) + 15*WhitePoint(2) + 3*WhitePoint(3)); 346 | 347 | Image = xyz(Image,SrcSpace); % Convert to XYZ 348 | U = (4*Image(:,:,1))./(Image(:,:,1) + 15*Image(:,:,2) + 3*Image(:,:,3)); 349 | V = (9*Image(:,:,2))./(Image(:,:,1) + 15*Image(:,:,2) + 3*Image(:,:,3)); 350 | Y = Image(:,:,2)/WhitePoint(2); 351 | L = 116*f(Y) - 16; 352 | Image(:,:,1) = L; % L* 353 | Image(:,:,2) = 13*L.*(U - WhitePointU); % u* 354 | Image(:,:,3) = 13*L.*(V - WhitePointV); % v* 355 | return; 356 | 357 | 358 | function Image = lch(Image,SrcSpace) 359 | % Convert to CIE L*ch 360 | Image = lab(Image,SrcSpace); % Convert to CIE L*ab 361 | H = atan2(Image(:,:,3),Image(:,:,2)); 362 | H = H*180/pi + 360*(H < 0); 363 | Image(:,:,2) = sqrt(Image(:,:,2).^2 + Image(:,:,3).^2); % C 364 | Image(:,:,3) = H; % H 365 | return; 366 | 367 | 368 | function Image = huetorgb(m0,m2,H) 369 | % Convert HSV or HSL hue to RGB 370 | N = size(H); 371 | H = min(max(H(:),0),360)/60; 372 | m0 = m0(:); 373 | m2 = m2(:); 374 | F = H - round(H/2)*2; 375 | M = [m0, m0 + (m2-m0).*abs(F), m2]; 376 | Num = length(m0); 377 | j = [2 1 0;1 2 0;0 2 1;0 1 2;1 0 2;2 0 1;2 1 0]*Num; 378 | k = floor(H) + 1; 379 | Image = reshape([M(j(k,1)+(1:Num).'),M(j(k,2)+(1:Num).'),M(j(k,3)+(1:Num).')],[N,3]); 380 | return; 381 | 382 | 383 | function H = rgbtohue(Image) 384 | % Convert RGB to HSV or HSL hue 385 | [M,i] = sort(Image,3); 386 | i = i(:,:,3); 387 | Delta = M(:,:,3) - M(:,:,1); 388 | Delta = Delta + (Delta == 0); 389 | R = Image(:,:,1); 390 | G = Image(:,:,2); 391 | B = Image(:,:,3); 392 | H = zeros(size(R)); 393 | k = (i == 1); 394 | H(k) = (G(k) - B(k))./Delta(k); 395 | k = (i == 2); 396 | H(k) = 2 + (B(k) - R(k))./Delta(k); 397 | k = (i == 3); 398 | H(k) = 4 + (R(k) - G(k))./Delta(k); 399 | H = 60*H + 360*(H < 0); 400 | H(Delta == 0) = nan; 401 | return; 402 | 403 | 404 | function Rp = gammacorrection(R) 405 | Rp = real(1.099*R.^0.45 - 0.099); 406 | i = (R < 0.018); 407 | Rp(i) = 4.5138*R(i); 408 | return; 409 | 410 | 411 | function R = invgammacorrection(Rp) 412 | R = real(((Rp + 0.099)/1.099).^(1/0.45)); 413 | i = (R < 0.018); 414 | R(i) = Rp(i)/4.5138; 415 | return; 416 | 417 | 418 | function fY = f(Y) 419 | fY = real(Y.^(1/3)); 420 | i = (Y < 0.008856); 421 | fY(i) = Y(i)*(841/108) + (4/29); 422 | return; 423 | 424 | 425 | function Y = invf(fY) 426 | Y = fY.^3; 427 | i = (Y < 0.008856); 428 | Y(i) = (fY(i) - 4/29)*(108/841); 429 | return; 430 | -------------------------------------------------------------------------------- /util/eachfile.m: -------------------------------------------------------------------------------- 1 | function results = eachfile(filenames, func, varargin) 2 | %EACHFILE Execure function for each specified file. 3 | % results = eachfile(filenames, func, params) 4 | % is same as: 5 | % for-loop: results{n} = func(file{n}, params{:}) 6 | % if no func is given, then output column filenames. 7 | % 8 | % Example 9 | % 10 | % % Display files in a folder 11 | % files = '%datasets/SLD2011\dataset3\sequence\01*.jpg'; 12 | % eachfile(files); %eachfile(files,@disp); 13 | % 14 | % % Get file names 15 | % filename = eachfile(files); 16 | % montage(filename(1:2:end)); 17 | % 18 | % % Display pictures in a folder 19 | % eachfile(files,@imshow); 20 | % 21 | % % Snapshot pictures. 22 | % images = eachfile(files,@imread); 23 | % montage(cat(4,images{:})); 24 | % 25 | % % Cmd-like usage 26 | % eachfile *.png @delete 27 | % 28 | % See more https://github.com/baidut/OpenVehicleVision/issues/46 29 | % LOG 2016-08-20 add linux support 30 | 31 | % check inputs 32 | validateattributes(filenames,{'char', 'cell'},{'nonempty'}); 33 | if nargin < 2 34 | func = @(x)x; 35 | end 36 | 37 | % validateattributes(func,{'function_handle'},{'nonempty'}); 38 | switch class(func) 39 | case 'function_handle' 40 | case 'char' 41 | func = str2func(func); 42 | otherwise 43 | error('unkown input types'); 44 | end 45 | 46 | 47 | % eachfile('peppers.png'); 48 | if ischar(filenames) && ~ismember('*', filenames) && isempty(fileparts(filenames)) 49 | results = {func(which(filenames))}; 50 | return; 51 | end 52 | 53 | 54 | %% 55 | % See doc dir 56 | % To exclude invalid entries returned by the dir command, use the cellfun function. 57 | % MyFolderInfo = dir; 58 | % MyFolderInfo = MyFolderInfo(~cellfun('isempty', {MyFolderInfo.date})); 59 | 60 | if iscell(filenames) 61 | files = filenames; 62 | nameFolds = filenames; 63 | else 64 | % gen full path 65 | if 0 ~= exist('GetFullPath','file') % 2 or 3 66 | filenames = GetFullPath(filenames); 67 | end 68 | 69 | % get files 70 | if ~isdir(filenames) 71 | path = fileparts(filenames); 72 | else 73 | path = (filenames); 74 | end 75 | 76 | d = dir(fullfile(filenames)); 77 | 78 | d = d(~cellfun(@(x)x, {d.isdir})); % exclude subfolder and <.> <..> 79 | d = d(~cellfun(@(x)x(1)=='.', {d.name})); % exclude mac files '._xxx.jpg' 80 | d = d(~cellfun('isempty', {d.date})); % exclude invalid entries 81 | 82 | nameFolds = {d.name}'; 83 | 84 | % if isempty(ext) && isempty(name) % 1: <.> 2: <..> 85 | % nameFolds = nameFolds(3:end); 86 | % end 87 | if ~isempty(path) 88 | files = strcat([path filesep],nameFolds); 89 | else 90 | files = nameFolds; 91 | end 92 | end 93 | 94 | % exec function 95 | f = @(x)func(x,varargin{:}); 96 | 97 | if nargout == 0 98 | %cellfun(f, files, 'UniformOutput',false); 99 | for n = 1:numel(files) 100 | fprintf('%3d %% <%s> ... \n', uint8(100*n/numel(files)), nameFolds{n}); 101 | f(files{n}); 102 | disp ok 103 | end 104 | else 105 | %cellfun is slower than for-loop 106 | %slower: results = cellfun(f, files, 'UniformOutput',false); 107 | %faster: for-loop 108 | results = cell(numel(files), 1); 109 | for n = 1:numel(files) 110 | results{n} = f(files{n}); 111 | end 112 | end -------------------------------------------------------------------------------- /util/ezFig.m: -------------------------------------------------------------------------------- 1 | function h = ezFig(varargin) 2 | %ezFig help you show figure with images easily 3 | 4 | if nargin == 0 5 | showhelp 6 | % ezFig('peppers.png', 'cameraman.tif', 'football.jpg'); 7 | disp 'Example 1 - command-like usage. Press any key to start.' 8 | pause; 9 | I = imread('football.jpg'); 10 | ezFig ''peppers.png'' [] cameraman.tif 'football.jpg' I I./2 11 | 12 | disp 'Example 2 - function-like usage. Press any key to start.' 13 | pause 14 | ezFig('peppers.png', ezAxes('cameraman.tif', 'football.jpg')); 15 | 16 | disp 'Example 3 - layout configuration. Press any key to start.' 17 | pause; 18 | cfg.layout = [1 1 0 19 | 2 2 3 20 | 4 4 4]; 21 | ezFig(cfg, 'peppers.png', 'cameraman.tif', 'pout.tif', 'football.jpg'); 22 | return; 23 | end 24 | 25 | names = arrayfun(@inputname,1:numel(varargin),'uniformoutput',false); 26 | args = struct('name',names,'value', varargin); 27 | 28 | %% cfg 29 | 30 | if isstruct(varargin{1}) 31 | cfg = varargin{1}; 32 | args = args(2:end); 33 | else 34 | cfg = struct; 35 | end 36 | 37 | default.interpreter = globalVar('ezFig_interpreter', 'tex'); 38 | default.titleFormat = globalVar('ezFig_titleFormat', '%name'); % %name\color{blue}<%class> 39 | cfg = loaddefault(cfg, default); 40 | 41 | if isfield(cfg, 'layout') 42 | mat = cfg.layout; 43 | [r, c] = size(mat); 44 | mat = mat'; mat = mat(:); % convert to a vector 45 | else 46 | narg = numel(args); 47 | r = floor(sqrt(narg)); 48 | c = ceil(narg/r); 49 | end 50 | 51 | %% main 52 | n = 0; 53 | % h = gcf; 54 | h = figure; % default: new figure 55 | for arg = args, n = n + 1; 56 | if isempty(arg.value) || strcmp(arg.value, '[]'); continue; end 57 | 58 | % first setup new subplot to allow some function eg. hist 59 | if isfield(cfg, 'layout') 60 | pStart = find( mat==n, 1, 'first'); 61 | pEnd = find( mat==n, 1, 'last'); 62 | subplot(r, c, [pStart pEnd]); 63 | else 64 | subplot(r, c, n); 65 | end 66 | 67 | if isempty(arg.name) 68 | if ischar(arg.value) % expression or 'image.jpg' 69 | arg.name = arg.value; 70 | try 71 | %if 2 == exist(arg.value, 'file') % image file 72 | arg.value = imread(arg.name); % not necessary 73 | %end 74 | catch % expression 75 | if arg.value(1) == '(' && arg.value(end) == ')' 76 | evalin('caller', arg.value); 77 | else 78 | arg.value = evalin('caller', arg.value); 79 | end 80 | end 81 | end 82 | %TODO: if isobject try char(object) 83 | end 84 | 85 | % arg.value can be: image, imagefilename, object 86 | try 87 | %if ~isvector(arg.value) % imhist 88 | imshow(arg.value); 89 | %end 90 | catch % more robust % allow histogram 91 | end 92 | %title(arg.name); 93 | if ~strcmp(cfg.interpreter, 'none') 94 | arg.name = strrep(arg.name, '_', '\_'); 95 | end 96 | 97 | text = strrep(cfg.titleFormat, '%name', arg.name); 98 | text = strrep(text, '%class', class(arg.value)); 99 | title(text, 'Interpreter', cfg.interpreter); 100 | end 101 | 102 | if nargout == 0, clear h; end 103 | 104 | %TODO: adaptive layout according to image size 105 | % 106 | % f = Fig(args); h = f.handle; 107 | % 108 | % if isstruct(cfg) 109 | % if isfield(cfg, 'layout') 110 | % f.setLayout(cfg.layout); 111 | % end 112 | % end 113 | % 114 | % disp(f); 115 | -------------------------------------------------------------------------------- /util/ezPath.m: -------------------------------------------------------------------------------- 1 | function oldPath = ezPath(varargin) 2 | %EZPATH add path more easier. 3 | %USAGE 4 | % ezPath folder1 folder2 ... 5 | 6 | %SEE ALSO addpath rmpath savepath 7 | % 8 | %COPYRIGHT Zhenqiang Ying 9 | 10 | oldPath = path; 11 | 12 | cfg.SavePath = true; 13 | cfg.FullPath = true; 14 | 15 | if isstruct(varargin{1}) 16 | cfg = loaddefault(varargin{1}, cfg, true); % time-consuming 17 | varargin = varargin(2:end); 18 | end 19 | 20 | inputPath = strjoin(varargin, ';'); 21 | pathList = strsplit(inputPath, ';'); 22 | 23 | try 24 | caller = callerFile; 25 | defaultPath = caller.path; 26 | catch 27 | defaultPath = cd; 28 | end 29 | 30 | if cfg.FullPath 31 | for pathStr = pathList 32 | [p, func] = strsplit(pathStr{1}, '>');p = p{1}; 33 | if ~ismember(':', p) % is not fullpath 34 | p = [defaultPath filesep p]; 35 | end 36 | if isempty(func) || ~exist(func{1}, 'file') 37 | if p(end) == '*' 38 | genpath(p(1:end-1)) 39 | addpath(genpath(p(1:end-1))); 40 | else 41 | addpath(p); 42 | end 43 | %this.path{end+1} = p; 44 | end 45 | end 46 | else 47 | addpath(inputPath); 48 | end 49 | 50 | if cfg.SavePath 51 | savepath 52 | end -------------------------------------------------------------------------------- /util/globalVar.m: -------------------------------------------------------------------------------- 1 | function value = globalVar(key, value) 2 | 3 | % globalVar(key, initValue); 4 | % v = globalVar(key); 5 | % v = globalVar(key, defaultValue); 6 | % 7 | % globalVar a 100 8 | % b = globalVar('a') 9 | % b = globalVar('b') 10 | % b = globalVar('b','hello') 11 | 12 | global globalVar__; 13 | 14 | if isempty(globalVar__) || ~isfield(globalVar__, key) || isempty(globalVar__.(key)) 15 | % init value 16 | if ~exist('value', 'var') 17 | value = []; 18 | end 19 | globalVar__.(key) = value; % init done 20 | else 21 | if nargout == 0 22 | % set value 23 | globalVar__.(key) = value; 24 | else 25 | % get value 26 | value = globalVar__.(key); 27 | end 28 | end -------------------------------------------------------------------------------- /util/imload.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baidut/BIMEF/509f0411a57111859e1f767b4d91b33631fb2e7a/util/imload.m -------------------------------------------------------------------------------- /util/install.m: -------------------------------------------------------------------------------- 1 | function install(your_dir) 2 | 3 | if nargin == 0 4 | your_dir = 'E:\shared\Matlab'; % '\\-BAIDUT\shared\Matlab'; % 5 | end 6 | 7 | % install datasets, includes 8 | if 7~=exist('#dataset','dir') 9 | disp 'Installing ...' 10 | %dir = callerFile('path'); 11 | runasadmin(sprintf('mklink /D "#dataset" "%s/#dataset"\nmklink /D "#include" "%s/#include"', your_dir, your_dir)); 12 | disp ok 13 | else 14 | disp 'Already Installed' 15 | end 16 | 17 | end 18 | 19 | % use %% instead of % since % is special char in batch file 20 | % mklink /D ".\%%datasets" E:\Sync\my\project\datasets -------------------------------------------------------------------------------- /util/loaddefault.m: -------------------------------------------------------------------------------- 1 | function [cfg, newCfg ] = loaddefault(cfg, defaultCfg, appendStruct) 2 | %loaddefault will be removed, use ezInput instead. 3 | % 4 | % keepStruct: recursive retain the struct 5 | %LOAD DEFAULT CONFIG 6 | % defaultCfg = struct('a',1,'b',2,'c',3); 7 | % cfg = struct('b',0); 8 | % [cfg, newCfg ] = loaddefault(cfg, defaultCfg) 9 | % 10 | % cfg = struct('b',0, 'd', 1, 'e', 2); % unknown paramvalue 11 | % [cfg, newCfg ] = loaddefault(cfg, defaultCfg) 12 | 13 | % existingfields = isfield(cfg,fieldnames(defaultCfg)); 14 | %if cfg 15 | if nargin < 3 16 | appendStruct = false; 17 | end 18 | 19 | if iscell(cfg) 20 | cfg = struct(cfg{:}); 21 | end 22 | if iscell(defaultCfg) 23 | defaultCfg = struct(defaultCfg{:}); 24 | end 25 | 26 | newCfg = cfg; 27 | 28 | % both are struct 29 | 30 | % defaultCfg --> cfg 31 | fields = fieldnames(defaultCfg); 32 | nfields = numel(fields); 33 | for n = 1:nfields 34 | if ~isfield(cfg,fields(n)) 35 | cfg.(fields{n}) = defaultCfg.(fields{n}); 36 | else 37 | if appendStruct && isstruct(defaultCfg.(fields{n})) 38 | cfg.(fields{n}) = loaddefault(cfg.(fields{n}), ... 39 | defaultCfg.(fields{n}) ); 40 | end 41 | newCfg = rmfield(newCfg, fields(n)); 42 | end 43 | end 44 | 45 | % newCfg --> cell 46 | if nargout > 1 47 | newCfg = convertToCell(newCfg); 48 | end 49 | end 50 | 51 | function c = convertToCell(s) 52 | twoRow = [fieldnames(s), struct2cell(s)]'; 53 | c = twoRow(:)'; 54 | end 55 | 56 | % scatter3_args = rmfield(param, default(1:2:end)); 57 | % -------------------------------------------------------------------------------- /util/rename.m: -------------------------------------------------------------------------------- 1 | function newName = rename(oldName , format, varargin) 2 | % rename(fileTest, '%s/--DRIM.png', dirDrimResult) 3 | 4 | [path, name, ext] = fileparts(oldName); 5 | if numel(varargin) ~= 0 6 | format = sprintf(format, varargin{:}); 7 | end 8 | newName = strrep(format, '', path); 9 | newName = strrep(newName, '', name); 10 | newName = strrep(newName, '', ext(2:end)); % no . mark 11 | end --------------------------------------------------------------------------------