【图像处理知识】Niblack算法和Otsu算法

版权声明:转载时打个招呼。 https://blog.csdn.net/qq_15971883/article/details/79788498

      图像的二值化根据阈值确定方法的不同,可以分为局部阈值法和全局阈值法。Niblack算法属于局部阈值法。Otsu算法属于全局阈值法。

一、Niblack算法

      Niblack算法是通过某一像素点及其邻域内像素点灰度值的均值和标准差计算得到二值化阈值的。在计算图像点(x,y)二值化阈值时,首先计算以(x,y)为中心的n*n大小的区域内像素点的灰度均值m和标准差s。灰度均值m和标准差s的计算公式如下:

                                    

然后根据灰度均值和标准差计算得到点(x,y)的二值化阈值T,计算公式为T(x,y)=k*s(x,y)+m(x,y),其中k为修正系数。最后根据计算得到的阈值T对该点进行二值化处理。将图像中所有的像素点按照此方法处理即可得到二值化图像。

                                            

Niblack算法虽然能够实现图像的二值化,但是如果选取的区域均为背景点时,该算法会将灰度值较高的点当做是目标点,导致伪噪声的引入(针对伪噪声引入的问题,产生了Sauvola算法)。此处说明一下Sauvola算法。Sauvola算法可以说是一种改进的Niblack算法。首先也是按照上文所述方式求取灰度均值和标准差,但是采用了不同的阈值选取方法,具体公式如下:

                                       

其中,R为所有选取区域中标准差的最大值。

以下部分为Niblack算法的MATLAB代码实现:

close all; clear all; clc; 

I = imread('rice.png'); % 读入图像
BW = niblack(I, 80, -0.2); % 调用niblack函数

figure; 
subplot(121), imshow(I); 
subplot(122), imshow(BW); 

实验效果如下:

扫描二维码关注公众号,回复: 3522246 查看本文章

其中niblack函数的实现代码如下:

function imageBW = niblack(image, n, k)
% 通过niblack算法对灰度图像image进行二值化,得到一幅二值图像。
% 编写时间:2018年4月2日21:52:31  编写人:
% 输入:
%     image: 灰度图像,灰度值范围0-255
%     n: 邻域的边长
%     k:修正系数
% 输出:
%     imageBW: 灰度图像image的二值图像
% 参考文献: 
%     Wayne Niblack. An Introduction to Digital Image Processing. pp: 115.
%     1986. Prentice/Hall International. ISBN: 013 480674 3

% 为方便理解下述代码,可假设image=[1 2 3; 4 5 6], n = 2,对代码过程进行分析

tic; % 开始计时

[Height, Width] = size(image); % 获得灰度图像的高和宽
image = padarray(image, [n, n], 'symmetric', 'both'); % 扩展图像矩阵
NewHeight = Height + 2 * n; 
NewWidth = Width + 2 * n;
temp = zeros(NewHeight, NewWidth); % 以新的高度和宽度建议一个零矩阵
for i = 1+n : Height+n
   for j = 1+n : Width+n
       upR = i - floor(n/2 - 1/2); % Row
       dnR = i + floor(n/2); 
       lfC = j - floor(n/2 - 1/2); % Column
       rtC = j + floor(n/2); 
       mean_all = mean(mean(image(upR:dnR, lfC:rtC)));
       % mean()用法:如果A是矢量,则mean(A)返回元素均值;如果A是矩阵,那么mean(A)返回每列均值的行向量
       sigma_squared = double(image(upR:dnR, lfC:rtC)) - mean_all; 
       sigma_squared = mean(mean(sigma_squared .^ 2)); 
       sigma = sqrt(sigma_squared); 
       T = mean_all + k * sigma; % T=k*s(x,y)+m(x,y)
       if double(image(i,j)) > T
           temp(i,j) = 1;
       else
           temp(i,j) = 0; 
       end 
   end
end
imageBW = temp(1+n : Height+n, 1+n : Width+n);

toc; % 结束计时

二、Otsu算法

      Otsu算法又称为最大类间方差法或者大津法,由日本学者大津于1979年提出。该算法是在灰度直方图的基础上采用最小二乘法原理推导出来的,具有统计意义上的最佳分割。它的基本原理是利用最佳阈值将图像的灰度值分割成两个部分,即背景和目标,使背景和目标之间的方差最大,具有最大的分离性。背景和目标之间的方差如果越大,就说明构成图像的两个部分之间的差别越大,当部分目标被错分为背景或者部分背景被错分为目标,都会导致两部分之间的差别变小,当所取阈值的分割使类间方差最大时就意味着错分概率最小。Otsu算法是一种自适应阈值确定的方法,计算简单,效率高,但对于光照不均的图像处理效果不是很好。

      设有一幅灰度图像,大小为M*N。f(x,y)是该图像中点(x,y)处像素的灰度值,灰度级为L,则f(x,y)∈[0, L-1]。若灰度级i的所有像素个数为fi,则第i级灰度出现的概率为:

                                                            

其中i=0, 1, 2, ..., L-1,并且

将图像中的像素按灰度级用阈值t划分为两类,即背景C0和目标C1。背景C0的灰度级为0~t-1,目标C1的灰度级为t~L-1。背景C0和目标C1对应的像素分别为{f(x,y)<t}和{f(x,y)≥t}。

背景C0部分出现的概率为:

                                                       

目标C1部分出现的概率为:

                                                          

其中w0+w1=1。

背景C0部分的平均灰度值为:

                                                      

目标C1部分的平均灰度值为:

                                                       

图像的总平均灰度值为:

                                                           

图像中背景和目标的类间方差为:

                                

令k的取值从0~L-1变化,计算不同k值下的类间方差,使得类间方差最大时的那个k值就是所要求的最佳阈值。

      在matlab图像处理工具箱中,函数graythresh()采用Otsu算法获取全局阈值,获取全局阈值后,可以采用函数im2bw()进行图像分割。函数graythresh()的调用格式如下:

level = graythresh(I):该函数采用Otsu算法获取灰度图像I的最佳阈值,函数的返回值level为获取的阈值,大小介于[0,1]之间。

以下部分为Otsu算法的MATLAB代码实现:

close all; clear all; clc; 

I = imread('rice.png'); % 读入图像
level = graythresh(I); % 通过otsu算法获取最佳阈值
BW = im2bw(I, level);  % 图像二值化

figure;      % imshowpair(I, BW, 'montage');可以采用这种方式显示两幅图像
subplot(121), imshow(I); 
subplot(122), imshow(BW); 

实验效果如下:

其中函数graythresh()实现的代码如下:

function [level, em] = graythresh(I)
% Global image threshold using Otsu's method
% 输入:
%     图像I(can be uint8,uint16,int16,single,double,must be nonsparse)
% 输出:
%     level: 全局阈值,值介于[0,1]之间
%     em: 有效性度量,用于评价level的有效性,值介于[0,1]之间
%
% Example
% -------
%           I = imread('coins.png'); 
%           level = graythresh(I); 
%           BW = imbinarize(I, level); 
%           figure, imshow(BW);
% Reference:
% N. Otsu, "A Threshold Selection Method from Gray-Level Histograms,"
% IEEE Transactions on Systems, Man, and Cybernetics, vol. 9, no. 1,
% pp. 62-66, 1979.

% 输入检查
validateattributes(I, {'uint8', 'uint16', 'double', 'single', 'int16'}, ...
    {'nonsparse'}, mfilename, 'I', 1); 

if ~isempty(I)
   % convert all N-D arrays into a single column. 
   % convert to uint8 for fastest histogram computation
    I = im2uint8(I(:)); % I(:),is all the elements of I, regarded as a single column
    num_bins = 256; 
    counts = imhist(I, num_bins); 
    
    if nargout <= 1 % 针对当前正在执行的函数,返回该函数输出参数的数目
        level = otsuthresh(counts);
    else
        [level, em] = otsuthresh(counts); 
    end
end

其中函数otsuthresh()实现的代码如下:

function [t,em] = otsuthresh(counts)
% global histogram threshold using Otsu's method

% 输入检查
validateattributes(counts, {'numeric'}, {'real', 'nonsparse', ...
    'vector', 'nonnegative', 'finite'}, mfilename, 'COUNTS');

num_bins = numel(counts); % numel()返回数组元素的数目

% make counts a double column vector
counts = double(counts(:)); 

% variables names are chosen to be similar to the formulas in the Otsu's paper
p = counts / sum(counts); % 这里的p是一个列向量,包含各灰度级出现的概率
omega = cumsum(p); % omega也是一个列向量
mu = cumsum(p .* (1:num_bins)'); 
mu_t = mu(end); 

sigma_b_squared = (mu_t * omega - mu) .^2 ./ (omega .* (1 - omega)); 

% find the location of the maximum value of sigma_b_squared
% the maximum may extend over several bins, so average together the
% locations. if maxval is nan, meaning that sigma_b_squared is all nan,then
% return 0.

maxval = max(sigma_b_squared); 
isfinite_maxval = isfinite(maxval); 
if isfinite_maxval
   idx = mean(find(sigma_b_squared == maxval)); 
   % normalize the threshold to the range [0,1]
   t = (idx - 1) / (num_bins - 1);
else
    t = 0.0; 
end

% compute the em
if nargout > 1
   if isfinite_maxval
       em = maxval / (sum(p .* ((1:num_bins) .^ 2)') - mu_t^2);
   else
        em = 0; 
   end
end

end

猜你喜欢

转载自blog.csdn.net/qq_15971883/article/details/79788498