声明:本文涉及到的行数皆指本文提供的附件imadjust.m的代码中行数

本文只讨论imadjust函数是一种用法,即

J = IMADJUST(I,[LOW_IN; HIGH_IN],[LOW_OUT; HIGH_OUT],GAMMA)

处理效果如下图

图像矩阵I要求数据类型uint8、uint16、double、single和int16,[LOW_IN HIGH_IN]和[LOW_OUT HIGH_OUT] 要求范围都要在[0 1]区间中,不然会出问题。

1.函数首先获得输入参数(行97)

[img,imageType,lowIn,highIn,lowOut,highOut,gamma] = ...parseInputs(varargin{:});

根据用法

J = IMADJUST(I,[LOW_IN; HIGH_IN],[LOW_OUT; HIGH_OUT],GAMMA)

其中I赋值给img,imgeType后续有说明,LOW_IN赋值给lowIn,HIGH_IN赋值给highIn,LOW_OUT赋值给lowOUt,HIGH_OUT赋值给highOut,GAMMA赋值给gamma。

进入子函数paraseInputs(行196)

函数会判断输出参数个数多少,本文主要讨论参数个数>1,从行231看起

if nargin == 1    %如果输入参数个数为1% IMADJUST(I)if ndims(img) ~= 2        % 图像矩阵维数不为2eid = sprintf('Images:%s:oneArgOnlyGrayscale',mfilename);error(eid, ...'IMADJUST(I) is only supported for 2-D grayscale images.');end% 检验图像矩阵数据类型是否double、uint8、uint16、int16和singleiptcheckinput(img, {'double' 'uint8' 'uint16' 'int16' 'single'}, ...{'2d'}, mfilename, 'I', 1);% If a user passes in a m-by-3 double array, assume it is an intensity% image (there is really no way to tell).imageType = 'intensity';% Turn off warning 'Images:imhistc:inputHasNans' before calling STRETCHLIM and% restore afterwards. STRETCHLIM calls IMHIST/IMHISTC and the warning confuses% a user who calls IMADJUST with NaNs.s = warning('off','Images:imhistc:inputHasNaNs');lowhigh_in = stretchlim(img);warning(s) else    % 如果输入参数个数不为1if nargin == 2        %如果输入参数个数为2% IMADJUST(I,[LOW_IN HIGH_IN])% IMADJUST(MAP,[LOW_IN HIGH_IN])% IMADJUST(RGB,[LOW_IN HIGH_IN])if ~isempty(varargin{2})    %如果输入参数2的数组不为空lowhigh_in = varargin{2};endelseif nargin == 3    %如果输入参数个数为3% IMADJUST(I,[LOW_IN HIGH_IN],[LOW_OUT HIGH_OUT])% IMADJUST(MAP,[LOW_IN HIGH_IN],[LOW_OUT HIGH_OUT])% IMADJUST(RGB,[LOW_IN HIGH_IN],[LOW_OUT HIGH_OUT])if ~isempty(varargin{2})lowhigh_in = varargin{2};endif ~isempty(varargin{3})lowhigh_out = varargin{3};endelse    %如果输入参数个数为4% IMADJUST(I,[LOW_IN HIGH_IN],[LOW_OUT HIGH_OUT],GAMMA)% IMADJUST(MAP,[LOW_IN HIGH_IN],[LOW_OUT HIGH_OUT],GAMMA)% IMADJUST(RGB,[LOW_IN HIGH_IN],[LOW_OUT HIGH_OUT],GAMMA)if ~isempty(varargin{2})lowhigh_in = varargin{2};endif ~isempty(varargin{3})lowhigh_out = varargin{3};endif ~isempty(varargin{4})gamma = varargin{4};endendimageType = findImageType(img, lowhigh_in, lowhigh_out);checkRange(lowhigh_in, imageType, 2,'[LOW_IN; HIGH_IN]');checkRange(lowhigh_out, imageType, 3,'[LOW_OUT; HIGH_OUT]');
end

View Code

这个if-else语句代码很明显看到函数输入参数[LOW_IN HIGH_IN]赋值给了lowhigh_in,参数[LOW_OUT HIGH_OUT]赋值给了lowhigh_out,而参数GAMMA赋值给了gamma,然后执行参数有效性判断。(行265)

imageType = findImageType(img, lowhigh_in, lowhigh_out);
checkRange(lowhigh_in, imageType, 2,'[LOW_IN; HIGH_IN]');
checkRange(lowhigh_out, imageType, 3,'[LOW_OUT; HIGH_OUT]');

第一个语句主要用于根据输入图像矩阵判断图像类型,第二个和第三个主要是判断[LOW_IN HIGH_IN]和[LOW_OUT HIGH_OUT]的正确性。

(1)findImageType函数如下(行274)

function imageType = findImageType(img, lowhigh_in, lowhigh_out)if (ndims(img)==3 && size(img,3)==3)% RGB image% RGB图像 第三维的维数为3iptcheckinput(img, {'double' 'uint8' 'uint16' 'int16' 'single'}, ...{}, mfilename, 'RGB1', 1);imageType = 'truecolor';elseif (numel(lowhigh_in) == 2 && numel(lowhigh_out) == 2) || ...size(img,2) ~= 3% Assuming that a user passed in an intensity image if lowhigh_in and% lowhigh_out are 2-element vectors, e.g., imadjust(3 column image,% [1;2], [2;3]).% 输入图像矩阵维数中列数不为3iptcheckinput(img, {'double' 'uint8' 'uint16' 'int16' 'single'}, ...{'2d'}, mfilename, 'I', 1);imageType = 'intensity';else%Colormapiptcheckmap(img,mfilename,'MAP',1);imageType = 'indexed';
end

View Code

图像类型分为三种,第一种是'truecolor'图像,第二种是'intensity',第三种为'indexed'。本文讨论的为第二种(一般情况使用的就是第二种,其他的目前没遇到,后续文章更新),即'intensity',判定第二种条件为[LOW_IN HIGH_IN]和[LOW_OUT HIGH_OUT]的元素个数为2并且输入图像矩阵列数不为3。

(2)chackRange函数如下(行300)

function checkRange(range, imageType, argumentPosition, variableName)if strcmp(imageType, 'intensity')if numel(range) ~= 2eid = sprintf('Images:%s:InputMustBe2ElVec',mfilename);error(eid, ...'Function %s expected its %s input argument, %s\n%s', ...mfilename, iptnum2ordinal(argumentPosition), variableName, ...'to be a two-element vector.');end
elseif ~(numel(range) == 2 || isequal(size(range), [2 3]))eid = sprintf('Images:%s:InputMustBe2ElVecOr2by3Matrix',mfilename);error(eid, ...'Function %s expected its %s input argument, %s\n%s', ...mfilename, iptnum2ordinal(argumentPosition), variableName, ...'to be a two-element vector or a 2-by-3 matrix.');end
end

View Code

前面判定图像为'intensity',这里主要判断[LOW_IN HIGH_IN]和[LOW_OUT HIGH_OUT]元素个数必须为2,不然报错,这里就是第一个检查,后面还有检查。

最后

[low_in high_in]   = splitRange(lowhigh_in, imageType);
[low_out high_out] = splitRange(lowhigh_out, imageType);

获取参数[low_in high_in] 和 [low_out high_out] ,然后函数返回。

2.参数检查

前面通过函数paraseInputs获取了用户输入的参数,接下来进行参数有效性检验

validateLowHigh(lowIn,highIn,lowOut,highOut);
gamma = validateGamma(gamma,imageType);

(1)函数validateLowHigh(行340)

function validateLowHigh(lowIn,highIn,lowOut,highOut)if any(lowIn >= highIn)eid = sprintf('Images:%s:lowMustBeSmallerThanHigh',mfilename);error(eid, '%s: LOW_IN must be less than HIGH_IN.',...upper(mfilename));
endif isInvalidRange(lowIn) || isInvalidRange(highIn) ...|| isInvalidRange(lowOut) || isInvalidRange(highOut)eid = sprintf('Images:%s:parametersAreOutOfRange',mfilename);error(eid, '%s: LOW_IN, HIGH_IN, LOW_OUT and HIGH_OUT %s',...upper(mfilename), 'must be in the range [0.0, 1.0].');
end

View Code

该函数首先检查了lowIn要小于highIn,但是没要求lowOut要小于highOut,因为这个函数有个运用,在于可以反转图像,即[0 1]变换到[1 0]。

然后使用函数isInvalidRange限制了输入lowIn、highIn、lowOut和highOut范围为[0 1],这就是开头所说[LOW_IN HIGH_IN]和[LOW_OUT HIGH_OUT] 要求范围都要在[0 1]区间中的出处。

(2)函数validateGamma(行362)

function gamma = validateGamma(gamma,image_type)if strcmp(image_type,'intensity')iptcheckinput(gamma,{'double'},{'scalar', 'nonnegative'}, ...mfilename, 'GAMMA', 4)
elseiptcheckinput(gamma,{'double'},{'nonnegative','2d'},...mfilename, 'GAMMA', 4)if numel(gamma) == 1,gamma = gamma*ones(1,3);end
end

View Code

前面判定图像类型为'intensity',这里判定gamma参数必须为正数。

3.执行变换(行104)

if ~isfloat(img) && numel(img) > 65536% integer data type image with more than 65536 elementsout = adjustWithLUT(img,lowIn,highIn,lowOut,highOut,gamma);elseclassin = class(img);classChanged = false;if ~isa(img,'double')    %如果图像矩阵数据类型不为double, 图像矩阵数据范围转为[0,1]classChanged = true;img = im2double(img);endif strcmp(imageType, 'intensity')out = adjustGrayscaleImage(img,lowIn,highIn,lowOut,highOut,gamma);elseif strcmp(imageType, 'indexed')out = adjustColormap(img,lowIn,highIn,lowOut,highOut,gamma);elseout = adjustTruecolorImage(img,lowIn,highIn,lowOut,highOut,gamma);endif classChangedout = changeclass(classin,out);endend

View Code

首先判断如果图像矩阵数据不为浮点数(double和single)并且矩阵元素个数>65536,则执行函数adjustWithLUT函数。

(1)adjustWithLUT函数如下

function out = adjustWithLUT(img,lowIn,highIn,lowOut,highOut,gamma)imgClass = class(img);
out = zeros(size(img),imgClass);%initialize for lutswitch imgClasscase 'uint8'lutLength = 256;conversionFcn = @im2uint8;case 'uint16'lutLength = 65536;conversionFcn = @im2uint16;case 'int16'lutLength = 65536;conversionFcn = @im2int16;otherwiseeid = sprintf('Images:%s:internalError',mfilename);msg = 'Internal error: invalid class type.';error(eid,'%s',msg);
end

View Code

关键部分

for p = 1:size(img,3)lut = linspace(0,1,lutLength);scalingFactor = 1;lut = adjustArray(lut,lowIn(p),highIn(p),lowOut(p),highOut(p), ...gamma(p),scalingFactor);lut = conversionFcn(lut);out(:,:,p) = intlut(img(:,:,p),lut);
end

首先创建一个数组作为筛选数组,不需要对图像矩阵进行变换,直接根据筛选数组的筛选图像矩阵。以下语句为灰度值归一化,将灰度归一化到[0 1]范围,这是为了后面变换方便。

lut = linspace(0,1,lutLength);

lutLength的大小为图像矩阵数据类型对应该类型的最大值,例如图像矩阵数据类型为uint8,则lutLength=256。该语句作用在于创建一个数组lut,数组储存归一化后的灰度值,每个元素分别对于相应的灰度等级。

lut = adjustArray(lut,lowIn(p),highIn(p),lowOut(p),highOut(p), ...gamma(p),scalingFactor);

对lut进行变换,变换结果如开头的图

lowIn=低输入 highIn=高输入 lowOut=低输出 highOut=高输出

由于数组lut元素范围[0 1],这是归一化数据,因此要还原对应的值

lut = conversionFcn(lut);

剩下就是筛选了

out(:,:,p) = intlut(img(:,:,p),lut);

(2)adjustArray函数(行187)

function out = adjustArray(img,lIn,hIn,lOut,hOut,g,d)%make sure img is in the range [lIn;hIn]
img(:) =  max(lIn(d,:), min(hIn(d,:),img));out = ( (img - lIn(d,:)) ./ (hIn(d,:) - lIn(d,:)) ) .^ (g(d,:));
out(:) = out .* (hOut(d,:) - lOut(d,:)) + lOut(d,:);

首先筛选掉矩阵img中小于lIn的数的数值变为lIn,大于hIn的数的数值变为hIn,筛选语句如下

img(:) =  max(lIn(d,:), min(hIn(d,:),img));

接着进行变换,令 并且d=1,则该函数处理的效果等价于:

至于为什么这样,我手写推导过程如下

表达式就是曲线AB的方程

附件:imadjust.m代码

  1 function out = imadjust(varargin)
  2 %IMADJUST Adjust image intensity values or colormap.
  3 %   J = IMADJUST(I) maps the values in intensity image I to new values in J
  4 %   such that 1% of data is saturated at low and high intensities of I.
  5 %   This increases the contrast of the output image J.
  6 %
  7 %   J = IMADJUST(I,[LOW_IN; HIGH_IN],[LOW_OUT; HIGH_OUT]) maps the values
  8 %   in intensity image I to new values in J such that values between LOW_IN
  9 %   and HIGH_IN map to values between LOW_OUT and HIGH_OUT. Values below
 10 %   LOW_IN and above HIGH_IN are clipped; that is, values below LOW_IN map
 11 %   to LOW_OUT, and those above HIGH_IN map to HIGH_OUT. You can use an
 12 %   empty matrix ([]) for [LOW_IN; HIGH_IN] or for [LOW_OUT; HIGH_OUT] to
 13 %   specify the default of [0 1]. If you omit the argument, [LOW_OUT;
 14 %   HIGH_OUT] defaults to [0 1].
 15 %
 16 %   J = IMADJUST(I,[LOW_IN; HIGH_IN],[LOW_OUT; HIGH_OUT],GAMMA) maps the
 17 %   values of I to new values in J as described in the previous syntax.
 18 %   GAMMA specifies the shape of the curve describing the relationship
 19 %   between the values in I and J. If GAMMA is less than 1, the mapping is
 20 %   weighted toward higher (brighter) output values. If GAMMA is greater
 21 %   than 1, the mapping is weighted toward lower (darker) output values. If
 22 %   you omit the argument, GAMMA defaults to 1 (linear mapping).
 23 %
 24 %   NEWMAP = IMADJUST(MAP,[LOW_IN; HIGH_IN],[LOW_OUT; HIGH_OUT],GAMMA)
 25 %   transforms the colormap associated with an indexed image. If LOW_IN,
 26 %   HIGH_IN, LOW_OUT, HIGH_OUT, and GAMMA are scalars, then the same
 27 %   mapping applies to red, green and blue components. Unique mappings for
 28 %   each color component are possible when: LOW_IN and HIGH_IN are both
 29 %   1-by-3 vectors, LOW_OUT and HIGH_OUT are both 1-by-3 vectors, OR GAMMA
 30 %   is a 1-by-3 vector. The rescaled colormap, NEWMAP, is the same size as
 31 %   MAP.
 32 %
 33 %   RGB2 = IMADJUST(RGB1,...) performs the adjustment on each image plane
 34 %   (red, green, and blue) of the RGB image RGB1. As with the colormap
 35 %   adjustment, you can apply unique mappings to each plane.
 36 %
 37 %   Note that IMADJUST(I) is equivalent to IMADJUST(I,STRETCHLIM(I)).
 38 %
 39 %   Note that if HIGH_OUT < LOW_OUT, the output image is reversed, as in a
 40 %   photographic negative.
 41 %
 42 %   Class Support
 43 %   -------------
 44 %   For syntaxes that include an input image (rather than a colormap), the
 45 %   input image can be uint8, uint16, int16, double, or single. The output
 46 %   image has the same class as the input image. For syntaxes that include
 47 %   a colormap, the input and output colormaps are double.
 48 %
 49 %   Examples
 50 %   --------
 51 %       I = imread('pout.tif');
 52 %       J = imadjust(I);
 53 %       figure, imshow(I), figure, imshow(J)
 54 %
 55 %       K = imadjust(I,[0.3 0.7],[]);
 56 %       figure, imshow(K)
 57 %
 58 %       RGB1 = imread('football.jpg');
 59 %       RGB2 = imadjust(RGB1,[.2 .3 0; .6 .7 1],[]);
 60 %       figure, imshow(RGB1), figure, imshow(RGB2)
 61 %
 62 %   See also BRIGHTEN, DECORRSTRETCH, HISTEQ, IMCONTRAST, STRETCHLIM.
 63
 64 %   Copyright 1992-2007 The MathWorks, Inc.
 65 %   $Revision: 5.26.4.9 $  $Date: 2007/12/10 21:37:18 $
 66
 67 %   Input-output specs
 68 %   ------------------
 69 %   I,J          real, full matrix, 2-D
 70 %                uint8, uint16, double, single, int16
 71 %
 72 %   RGB1,RGB2    real, full matrix
 73 %                M-by-N-by-3
 74 %                uint8, uint16, double, single, int16
 75 %
 76 %   MAP,NEWMAP   real, full matrix
 77 %                M-by-3
 78 %                double with values in the range [0,1].
 79 %
 80 %   [LOW_IN; HIGH_IN]    double, real, full matrix
 81 %                        For I, size can only be 2 elements.
 82 %                        For RGB or MAP, size can be 2 elements OR
 83 %                        2-by-3 matrix.
 84 %                        LOW_IN < HIGH_IN
 85 %
 86 %   [LOW_OUT; HIGH_OUT]  Same size restrictions as [LOW_IN; HIGH_IN]
 87 %                        LOW_OUT can be less than HIGH_OUT
 88 %
 89 %   LOW_IN, HIGH_IN, LOW_OUT, HIGH_OUT all must be in the range [0,1];
 90 %
 91 %   GAMMA         real, double, nonnegative
 92 %                 scalar for I
 93 %                 scalar or 1-by-3 vector for RGB and MAP
 94
 95
 96
 97 %Parse inputs and initialize variables
 98 [img,imageType,lowIn,highIn,lowOut,highOut,gamma] = ...
 99     parseInputs(varargin{:});
100
101 validateLowHigh(lowIn,highIn,lowOut,highOut);
102 gamma = validateGamma(gamma,imageType);
103
104 if ~isfloat(img) && numel(img) > 65536
105     % integer data type image with more than 65536 elements
106     out = adjustWithLUT(img,lowIn,highIn,lowOut,highOut,gamma);
107
108 else
109     classin = class(img);
110     classChanged = false;
111     if ~isa(img,'double')    %如果图像矩阵数据类型不为double, 图像矩阵数据范围转为[0,1]
112         classChanged = true;
113         img = im2double(img);
114     end
115
116     if strcmp(imageType, 'intensity')
117         out = adjustGrayscaleImage(img,lowIn,highIn,lowOut,highOut,gamma);
118     elseif strcmp(imageType, 'indexed')
119         out = adjustColormap(img,lowIn,highIn,lowOut,highOut,gamma);
120     else
121         out = adjustTruecolorImage(img,lowIn,highIn,lowOut,highOut,gamma);
122     end
123
124     if classChanged
125         out = changeclass(classin,out);
126     end
127
128 end
129
130 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
131 function out = adjustWithLUT(img,lowIn,highIn,lowOut,highOut,gamma)
132
133 imgClass = class(img);
134 out = zeros(size(img),imgClass);
135
136 %initialize for lut
137
138 switch imgClass
139     case 'uint8'
140         lutLength = 256;
141         conversionFcn = @im2uint8;
142     case 'uint16'
143         lutLength = 65536;
144         conversionFcn = @im2uint16;
145     case 'int16'
146         lutLength = 65536;
147         conversionFcn = @im2int16;
148     otherwise
149         eid = sprintf('Images:%s:internalError',mfilename);
150         msg = 'Internal error: invalid class type.';
151         error(eid,'%s',msg);
152 end
153
154 for p = 1:size(img,3)
155     lut = linspace(0,1,lutLength);
156     scalingFactor = 1;
157     lut = adjustArray(lut,lowIn(p),highIn(p),lowOut(p),highOut(p), ...
158         gamma(p),scalingFactor);
159     lut = conversionFcn(lut);
160     out(:,:,p) = intlut(img(:,:,p),lut);
161 end
162
163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164 function out = adjustColormap(cmap,lIn,hIn,lOut,hOut,g)
165
166 % expansion factor that can expand a 1-by-3 range to the size of cmap.
167 expansionFactor = ones(size(cmap,1), 1);
168 out = adjustArray(cmap, lIn, hIn, lOut, hOut, g, expansionFactor);
169
170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
171 function out = adjustGrayscaleImage(img,lIn,hIn,lOut,hOut,g)
172
173 expansionFactor = 1;
174 out = adjustArray(img, lIn, hIn, lOut, hOut, g, expansionFactor);
175
176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
177 function out = adjustTruecolorImage(rgb,lIn,hIn,lOut,hOut,g)
178
179 out = zeros(size(rgb), class(rgb));
180 expansionFactor = 1;
181 for p = 1 : 3
182     out(:,:,p) = adjustArray(rgb(:,:,p), lIn(p),hIn(p), lOut(p), ...
183         hOut(p), g(p), expansionFactor);
184 end
185
186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
187 function out = adjustArray(img,lIn,hIn,lOut,hOut,g,d)
188
189 %make sure img is in the range [lIn;hIn]
190 img(:) =  max(lIn(d,:), min(hIn(d,:),img));
191
192 out = ( (img - lIn(d,:)) ./ (hIn(d,:) - lIn(d,:)) ) .^ (g(d,:));
193 out(:) = out .* (hOut(d,:) - lOut(d,:)) + lOut(d,:);
194
195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
196 % 参数获取
197 function [img,imageType,low_in,high_in,low_out,high_out,gamma] = ...
198     parseInputs(varargin)
199
200 iptchecknargin(1,4,nargin,mfilename);    % 输入参数个数在1-4个
201 img = varargin{1};    % img保存图像矩阵
202
203
204 % Default values (默认值)
205 lowhigh_in  = [0; 1];
206 lowhigh_out = [0; 1];
207 gamma = 1;
208
209 if nargin == 1    %如果输入参数个数为1
210     % IMADJUST(I)
211     if ndims(img) ~= 2        % 图像矩阵维数不为2
212         eid = sprintf('Images:%s:oneArgOnlyGrayscale',mfilename);
213         error(eid, ...
214             'IMADJUST(I) is only supported for 2-D grayscale images.');
215     end
216     % 检验图像矩阵数据类型是否double、uint8、uint16、int16和single
217     iptcheckinput(img, {'double' 'uint8' 'uint16' 'int16' 'single'}, ...
218         {'2d'}, mfilename, 'I', 1);
219
220     % If a user passes in a m-by-3 double array, assume it is an intensity
221     % image (there is really no way to tell).
222     imageType = 'intensity';
223
224     % Turn off warning 'Images:imhistc:inputHasNans' before calling STRETCHLIM and
225     % restore afterwards. STRETCHLIM calls IMHIST/IMHISTC and the warning confuses
226     % a user who calls IMADJUST with NaNs.
227     s = warning('off','Images:imhistc:inputHasNaNs');
228     lowhigh_in = stretchlim(img);
229     warning(s)
230
231 else    % 如果输入参数个数不为1
232     if nargin == 2        %如果输入参数个数为2
233     % IMADJUST(I,[LOW_IN HIGH_IN])
234     % IMADJUST(MAP,[LOW_IN HIGH_IN])
235     % IMADJUST(RGB,[LOW_IN HIGH_IN])
236     if ~isempty(varargin{2})    %如果输入参数2的数组不为空
237         lowhigh_in = varargin{2};
238     end
239
240     elseif nargin == 3    %如果输入参数个数为3
241         % IMADJUST(I,[LOW_IN HIGH_IN],[LOW_OUT HIGH_OUT])
242         % IMADJUST(MAP,[LOW_IN HIGH_IN],[LOW_OUT HIGH_OUT])
243         % IMADJUST(RGB,[LOW_IN HIGH_IN],[LOW_OUT HIGH_OUT])
244
245         if ~isempty(varargin{2})
246             lowhigh_in = varargin{2};
247         end
248         if ~isempty(varargin{3})
249             lowhigh_out = varargin{3};
250         end
251     else    %如果输入参数个数为4
252         % IMADJUST(I,[LOW_IN HIGH_IN],[LOW_OUT HIGH_OUT],GAMMA)
253         % IMADJUST(MAP,[LOW_IN HIGH_IN],[LOW_OUT HIGH_OUT],GAMMA)
254         % IMADJUST(RGB,[LOW_IN HIGH_IN],[LOW_OUT HIGH_OUT],GAMMA)
255         if ~isempty(varargin{2})
256             lowhigh_in = varargin{2};
257         end
258         if ~isempty(varargin{3})
259             lowhigh_out = varargin{3};
260         end
261         if ~isempty(varargin{4})
262             gamma = varargin{4};
263         end
264     end
265     imageType = findImageType(img, lowhigh_in, lowhigh_out);
266     checkRange(lowhigh_in, imageType, 2,'[LOW_IN; HIGH_IN]');
267     checkRange(lowhigh_out, imageType, 3,'[LOW_OUT; HIGH_OUT]');
268 end
269
270 [low_in high_in]   = splitRange(lowhigh_in, imageType);
271 [low_out high_out] = splitRange(lowhigh_out, imageType);
272
273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274 function imageType = findImageType(img, lowhigh_in, lowhigh_out)
275
276 if (ndims(img)==3 && size(img,3)==3)
277     % RGB image
278     % RGB图像 第三维的维数为3
279     iptcheckinput(img, {'double' 'uint8' 'uint16' 'int16' 'single'}, ...
280         {}, mfilename, 'RGB1', 1);
281     imageType = 'truecolor';
282
283 elseif (numel(lowhigh_in) == 2 && numel(lowhigh_out) == 2) || ...
284     size(img,2) ~= 3
285     % Assuming that a user passed in an intensity image if lowhigh_in and
286     % lowhigh_out are 2-element vectors, e.g., imadjust(3 column image,
287     % [1;2], [2;3]).
288     % 输入图像矩阵维数中列数不为3
289     iptcheckinput(img, {'double' 'uint8' 'uint16' 'int16' 'single'}, ...
290         {'2d'}, mfilename, 'I', 1);
291     imageType = 'intensity';
292
293 else
294     %Colormap
295     iptcheckmap(img,mfilename,'MAP',1);
296     imageType = 'indexed';
297 end
298
299 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
300 function checkRange(range, imageType, argumentPosition, variableName)
301
302 if strcmp(imageType, 'intensity')
303     if numel(range) ~= 2
304         eid = sprintf('Images:%s:InputMustBe2ElVec',mfilename);
305         error(eid, ...
306             'Function %s expected its %s input argument, %s\n%s', ...
307             mfilename, iptnum2ordinal(argumentPosition), variableName, ...
308             'to be a two-element vector.');
309     end
310 else
311     if ~(numel(range) == 2 || isequal(size(range), [2 3]))
312         eid = sprintf('Images:%s:InputMustBe2ElVecOr2by3Matrix',mfilename);
313         error(eid, ...
314             'Function %s expected its %s input argument, %s\n%s', ...
315             mfilename, iptnum2ordinal(argumentPosition), variableName, ...
316             'to be a two-element vector or a 2-by-3 matrix.');
317     end
318 end
319
320 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
321 function [rangeMin rangeMax] = splitRange(range, imageType)
322
323 if numel(range) == 2
324     if strcmp(imageType, 'intensity')
325         rangeMin = range(1);
326         rangeMax = range(2);
327     else
328         % Create triples for RGB image or Colormap
329         rangeMin = range(1) * ones(1,3);
330         rangeMax = range(2) * ones(1,3);
331     end
332 else
333     % range is a 2 by 3 array
334     rangeMin = range(1,:);
335     rangeMax = range(2,:);
336 end
337
338
339 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340 function validateLowHigh(lowIn,highIn,lowOut,highOut)
341
342 if any(lowIn >= highIn)
343     eid = sprintf('Images:%s:lowMustBeSmallerThanHigh',mfilename);
344     error(eid, '%s: LOW_IN must be less than HIGH_IN.',...
345         upper(mfilename));
346 end
347
348 if isInvalidRange(lowIn) || isInvalidRange(highIn) ...
349         || isInvalidRange(lowOut) || isInvalidRange(highOut)
350     eid = sprintf('Images:%s:parametersAreOutOfRange',mfilename);
351     error(eid, '%s: LOW_IN, HIGH_IN, LOW_OUT and HIGH_OUT %s',...
352         upper(mfilename), 'must be in the range [0.0, 1.0].');
353 end
354
355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
356 function isInvalid = isInvalidRange(range)
357
358 isInvalid = min(range) < 0 || max(range) > 1;
359
360
361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
362 function gamma = validateGamma(gamma,image_type)
363
364 if strcmp(image_type,'intensity')
365     iptcheckinput(gamma,{'double'},{'scalar', 'nonnegative'}, ...
366         mfilename, 'GAMMA', 4)
367 else
368     iptcheckinput(gamma,{'double'},{'nonnegative','2d'},...
369         mfilename, 'GAMMA', 4)
370     if numel(gamma) == 1,
371         gamma = gamma*ones(1,3);
372     end
373 end

View Code

转载于:https://www.cnblogs.com/cpointer/p/4610755.html

imadjust函数分析一相关推荐

  1. linux C函数之strdup函数分析【转】

    本文转载自:http://blog.csdn.net/tigerjibo/article/details/12784823 linux C函数之strdup函数分析 一.函数分析 1.函数原型: [c ...

  2. 【Android 逆向】Dalvik 函数抽取加壳 ( 类加载流程分析 | Class.cpp#findClassNoInit 函数 | DexFile.cpp#dexFindClass 函数分析 )

    文章目录 前言 一.Class.cpp#dvmDefineClass 函数分析 二.Class.cpp#findClassNoInit 函数分析 三.DexFile.cpp#dexFindClass ...

  3. 【Android 逆向】Dalvik 函数抽取加壳 ( 类加载流程分析 | DexPathList#findClass 函数分析 | DexFile#loadClassBinaryName 函数 )

    文章目录 前言 一.DexPathList.java#findClass 类加载函数源码分析 二.DexFile.java#loadClassBinaryName 函数源码分析 前言 上一篇博客 [A ...

  4. 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexPathList 构造函数分析 | makeDexElements 函数分析 )

    文章目录 前言 一.DexPathList 构造函数分析 二.DexPathList.makeDexElements 函数分析 三.Element 类分析 前言 上一篇博客 [Android 逆向]整 ...

  5. 【Android 逆向】Android 逆向通用工具开发 ( adb forward 网络端口重定向命令 | PC 端逆向程序主函数分析 )

    文章目录 前言 一.adb forward 网络端口重定向命令 二.PC 端逆向程序主函数分析 前言 本篇博客重点分析 PC 端 hacktool 模块 ; 一.adb forward 网络端口重定向 ...

  6. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 注入工具的 main 函数分析 )

    文章目录 一.注入流程 二.注入工具的 main 函数分析 一.注入流程 开始分析 [Android 逆向]Android 进程注入工具开发 ( 编译注入工具 | 编译结果文件说明 | 注入过程说明 ...

  7. 继承关系中的拷贝构造函数和赋值操作重载函数分析

    文章目录 1 继承关系中的拷贝构造函数和赋值操作重载函数分析 1 继承关系中的拷贝构造函数和赋值操作重载函数分析 在继承关系中,如果子类未实现拷贝构造函数,那么在子类进行拷贝构造操作时,会直接调用父类 ...

  8. Windows事件等待学习笔记(三)—— WaitForSingleObject函数分析

    Windows事件等待学习笔记(三)-- WaitForSingleObject函数分析 要点回顾 WaitForSingleObject NtWaitForSingleObject KeWaitFo ...

  9. fprintf/fscanf函数分析

    fprintf/fscanf函数分析 宗旨:技术的学习是有限的,分享的精神是无限的. fprintf/fscanf函数与printf/scanf区别:printf/scanf专门针对标准输入输出流,f ...

最新文章

  1. zookeeper快速入门——简介
  2. php manual 反射,Laravel框架源码解析之反射的使用详解
  3. DWZ中Tree树形菜单的treeCheck如何获取返回值解决方案
  4. ubuntu 13.04 telnet 详细配置
  5. dotnet watch+vs code提升asp.net core开发效率
  6. yum安装报错Error:Nothing to do
  7. 介绍一个Office画图工具--visio
  8. 微表情识别的图片预处理(python版)
  9. 长视频请回答2020:技术如何让流媒体更“酷”?
  10. NIOS II 15:AD7606共享SDRAM
  11. 五年了还在原地踏步咋整?技术大佬给你整理了一套切实可行的方法论
  12. both methods have same erasure, yet neither overrides the other
  13. C# 查询科星继电器的输入端状态以及控制输出
  14. 卧槽,这也真的太上头了吧
  15. CAT实时监控预警系统
  16. 【附源码】计算机毕业设计SSM网上商城比价系统
  17. 数据可视化 信息可视化_可视化数据操作数据可视化与纪录片的共同点
  18. 扫盲:云计算、大数据和人工智能
  19. 不要被新媒体营造的焦虑所绑架(咪蒙类账号的不道德)
  20. squirrelSql小松鼠数据库连接工具的安装以及连接informix(系列3,squirrelSql作为客户端连接)

热门文章

  1. pythom入门_3(学习笔记)
  2. 修改input输入框样式
  3. iOS开发之如何不使用系统的密码自动填充(如何禁用系统键盘使用第三方搜狗键盘)
  4. 英特尔已不满足于只做CPU
  5. Linux 自定义网桥配置静态 IP
  6. 朱江明坚持以客户为本,不断推出新车型
  7. 婴儿床(STM32)
  8. 【python中级】苹果HEIC格式转化JPG
  9. 北漂程序员加入了”程前朋友圈“,老板圈子很重要吗?经验分享
  10. cookie各字段详解