我正在尝试对所示图像实施各种二值化算法:

代码如下:

clc;
clear;
x=imread('n2.jpg');     %load original image


%现在我们调整图像的大小这样以后我们的计算工作就变得更容易了。 sauvola算法

size(x);
x=imresize(x,[500 800]);
figure;
imshow(x);
title('original image');

z=rgb2hsv(x);       %extract the value part of hsv plane
v=z(:,:,3);
v=imadjust(v);

实施niblack阈值算法的百分比:

m = mean(v(:))
s=std(v(:))
k=-.4;
value=m+ k*s;
temp=v;

实施sauvola阈值算法的百分比:
/>
for p=1:1:500
    for q=1:1:800
        pixel=temp(p,q);
        if(pixel>value)
            temp(p,q)=1;
        else
            temp(p,q)=0;
        end
    end
end
figure;
imshow(temp);
title('result by niblack');
k=kittlerMet(g);
figure;
imshow(k);
title('result by kittlerMet');


结束

val2=m*(1+.1*((s/128)-1));
t2=v;
for p=1:1:500
for q=1:1:800
    pixel=t2(p,q);
    if(pixel>value)
        t2(p,q)=1;
    else
        t2(p,q)=0;
    end
end


我获得的结果如下:


您可以看到在较暗的地方所产生的图像质量下降。有人可以建议如何优化我的结果吗?

评论

您可以使用颜色信息代替背景而仅丢弃亮度吗?

尊敬的先生/女士。我正在做图像处理项目。我是一个有趣的二值化概念。请检查并纠正编码。另一个是msp中的错误(第31行)k = kittlerMet(g); ..如何解决...请更正编码...

#1 楼

您的图像亮度不均匀,因此不应使用统一的阈值。您需要一个自适应阈值。这可以通过对图像进行预处理以使图像上的亮度更加均匀来实现(用Mathematica编写的代码,您必须自己实现Matlab版本):

亮度均匀是使用封闭滤镜从图像中去除实际文本:字体笔划的宽度,并且小于要尝试去除的污点的大小。这是形态膨胀,然后是形态侵蚀。膨胀实质上将结构元素移动到图像中的每个位置,并在遮罩下拾取最亮的像素,因此:


去除小于结构元素的暗结构
缩小按结构化元素的大小可以放大较大的深色结构
放大明亮的结构

腐蚀操作的作用与此相反(它会在结构化元素内部拾取最暗的像素),因此如果将其应用于膨胀后的图像:


由于比结构元素小而被删除的深色结构仍然消失了
缩小的深色结构再次被放大到原始形状大小(尽管它们的形状会更平滑)
明亮的结构会减小到其原始大小

,因此关闭操作可以删除较小的深色物体,而对较大的深色物体和明亮的物体只需进行较小的更改即可。

下面是一个具有不同结构元素大小的示例:



随着结构元素的大小增加,越来越多的字符被删除。在radius = 5处,所有字符均被删除。如果半径进一步增大,那么较小的污点也将被去除: (几乎)均匀亮度:

white = Closing[src, DiskMatrix[5]]




现在可以使用恒定阈值对图像进行二值化:

whiteAdjusted = Image[ImageData[src]/ImageData[white]*0.85]




评论


$ \ begingroup $
哇!这真是太酷了!巨大+1!
$ \ endgroup $
– Phonon
2012年4月4日14:03

$ \ begingroup $
@nikie +1非常好-您关闭关闭过滤器的确切含义是“必须选择大于字体笔划”?字母的宽度或长度?此外,关闭过滤器“确实”在做什么?谢谢!
$ \ endgroup $
–太空
2012年4月4日在16:02



$ \ begingroup $
@Mohammad:我在回答中添加了一些解释。是的,这些是非线性运算。共同的标题是形态图像处理。
$ \ endgroup $
– Niki Estner
2012年4月4日在20:15

$ \ begingroup $
@nikie没关系,白色是最大值,而不是黑色。 :-)
$ \ endgroup $
–太空
2012年4月4日在20:33

$ \ begingroup $
@gdelfino:为了安全起见,我通常尝试使用足够大的遮罩来避免这种情况,并使用Clip [ImageData [white],{eps,Infinity}](其中eps很小)来避免这种情况。
$ \ endgroup $
– Niki Estner
2012年11月22日19:53



#2 楼

Nikie的答案似乎最好,而且似乎正在奏效并产生结果。因此,这无疑是赢家。

这种技术称为自适应阈值化,它不需要显式学习背景。

本质上,无需寻找最合适的全局阈值-我们可以将图像分区一个本地窗口(例如大约7x7或适当的大小),并找到随窗口移动而变化的阈值。

下面的参考详细介绍了确切的方法。
http://homepages.inf.ed.ac.uk/rbf/HIPR2/adpthrsh.htm

此该方法在计算上相对较快。

评论


$ \ begingroup $
这两件事根本不一样吗?是否在阈值化之前估计信号的局部均值?
$ \ endgroup $
– Maurits
2012年4月9日在11:12

$ \ begingroup $
@Maurits看起来主要区别在于排序和使用的统计信息。例如,在打开/关闭运算符(由膨胀和腐蚀组成,但顺序不同)中,对窗口进行光栅扫描并获取最大值。 (除其他事项外)。但是,在自适应阈值中,可以采用平均值/中位数代替最大值。
$ \ endgroup $
–太空
2012年4月9日在23:17

$ \ begingroup $
OP也对SO提出了要求,我回答了。但是原则上,我认为答案之间没有任何区别,一个总是估算本地统计信息。如果您进行自适应阈值化,那么您还将在此过程中了解背景知识。
$ \ endgroup $
– Maurits
2012年10月10日7:54

#3 楼

使用带通滤波器的另一种方法(在MATLAB中)。玩弄高斯参数的差异可能会得到更好的结果。该过程基本上是对图像进行带通滤波,以去除低频背景斑点,并标准化为'graythresh'命令所需的[0,1],阈值图像。 br />
I = imread('hw.jpg');
I = rgb2gray(I);
I = double(I);




使用高斯核的差值对滤波器进行归一化:

J = imgaussian(I,1.5) - imgaussian(I,0.5);
J = J - min(J(:));
J = J / max(J(:));





计算阈值并得出010101:

T = J > graythresh(J);




#4 楼

这是用于自适应阈值的很好的Matlab代码:http://www.mathworks.com/matlabcentral/fileexchange/8647-local-adaptive-thresholding

评论


$ \ begingroup $
啊!但是需要图像处理工具箱。 :-/
$ \ endgroup $
–太空
2012年4月9日23:00

$ \ begingroup $
的确如此。对不起,如果您没有它。但是DIPImage是Matlab的免费Image Tolbox。 diplib.org/documentation它提供了几种阈值化方法(检查分段部分),并且您还可以执行所有形态学操作,例如关闭。开发人员还有一个博客cb.uu.se/~cris/blog/index.php/archives/tag/matlab
$ \ endgroup $
– MyCarta
2012年10月10日14:15

#5 楼

我会尝试这种编码。但是我没有正确的答案...

clc;
clear;
x=imread('base2.jpg');
size(x);
x=imresize(x,[500 800]);
figure;
imshow(x);
title('original image');
z=rgb2hsv(x);       %extract the value part of hsv plane
v=z(:,:,3);
v=imadjust(v);
m = mean(v(:))
s=std(v(:))
k=-2;
value=m+ k*s;
temp=v;
for p=1:1:500
    for q=1:1:800
        pixel=temp(p,q);
        if(pixel>value)
            temp(p,q)=1;
        else
            temp(p,q)=0;
        end
    end
end
figure;
imshow(temp);
title('result by niblack');
% k=kittlerMet(g);
% figure;
% imshow(k);
% title('result by kittlerMet');

val2=m*(1+.1*((s/128)-1));
t2=v;
for p=1:1:500
for q=1:1:800
    pixel=t2(p,q);
    if(pixel>value)
        t2(p,q)=1;
    else
        t2(p,q)=0;
    end
end

end
figure;
imshow(t2);
title('result by sauvola');






评论


$ \ begingroup $
如果要回答这个问题,请说明您在做什么以及原因。
$ \ endgroup $
– Matt L.
15年3月20日在11:37