二值法方法综述及matlab程序

在某些图像处理当中一个关键步是二值法,二值化一方面能够去除冗余信息,另一方面也会使有效信息丢失。所以有效的二值化算法是后续的处理的基础。比如对于想要最大限度的保留下面图的中文字,以便后续的定位处理。 二值化算法包括全局二值化和局部二值化, 全局二值化具有速度快但效果相对差的特点, 局部二值化算法具有速度慢效果好的特点。

原图

全局阈值             

方法一:直接采用im2bw ;手动阈值

方法二:迭代法求阈值

迭代式阈值选取的基本思路是:首先根据图像中物体的灰度分布情况,选取一个近似阈值作为初始阈值,一个较好的方法就是将图像的灰度均值作为初始阈值;然后通过分割图像和修改阈值的迭代过程获得认可的最佳阈值。迭代式阈值选取过程可描述如下。

(1)选取一个初始阈值T。

(2)利用阈值T把给定图像分割成两组图像,记为R1和R2 。

(3)计算R1和R2 均值u1和 u2

(4)选取新的阈值T,且T=(u1+u2)/2

(5)重复第(2)~(4)步,直至R1和R2均值不再变化为止。

具体实现时,首先根据初始开关函数将输入图逐个图像分为前景和背景,在第一遍对图像扫描结束后,平均两个积分器的值以确定一个阈值。用这个阈值控制开关再次将输入图分为前景和背景,并用做新的开关函数。如此反复迭带直到开关函数不在发生变化,此时得到的前景和背景即为最终分割结果。迭代所得的阈值分割的图像效果良好。基于迭代的阈值能区分出图像的前景和背景的主要区域所在,但在图像的细微处还没有很好的区分度。对某些特定图像,微小数据的变化却会引起分割效果的巨大改变,两者的数据只是稍有变化,但分割效果却反差极大。对于直方图双峰明显,谷底较深的图像,迭代方法可以较快地获得满意结果,但是对于直方图双峰不明显,或图像目标和背景比例差异悬殊,迭代法所选取的阈值不如其它方法。将全局平均值作为初始阈值,将图像分为两部分,求每部分的均值,迭代,直到这两部分均值不在变化。

function [b1 ] = binary_iterate( f1 )
% 用迭代的方法对图像进行二值化

t=mean(f1(:));
is_done=false;
count=0;
while ~is_done                         

    r1=f1(f1<=t);
    r2=f1(f1>t);
    temp1=mean(r1(:));
    if isnan(temp1);
         temp1=0;
    end
    temp2=mean(r2(:));
    if isnan(temp2)
         temp2=0;
    end
    t_new=(temp1+temp2)/2;
    is_done=abs(t_new-t)<1;
    t=t_new;
    count=count+1;
    if count>=1000
        Error=‘Error:Cannot find the ideal threshold.‘
        Return
    end
end 

b1=im2bw(mat2gray(f1),t/256);
end

方法三:居于最大类间差的方法----Otsu法

图像记t为前景与背景的分割阈值,前景点数占图像比例为w0,平均灰度为u0;背景点数占图像比例为w1,平均灰度为u1,则图像的总平均灰度为:u=w0*u0+w1*u1从最小灰度值到最大灰度值遍历t,当t使得值g=w0*(u0-u)^2+w1*(u1-u)^2最大时t即为分割的最佳阈值。

大津法可作如下理解:该式实际上就是类间方差值,阈值t 分割出的前景和背景两部分构成了整幅图像,而前景取值u0,概率为 w0,背景取值u1,概率为w1 ,总均值为u,根据方差的定义即得该式。因方差是灰度分布均匀性的一种度量,方差值越大,说明构成图像的两部分差别越大,当部分目标错分为背景或部分背景错分为目标都会导致两部分差别变小,因此使类间方差最大的分割意味着错分概率最小。直接应用大津法计算量较大,因此在实现时采用了等价的公式g=w0*w1*(u0-u1)^2第二,第三种方法得到的阈值相差不大,效果也类似,不能解决光照不均的局面。这是因为用全局阈值是无法根据每个特定的区域采用不同的阈值,于是只能尝试采用局部阈值,或是对图像进行预处理改进其直方图特性。

function [b1,reT] =binary_otus( f1 )
% otus法二值化
[r c]=size(f1);
gray_level=256;
resultT=0;
hist=zeros(gray_level,1);
for i=1:r
    for j=1:c
        hist(f1(i,j)+1)=hist(f1(i,j)+1)+1;
    end
end
hist=hist/(r*c);
vmax=0;
for tt=1:gray_level
    T=tt-1;
    w0=0;w1=0;u0=0;u1=0;var=0;%重要的地方,在每次循环遍历的时候。要把涉及到的变量清零。
    for i=1:T+1
        w0=w0+hist(i);
        u0=u0+(i-1)*hist(i);
    end
    u0=u0/w0;
    w1=1-w0;
    for j=T+2:gray_level
        u1=u1+(j-1)*hist(j);
    end
    u1=u1/w1;
    var=w0*w1*(u0-u1)^2;
%     v(tt)=var;
    if var>vmax
        vmax=var;
        resultT=T;
    end
end
b1=im2bw(mat2gray(f1),resultT/255);
reT=resultT/255;
end

局部阈值法

方法四:分块otus

对图像分块,对每块采用方法三最大类间差的方法处理,(改进的地方分块的长宽不是一致的)设置的窗口为10*10.。 看上图,明显看到光照不均那段被检测出来 了,但是缺点是要很好的设置好分块的大小。而且图片产生了伪影,多出了很多黑块。怎么会出现这些黑块呢?观察后发现黑块往往是在图像灰度细节不够丰富的区域产生。黑块产生的原因一定是出在每个分块采用的二值化方法--otsu算法。otsu算法更适合空间细节不丰富但灰度细节却很丰富的图像,因为这种图像往往才会有明显的类间距。对于灰度不丰富的图像,otsu 得到的阈值较不理想。

function [ b1] = binary_part(gray_image,a,b)
% 采用局部二值化,各个局部采用otus法
[m,n]=size(gray_image);
result=zeros(m,n);
for i=1:a:m
    for j=1:b:n
        if ((i+a)>m)&&((j+b)>n)     %分块
            block1=gray_image(i:end,j:end); %右下角区块
        elseif ((i+a)>m)&&((j+b)<=n)
            block1=gray_image(i:end,j:j+b-1); %最右列区块
        elseif ((i+a)<=m)&&((j+b)>n)
            block1=gray_image(i:i+a-1,j:end);  %最下行区块
        else
             block1=gray_image(i:i+a-1,j:j+b-1); %普通区块
        end 

       [ block,~]=binary_otus(block1);
        if ((i+a)>m)&&((j+b)>n)            %合并结果
            result(i:end,j:end)=block;
        elseif ((i+a)>m)&&((j+b)<=n)
           result(i:end,j:j+b-1)=block;
        elseif ((i+a)<=m)&&((j+b)>n)
            result(i:i+a-1,j:end)=block;
        else
            result(i:i+a-1,j:j+b-1)=block;
        end
    end
end 

b1=result;
end

方法五:ernsen算法

ernsen算法凭其优异的综合性能, 在局部二值化领域占有重要一席, 它较适合解决光照不均的问题。这个算法的中心思想是:设当前像素为P,计算以P为中心的大小为(2w+1)*(2w+1)窗口内的所有像素的最大值M与最小值N,两者的均值T,if(M-N)> S 则当前点P的阈值为T。else当前窗口所在区域的灰度级差别较小,那么窗口在目标区或在背景区,若T>T1则当前点灰度值为255,否则,当前点灰度值为0。S设为15, T1设为20。(这两个值的设定还是需要根据具体的图像具体分析)从上图中可以看到bernsen方法能够较为有效的解决光照不均的问题。美中不足的是这方法运行的时间太长,针对这一问题也有很多的改善的方法。

function [ b1 ] = binary_bernsen( f1 )
% 局部二值化方法,局部区域采用简单阈值。
[m,n]=size(f1);
s=15;
t1=20;
exI=uint8(ones(m+2,n+2));%扩展图片,预分配一个矩阵
re=uint8(ones(m,n));
exI(2:m+1,2:n+1)=f1;%把原图片赋给矩阵
%==========对矩阵进行填充==========%
exI(1,:)=exI(2,:);
exI(m+2,:)=exI(m+1,:);
exI(:,1)=exI(:,2);
exI(:,n+2)=exI(:,n+1);

for i=2:m+1
    for j=2:n+1
        %===========求3*3区域内的阈值并对图像进行二值化,结果存在re中==========%
        ma=max(max(exI(i-1:i+1,j-1:j+1)));
        mi=min(min(exI(i-1:i+1,j-1:j+1)));
        t=(ma+mi)/2;
        if ma-mi>s
             if exI(i,j)>t
                 re(i-1,j-1)=255;
             else
                re(i-1,j-1)=0;
            end
        else
            if t>t1
                re(i-1,j-1)=255;
             else
                re(i-1,j-1)=0;
            end
        end

    end
end

b1=re;
end

主函数:

clc;
clear all;
[fn pn fi]=uigetfile(‘*.*‘,‘choose a picture‘);
Img=imread([pn fn]);
Img_gray=rgb2gray(Img);
Img_bw=binary_bernsen(Img_gray);%这里修改对应的函数
figure;
imshow(Img_bw);
imwrite(Img_bw,‘bw.jpg‘)

二值法方法综述及matlab程序

时间: 2024-10-25 18:10:40

二值法方法综述及matlab程序的相关文章

二值化方法:Minimum Error Thresholding

Kittler二值化方法,是一种经典的基于直方图的二值化方法.由Kittler在1986年在论文“Minimum Error Thresholding”提出. 参考了ImageShop提供的C#版本(http://www.cnblogs.com/Imageshop/p/3307308.html),做了简单修改得到了C++版本的,代码如下: /*灰度图像的二值化方法*/ class CxThreshold { public: static int CalcKittlerMinError(int*

一维最大熵二值化方法

static int Get1DMaxEntropyThreshold(const int* HistGram, int const in_Start, int const in_End) { int X, Y, Amount = 0; double HistGramD[256]; double SumIntegral, EntropyBack, EntropyFore, MaxEntropy; int MinValue = in_Start, MaxValue = in_End; int Th

图像处理之常见二值化方法汇总

图像处理之常见二值化方法汇总 图像二值化是图像分析与处理中最常见最重要的处理手段,二值处理方法也非常多.越 精准的方法计算量也越大.本文主要介绍四种常见的二值处理方法,通常情况下可以满 足大多数图像处理的需要.主要本文讨论的方法仅针对RGB色彩空间. 方法一: 该方法非常简单,对RGB彩色图像灰度化以后,扫描图像的每个像素值,值小于127的 将像素值设为0(黑色),值大于等于127的像素值设为255(白色).该方法的好处是计算 量少速度快.缺点更多首先阈值为127没有任何理由可以解释,其次完全不

atitit.验证码识别step4--------图形二值化 灰度化

atitit.验证码识别step4--------图形二值化 灰度化 1. 常见二值化的方法原理总结 1 1.1. 方法一:该方法非常简单,对RGB彩色图像灰度化以后,扫描图像的每个像素值,值小于127的将像素值设为0(黑色),值大于等于127的像素值设为255(白色). 1 1.2. 方法二:最常见的二值处理方法是计算像素的平均值K, 2 1.3. 方法三:使用直方图方法来寻找二值化阈值, 2 1.4. 方法四:使用近似一维Means方法寻找二值化阈值,(推荐) 3 2. 使用类库imagei

二值化函数cvThreshold()参数CV_THRESH_OTSU的疑惑【转】

查看OpenCV文档cvThreshold(),在二值化函数cvThreshold(const CvArr* src, CvArr* dst, double threshold, double max_value, int threshold_type)中,参数threshold_type有5种类型: THRESH_BINARY THRESH_BINARY_INV THRESH_TRUNC THRESH_TOZERO THRESH_TOZERO_INV 问题来了:为什么可以在threshold_

一种超级快速的图像二值化技术

在计算机视觉中,对图像进行二值化恐怕是最常见的操作了.为了检测目标,可能需要对每一帧图像的每一个像素点进行运算.如果能提升二值化的速度,那么,你的算法的效率就会大大的提高.本文,将介绍一种超级快速的图像二值化技术. 要解决的问题: 如上图所示,需要把彩色图像中, (1) R通道介于(smoevalue1, somevalue2)(2) G通道介于(somevalue3, somevalue4)(3) B通道介于(somevalue5, somevalue6)当图像中某个像素点同时满足上面3个条件

席位分配问题——惯例Q值法和d&#39;hondt法的MATLAB程序

  本篇博文为追忆曾经写过的算法系列第四篇 温故知新 本篇于2009年发表于百度博客,当时还没接触CSDN,所以是文学和技术博客混淆,不过这个程序博文访问量突破2000,有不少网友评论互动,应该对很多人有一定的帮助. 程序介绍了数学建模中经典问题的两种解法,即席位分配问题! %适用于所有情况 BY Gu clear all clc %惯例Q值法分配席位,wy为席位数,ps为人数总和,R为分配方案 wy=19; P=[103 63 34] %菜单选项 MENUN=menu('选择方法','惯

获取Enum枚举值描述的几法方法

原文:获取Enum枚举值描述的几法方法 1.定义枚举时直接用中文 由于VS对中文支持的很不错,所以很多程序员都采用了此方案. 缺点:1.不适合多语言 2.感觉不太完美,毕竟大部分程序员大部分代码都使用英文 2.利用自定义属性定义枚举值的描述(博客园-大尾巴狼) 缺点:不适合多语言 原文:http://www.cnblogs.com/hilite/archive/2006/03/28/360793.html 枚举定义: [EnumDescription("订单.订单中的产品.产品项的状态.&quo

Matlab 对图片的二值化处理

这几天做了一道题目,要求在 5000 张图片中找出 30 张与样例相同但经过放大或缩小,高亮或变暗的图片. 整体思路是把图片hash成一段指纹,这个指纹和图片的大小.格式.明暗均无关,只和图片的内容本身有关. 1.先把彩色图片转为灰度图 如果原本的一个像素点的rgb值为(r1,g1,b1),一个比较简易的方法转为灰度图, 就是 gray1=(r1*299+g1*587+b1*114+500)/1000 那么该像素点的rgb颜色变为(gray1,gray1,gray1). 而我用的是 Matlab