imadjust函數分析一


聲明:本文涉及到的行數皆指本文提供的附件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
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圖像 第三維的維數為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
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) ~= 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
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));
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
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)
else
    iptcheckinput(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 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
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 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
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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM