OTSU阈值分割算法

阈值分割算法

二值化

首先以灰度图的x,y坐标为二维坐标系的x,y坐标,以对应位置的像素灰度值为z坐标,建立灰度图的三维坐标系,如下图

二值化处理就是在对应0255范围内找出合适阈值筛选出对我们有用的信息。如果把上图当作一个地形图,阈值分割就是找出合适的水位去淹没对我们无用的信息,保留有用信息。具体效果如下图

上述两图的灰度图像为

untitled

现在的难点是如何找到合适的阈值去分割图像信息,准确的说是如何用数学的方法使阈值的选取转化成计算机可以运行的过程。

OTSU阈值分割算法

对于上述灰度等级为0,1...,255分辨率为120188的灰度图像

ni为灰度等级为i的像素个数,则图像像素总数为N=n1+n2+...+n255=120188,

灰度为i的像素概率为P(i)=niN

ix轴,ni对应的像素个数为y轴绘制像素直方图如下图

image-20230505120222169

对于赛道图来说,由于赛道和背景有较大差异(灰度值不同),且赛道在图像内占比较大,数以直方图内一般会出现两个波峰,分别代表赛道灰度像素与背景灰度像素。

现在我们假设存在一个阈值k,对灰度值大于k的部分称为前景,小于k的部分称为背景

像素分类到前景的概率为P1(k)=1Ni=0kni

分类到背景的概率为P2(k)=1P1(k)

背景的像素灰度均值为:

mean1(k)=1n1+....+nki=0kini=Nn1+....+nk1Ni=0kini=Nn1+....+nki=0kiniN=1P1(k)i=0kiP(i)

同理可得前景像素灰度均值为:

mean2=1P2(k)i=k+1255iP(i)

整张图像的灰度均值为:

meanG=1Ni=0255ini=i=0255iP(i)=P1(k)mean1(k)+P2(k)mean2(k)

类间方差定义为阈值两侧数据各自均值距离总均值的加权方差,阈值两侧均值分别代表了前景与背景的主要灰度值,类间方差越大表示前景与背景可以得到更好的分离,二值化效果也更佳。

σ(k)=P1(k)[mean1(k)meanG]2+P2(k)[mean2(k)meanG]2=P1(k)[mean1(k)P1(k)mean1(k)P2(k)mean2(k)]2+P2(k)[mean2(k)P1(k)mean1(k)P2(k)mean2(k)]2=P1(k)[P2(k)mean1(k)P2(k)mean2(k)]2+P2(k)[P1(k)mean2(k)P1(k)mean1(k)]2=P1(k)P2(k)2[mean1(k)mean2(k)]2+P2(k)P1(k)2[mean2(k)mean1(k)]2=P1(k)P2(k)[[P2(k)+P1(k)][mean1(k)mean2(k)]2]=P1(k)P2(k)[mean1(k)mean2(k)]2

最后得出类区间方差公式为:

σ(k)=P1(k)P2(k)[mean1(k)mean2(k)]2

遍历灰度的直方图数组,找出使σ(k)最大的k值即为阈值。

代码实现:

function Threshold = OTSU(pic ,W ,H)
HistGram = zeros(256,1);            		%直方图一维矩阵
pixelsum = uint32(0);               		   %像素总个数
PixelIntegral = uint32(0);                             %灰度总个数
PixelFore = uint32(0);             	                   %前景像素个数指灰度值>阈值
PixelBack = uint32(0);           	                 %背景像素个数指灰度值<阈值
P_Fore = double(0);                                      %前景概率
P_Back = double(0);                                     %背景概率
PixelIntegralFore = uint32(0);     	               %前景灰度总值
PixelIntegralBack = uint32(0);                      %背景灰度总值
MIntegralFore = double(0);          		%前景灰度均值
MIntegralBack = double(0);          		%背景灰度均值
tau = double(0);                    			%类间方差
last_tau = double(-1);
for i = 1:W
    for j = 1:H
         HistGram(pic(i,j)) = HistGram(pic(i,j)) + 1;       %遍历图像完善直方图内容
    end
end
for i = 1:256
    pixelsum = pixelsum + HistGram(i);			%获取像素总数可简化为W*H
    PixelIntegral = PixelIntegral + HistGram(i)*i;	   %灰度值总个数
end
for i = 1:256
    PixelFore = PixelFore + HistGram(i);		   %获取前景灰度总值
    PixelBack = pixelsum - PixelFore; 			  %背景灰度值
    P_Fore = double(PixelFore)/double(pixelsum);   %前景概率
    P_Back = 1 - P_Fore;					   %背景概率
    PixelIntegralFore = PixelIntegralFore + HistGram(i)*i;
    PixelIntegralBack = PixelIntegral - PixelIntegralFore;
    MIntegralFore = double(PixelIntegralFore)/double(PixelFore);
    MIntegralBack = double(PixelIntegralBack)/double(PixelBack);
    tau = double(P_Fore*P_Back*(MIntegralFore-MIntegralBack)^2);	%类区间方差公式
    if tau > last_tau											%取阈值为使tau为最大时
        last_tau = tau;
        Threshold = i;
    end     
end
end

二值化结果如下图

image-20230505145325070

作者:whwhhf

出处:https://www.cnblogs.com/whwhhf/p/17374156.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   DOinging  阅读(207)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示
more_horiz
keyboard_arrow_up dark_mode palette
选择主题