声明:本文涉及到的行数皆指本文提供的附件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 % 图像矩阵维数不为2
eid = sprintf('Images:%s:oneArgOnlyGrayscale',mfilename);
error(eid, ...
'IMADJUST(I) is only supported for 2-D grayscale images.');
end
% 检验图像矩阵数据类型是否double、uint8、uint16、int16和single
iptcheckinput(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 % 如果输入参数个数不为1
if 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};
end elseif 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};
end
if ~isempty(varargin{3})
lowhigh_out = varargin{3};
end
else %如果输入参数个数为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};
end
if ~isempty(varargin{3})
lowhigh_out = varargin{3};
end
if ~isempty(varargin{4})
gamma = varargin{4};
end
end
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]');
end

这个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图像 第三维的维数为3
iptcheckinput(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]).
% 输入图像矩阵维数中列数不为3
iptcheckinput(img, {'double' 'uint8' 'uint16' 'int16' 'single'}, ...
{'2d'}, mfilename, 'I', 1);
imageType = 'intensity'; else
%Colormap
iptcheckmap(img,mfilename,'MAP',1);
imageType = 'indexed';
end

图像类型分为三种,第一种是'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) ~= 2
eid = 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
else
if ~(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

前面判定图像为'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));
end if 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

该函数首先检查了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)
else
iptcheckinput(gamma,{'double'},{'nonnegative','2d'},...
mfilename, 'GAMMA', 4)
if numel(gamma) == 1,
gamma = gamma*ones(1,3);
end
end

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

3.执行变换(行104)

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

首先判断如果图像矩阵数据不为浮点数(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 lut switch imgClass
case 'uint8'
lutLength = 256;
conversionFcn = @im2uint8;
case 'uint16'
lutLength = 65536;
conversionFcn = @im2uint16;
case 'int16'
lutLength = 65536;
conversionFcn = @im2int16;
otherwise
eid = sprintf('Images:%s:internalError',mfilename);
msg = 'Internal error: invalid class type.';
error(eid,'%s',msg);
end

关键部分

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代码

 function out = imadjust(varargin)
%IMADJUST Adjust image intensity values or colormap.
% J = IMADJUST(I) maps the values in intensity image I to new values in J
% such that 1% of data is saturated at low and high intensities of I.
% This increases the contrast of the output image J.
%
% J = IMADJUST(I,[LOW_IN; HIGH_IN],[LOW_OUT; HIGH_OUT]) maps the values
% in intensity image I to new values in J such that values between LOW_IN
% and HIGH_IN map to values between LOW_OUT and HIGH_OUT. Values below
% LOW_IN and above HIGH_IN are clipped; that is, values below LOW_IN map
% to LOW_OUT, and those above HIGH_IN map to HIGH_OUT. You can use an
% empty matrix ([]) for [LOW_IN; HIGH_IN] or for [LOW_OUT; HIGH_OUT] to
% specify the default of [0 1]. If you omit the argument, [LOW_OUT;
% HIGH_OUT] defaults to [0 1].
%
% J = IMADJUST(I,[LOW_IN; HIGH_IN],[LOW_OUT; HIGH_OUT],GAMMA) maps the
% values of I to new values in J as described in the previous syntax.
% GAMMA specifies the shape of the curve describing the relationship
% between the values in I and J. If GAMMA is less than 1, the mapping is
% weighted toward higher (brighter) output values. If GAMMA is greater
% than 1, the mapping is weighted toward lower (darker) output values. If
% you omit the argument, GAMMA defaults to 1 (linear mapping).
%
% NEWMAP = IMADJUST(MAP,[LOW_IN; HIGH_IN],[LOW_OUT; HIGH_OUT],GAMMA)
% transforms the colormap associated with an indexed image. If LOW_IN,
% HIGH_IN, LOW_OUT, HIGH_OUT, and GAMMA are scalars, then the same
% mapping applies to red, green and blue components. Unique mappings for
% each color component are possible when: LOW_IN and HIGH_IN are both
% 1-by-3 vectors, LOW_OUT and HIGH_OUT are both 1-by-3 vectors, OR GAMMA
% is a 1-by-3 vector. The rescaled colormap, NEWMAP, is the same size as
% MAP.
%
% RGB2 = IMADJUST(RGB1,...) performs the adjustment on each image plane
% (red, green, and blue) of the RGB image RGB1. As with the colormap
% adjustment, you can apply unique mappings to each plane.
%
% Note that IMADJUST(I) is equivalent to IMADJUST(I,STRETCHLIM(I)).
%
% Note that if HIGH_OUT < LOW_OUT, the output image is reversed, as in a
% photographic negative.
%
% Class Support
% -------------
% For syntaxes that include an input image (rather than a colormap), the
% input image can be uint8, uint16, int16, double, or single. The output
% image has the same class as the input image. For syntaxes that include
% a colormap, the input and output colormaps are double.
%
% Examples
% --------
% I = imread('pout.tif');
% J = imadjust(I);
% figure, imshow(I), figure, imshow(J)
%
% K = imadjust(I,[0.3 0.7],[]);
% figure, imshow(K)
%
% RGB1 = imread('football.jpg');
% RGB2 = imadjust(RGB1,[.2 .3 0; .6 .7 1],[]);
% figure, imshow(RGB1), figure, imshow(RGB2)
%
% See also BRIGHTEN, DECORRSTRETCH, HISTEQ, IMCONTRAST, STRETCHLIM. % Copyright 1992-2007 The MathWorks, Inc.
% $Revision: 5.26.4.9 $ $Date: 2007/12/10 21:37:18 $ % Input-output specs
% ------------------
% I,J real, full matrix, 2-D
% uint8, uint16, double, single, int16
%
% RGB1,RGB2 real, full matrix
% M-by-N-by-3
% uint8, uint16, double, single, int16
%
% MAP,NEWMAP real, full matrix
% M-by-3
% double with values in the range [0,1].
%
% [LOW_IN; HIGH_IN] double, real, full matrix
% For I, size can only be 2 elements.
% For RGB or MAP, size can be 2 elements OR
% 2-by-3 matrix.
% LOW_IN < HIGH_IN
%
% [LOW_OUT; HIGH_OUT] Same size restrictions as [LOW_IN; HIGH_IN]
% LOW_OUT can be less than HIGH_OUT
%
% LOW_IN, HIGH_IN, LOW_OUT, HIGH_OUT all must be in the range [0,1];
%
% GAMMA real, double, nonnegative
% scalar for I
% scalar or 1-by-3 vector for RGB and MAP %Parse inputs and initialize variables
[img,imageType,lowIn,highIn,lowOut,highOut,gamma] = ...
parseInputs(varargin{:}); validateLowHigh(lowIn,highIn,lowOut,highOut);
gamma = validateGamma(gamma,imageType); if ~isfloat(img) && numel(img) > 65536
% integer data type image with more than 65536 elements
out = adjustWithLUT(img,lowIn,highIn,lowOut,highOut,gamma); else
classin = class(img);
classChanged = false;
if ~isa(img,'double') %如果图像矩阵数据类型不为double, 图像矩阵数据范围转为[0,1]
classChanged = true;
img = im2double(img);
end if strcmp(imageType, 'intensity')
out = adjustGrayscaleImage(img,lowIn,highIn,lowOut,highOut,gamma);
elseif strcmp(imageType, 'indexed')
out = adjustColormap(img,lowIn,highIn,lowOut,highOut,gamma);
else
out = adjustTruecolorImage(img,lowIn,highIn,lowOut,highOut,gamma);
end if classChanged
out = changeclass(classin,out);
end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function out = adjustWithLUT(img,lowIn,highIn,lowOut,highOut,gamma) imgClass = class(img);
out = zeros(size(img),imgClass); %initialize for lut switch imgClass
case 'uint8'
lutLength = 256;
conversionFcn = @im2uint8;
case 'uint16'
lutLength = 65536;
conversionFcn = @im2uint16;
case 'int16'
lutLength = 65536;
conversionFcn = @im2int16;
otherwise
eid = sprintf('Images:%s:internalError',mfilename);
msg = 'Internal error: invalid class type.';
error(eid,'%s',msg);
end 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 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function out = adjustColormap(cmap,lIn,hIn,lOut,hOut,g) % expansion factor that can expand a 1-by-3 range to the size of cmap.
expansionFactor = ones(size(cmap,1), 1);
out = adjustArray(cmap, lIn, hIn, lOut, hOut, g, expansionFactor); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function out = adjustGrayscaleImage(img,lIn,hIn,lOut,hOut,g) expansionFactor = 1;
out = adjustArray(img, lIn, hIn, lOut, hOut, g, expansionFactor); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function out = adjustTruecolorImage(rgb,lIn,hIn,lOut,hOut,g) out = zeros(size(rgb), class(rgb));
expansionFactor = 1;
for p = 1 : 3
out(:,:,p) = adjustArray(rgb(:,:,p), lIn(p),hIn(p), lOut(p), ...
hOut(p), g(p), expansionFactor);
end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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,:); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 参数获取
function [img,imageType,low_in,high_in,low_out,high_out,gamma] = ...
parseInputs(varargin) iptchecknargin(1,4,nargin,mfilename); % 输入参数个数在1-4个
img = varargin{1}; % img保存图像矩阵 % Default values (默认值)
lowhigh_in = [0; 1];
lowhigh_out = [0; 1];
gamma = 1; if nargin == 1 %如果输入参数个数为1
% IMADJUST(I)
if ndims(img) ~= 2 % 图像矩阵维数不为2
eid = sprintf('Images:%s:oneArgOnlyGrayscale',mfilename);
error(eid, ...
'IMADJUST(I) is only supported for 2-D grayscale images.');
end
% 检验图像矩阵数据类型是否double、uint8、uint16、int16和single
iptcheckinput(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 % 如果输入参数个数不为1
if 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};
end elseif 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};
end
if ~isempty(varargin{3})
lowhigh_out = varargin{3};
end
else %如果输入参数个数为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};
end
if ~isempty(varargin{3})
lowhigh_out = varargin{3};
end
if ~isempty(varargin{4})
gamma = varargin{4};
end
end
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]');
end [low_in high_in] = splitRange(lowhigh_in, imageType);
[low_out high_out] = splitRange(lowhigh_out, imageType); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function imageType = findImageType(img, lowhigh_in, lowhigh_out) if (ndims(img)==3 && size(img,3)==3)
% RGB image
% RGB图像 第三维的维数为3
iptcheckinput(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]).
% 输入图像矩阵维数中列数不为3
iptcheckinput(img, {'double' 'uint8' 'uint16' 'int16' 'single'}, ...
{'2d'}, mfilename, 'I', 1);
imageType = 'intensity'; else
%Colormap
iptcheckmap(img,mfilename,'MAP',1);
imageType = 'indexed';
end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function checkRange(range, imageType, argumentPosition, variableName) if strcmp(imageType, 'intensity')
if numel(range) ~= 2
eid = 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
else
if ~(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 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [rangeMin rangeMax] = splitRange(range, imageType) if numel(range) == 2
if strcmp(imageType, 'intensity')
rangeMin = range(1);
rangeMax = range(2);
else
% Create triples for RGB image or Colormap
rangeMin = range(1) * ones(1,3);
rangeMax = range(2) * ones(1,3);
end
else
% range is a 2 by 3 array
rangeMin = range(1,:);
rangeMax = range(2,:);
end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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));
end if 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 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function isInvalid = isInvalidRange(range) isInvalid = min(range) < 0 || max(range) > 1; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function gamma = validateGamma(gamma,image_type) if strcmp(image_type,'intensity')
iptcheckinput(gamma,{'double'},{'scalar', 'nonnegative'}, ...
mfilename, 'GAMMA', 4)
else
iptcheckinput(gamma,{'double'},{'nonnegative','2d'},...
mfilename, 'GAMMA', 4)
if numel(gamma) == 1,
gamma = gamma*ones(1,3);
end
end

imadjust函数分析一的更多相关文章

  1. split(),preg_split()与explode()函数分析与介

    split(),preg_split()与explode()函数分析与介 发布时间:2013-06-01 18:32:45   来源:尔玉毕业设计   评论:0 点击:965 split()函数可以实 ...

  2. string函数分析

    string函数分析string函数包含在string.c文件中,经常被C文件使用.1. strcpy函数原型: char* strcpy(char* str1,char* str2);函数功能: 把 ...

  3. start_amboot()函数分析

    一.整体流程 start_amboot()函数是执行完start.S汇编文件后第一个C语言函数,完成的功能自然还是初始化的工作 . 1.全局变量指针r8设定,以及全局变量区清零 2.执行一些类初始化函 ...

  4. uboot的jumptable_init函数分析

    一.函数说明 函数功能:安装系统函数指针 函数位置:common/exports.c 二.函数分析 void jumptable_init (void) { int i; gd->jt = (v ...

  5. Linux-0.11内核源代码分析系列:内存管理get_free_page()函数分析

    Linux-0.11内存管理模块是源码中比較难以理解的部分,如今把笔者个人的理解发表 先发Linux-0.11内核内存管理get_free_page()函数分析 有时间再写其它函数或者文件的:) /* ...

  6. 31.QPainter-rotate()函数分析-文字旋转不倾斜,图片旋转实现等待

    在上章和上上上章: 28.QT-QPainter介绍 30.QT-渐变之QLinearGradient. QConicalGradient.QRadialGradient 学习了QPainter基础绘 ...

  7. 如何验证一个地址可否使用—— MmIsAddressValid函数分析

    又是一篇内核函数分析的博文,我个人觉得Windows的内核是最好的老师,当你想实现一个功能之前可以看看Windows内核是怎么做的,说不定就有灵感呢:) 首先看下官方的注释说明: /*++ Routi ...

  8. STM32F10X固件库函数——串口清状态位函数分析

    STM32F10X固件库函数——串口清状态位函数分析 最近在测试串口热插拔功能的时候,意外发现STM32F10X的串口库函数中,清理串口状态位函数稍稍有点不解.下面是改函数的源码: /******** ...

  9. 常用string函数分析

    string函数分析string函数包含在string.c文件中,经常被C文件使用.1. strcpy函数原型: char* strcpy(char* str1,char* str2);函数功能: 把 ...

随机推荐

  1. sql 字段先计算后再拿比对的字段进行比对 效率提升100倍

    关于日期索引的使用,不要计算后再对比,否则使用不了索引例如:以下执行不了索引,耗时很大 dywl=# explain analyze SELECT car_bill.billno,car_bill.b ...

  2. js兼容性 - 动态删除script标签后 ,定义的函数是否执行

    hello.js function hello(){ alert('hello'); } hello.html <!DOCTYPE html> <html lang="en ...

  3. destoon实现商铺管理主页设置增加新菜单的方法

    1.打开/lang/zh-cn/home.inc.php,找到9,10行替换如下: $HMENU = $DMENU = array('公司介绍', '供应产品', '采购清单', '新闻中心', '荣 ...

  4. 换行word-wrap与word-break兼容IE和FIREFOX -----设计师零张

    word-wrap是控制换行的.使用break-word时,是将强制换行.中文没有任何问题,英文语句也没问题.但是对于长串的英文,就不起作用.word-break是控制是否断词的.normal是默认情 ...

  5. 【好程序员笔记分享】——Cocoapods集成

    -iOS培训,iOS学习-------型技术博客.期待与您交流!------------ Xcode集成POD教程 准备工作: 首先我们要在我们的电脑中安装POD,进入命令行,输入如下指令 sudo  ...

  6. 关于android:focusable属性

    http://www.cnblogs.com/Gaojiecai/archive/2013/06/18/3142783.html Android属性 android:focusableInTouchM ...

  7. Codeforces 509F Progress Monitoring

    http://codeforces.com/problemset/problem/509/F 题目大意:给出一个遍历树的程序的输出的遍历顺序b序列,问可能的树的形态有多少种. 思路:记忆化搜索 其中我 ...

  8. KEILC51可重入函数及模拟栈浅析

    MARK:文章中的红色部分是个人的理解. KEILC51可重入函数及模拟栈浅析 关键字:keilc51,模拟堆栈,可重入函数调用,参数传递,C?XBP,C?ADDXBP 摘要:本文较详细的介绍了kei ...

  9. 【转】Java基本数据类型

    原文网址:http://blog.csdn.net/bingduanlbd/article/details/27790287 Java语言是静态类型的(statical typed),也就是说所有变量 ...

  10. soj 1698 Hungry Cow_三角函数

    题目链接 题意:有只牛要吃草,现在有个墙挡着,给你绑着牛的绳的长度,墙的长度,绳原点到墙的距离,问牛能在多大的面积里吃草 思路:分为四种情况,详情请看书.被dp卡着这题没做成 #include < ...