Matlab中的stretchlim主要用于自适应找到一个分割阈值向量来改变一幅图像的对比度,其通用调用格式如下:
low_high = stretchlim(f,tol);
可得到一个灰度变换自适应最佳阈值,不用人为规定,再将其带入imadjust函数中便可实现灰度图像对比度的增加或减弱。
g=imadjust(f,low_high,[ ]);%增强对比度代码示例
一.
若tol是一个含两元素的向量,设为[low_frac
high_frac],假如我们想了解该函数如何得出的最佳灰度变换阈值,可选中该函数,右键open“stretchlim”。在此我就将结合Matlab的stretchlim函数源码分析其运算原理。
1.tol_low = tol(1);
2.tol_high = tol(2);
3.ilowhigh = zeros(2,1);%创建一个2X1大小的矩阵,用于储存后文算出的特征值
4.N=imhist(f,255);%计算输入图像f的灰度级数,即算出从1到255区间的任意一个灰度值i,在图像f中有多少个像素点的灰度值为i(uint8型共有255个灰度值,)
5.cdf =cumsum(N)/sum(N);%计算1~255每个灰度值的分布概率,该灰度值处像素点
的个数及灰度值小于该点的像素点个数之和与总像素点个数之比即为该灰度值的分布概率。例:A=[1 2
3] cumsum(A)=[13 6]
6.ilow = find(cdf> tol_low,
1,'first');%找到分布概率大于我们的输入值tol_low处最接近的灰度值,并以此作为最佳分割阈值的最小值
7.ihigh = find(cdf
>= tol_high, 1,'first');
%找到分布概率大于或等于我们的输入值tol_high处最接近的灰度值,并以此作为最佳分割阈值的最大值
8.if
ilow ==
ihigh%如果算出的最小值等于最大值的话,说明该输入图像为等灰度值图像
9.ilowhigh
= [1;255];%此时最佳分割阈值就为[0 1]
10.else
11.ilowhigh
=[ilow;ihigh];
12.end
13.end
14.low_high=
(ilowhigh -
1)/(255-1);% 由于在imadjust函数中的灰度分割阈值为0-1之间的实数,而我们在上面由分布概率得到的阈值是像素值形式,其值的范围为0-255。而之所以上下均-1,是因为阈值可以是[0
1]而matlab的灰度级数去不能为0,最小为1
注:输入图像f为uint8型的灰度图像,若对于自适应于其他格式的情况,理解上述程序后参考文章最后的源码。
二.若tol是一个标量low_frac,那么上述程序的第1、2步则为
tol_low = low_frac;
tol_high = 1-low_frac;
其余计算则与一情况完全相同
三.若调用时忽略了参数tol,则上述程序的第1、2步为
tol_low = 0.01;
tol_high = 0.99;
四.若tol=0;则直接得到输出阈值
low_high=[min(f(:)),max(f(:))]
五.自适应多种情况的源码:
function lowhigh =
The_note_of_stretchlim(varargin)
%STRETCHLIM Find limits to
contrast stretch an image.
%
LOW_HIGH = STRETCHLIM(I,TOL) returns a pair of gray values that can
be
% used
by IMADJUST to increase the contrast of an image.
%
% TOL =
[LOW_FRACT HIGH_FRACT] specifies the fraction of the image
to
%
saturate at low and high pixel values.
%
% If TOL
is a scalar, TOL = LOW_FRACT, and HIGH_FRACT = 1 -
LOW_FRACT,
% which
saturates equal fractions at low and high pixel values.
%
% If you
omit the argument, TOL defaults to [0.01 0.99], saturating
2%.
%
% If TOL
= 0, LOW_HIGH = [min(I(:)); max(I(:))].
%
%
LOW_HIGH = STRETCHLIM(RGB,TOL) returns a 2-by-3 matrix of pixel
value
% pairs
to saturate each plane of the RGB image. TOL specifies the
same
%
fractions of saturation for each plane.
%
% Class
Support
%
-------------
% The
input image can be uint8, uint16, int16, double, or single, and
must
% be
real and nonsparse. The output limits are double and have
values
%
between 0 and 1.
%
%
Note
%
----
% If TOL
is too big, such that no pixels would be left after
saturating
% low
and high pixel values, then STRETCHLIM returns [0; 1].
%
%
Example
%
-------
%
I =
imread('pout.tif');
%
J =
imadjust(I,stretchlim(I),[]);
%
figure, imshow(I), figure,
imshow(J)
%
% See
also BRIGHTEN, DECORRSTRETCH, HISTEQ, IMADJUST.
%
Copyright 1999-2014 The MathWorks, Inc.
[img,tol] = ParseInputs(varargin{:});
if isa(img,'uint8')
nbins =
256;
else
nbins =
65536;
end
tol_low = tol(1);%默认值的情况下tol = [0.01 0.99];
�fault
tol_high = tol(2);
p = size(img,3);%size(img,1)为计算行数,size(img,2)为计算列数,3就是维数
if tol_low < tol_high
ilowhigh =
zeros(2,p);%灰度图像维数为1
for i = 1:p% Find limits, one plane at a
time
N = imhist(img(:,:,i),nbins);%计算灰度级数,即算出1~255,每个灰度级刻度对应有多少个像素为该灰度级
cdf = cumsum(N)/sum(N); %cumulative distribution
function(累积分布函数,就是概率论里面的分布函数)
ilow = find(cdf > tol_low,
1, 'first');
ihigh = find(cdf >= tol_high,
1, 'first');
if ilow == ihigh
% this could happen if img is
flat当图像为单像素矩阵时概率分布为0.1和0.9是相等的
ilowhigh(:,i) = [1;nbins];%这是输出的范围就是[0 1]了
else
ilowhigh(:,i) = [ilow;ihigh];%正常非单像素值矩阵时
end
end
lowhigh = (ilowhigh
- 1)/(nbins-1);% convert to range [0 1]将输出值归一化到[0
1]
else
% tol_low
>= tol_high, this tolerance does not make sense. For
example, if
% the tolerance is .5 then no
pixels would be left after saturating
% low and high pixel values.
In all of these cases, STRETCHLIM
% returns [0; 1]. See
gecks(欺骗) 278249 and 235648.
lowhigh =
repmat([0;1],1,p);
end
%-----------------------------------------------------------------------------
function [img,tol] = ParseInputs(varargin)
narginchk(1, 2);
img = varargin{1};
validateattributes(img, {'uint8', 'uint16', 'double', 'int16',
'single'}, {'real', ...
'nonsparse','nonempty'},
mfilename, 'I or
RGB', 1);
if (ndims(img) > 3)
error(message('images:stretchlim:dimTooHigh'))
end
tol = [.01 .99]; �fault
if nargin == 2
tol =
varargin{2};
switch
numel(tol)
case 1
tol(2) = 1
- tol;
case 2
if (tol(1)
>= tol(2))
error(message('images:stretchlim:invalidTolOrder'))
end
otherwise
error(message('images:stretchlim:invalidTolSize'))
end
end
if ( any(tol < 0) || any(tol
> 1) || any(isnan(tol)) )
error(message('images:stretchlim:tolOutOfRange'))
end