求一个自适应阈值二值化化图片的软件,最好能自己改阈...

图象二值化代码 一个在 处理中有用的 源程序,要用快下! Graph program 图形
240万源代码下载-
&文件名称: 图象二值化代码
& & & & &&]
&&所属分类:
&&开发工具: Visual C++
&&文件大小: 1 KB
&&上传时间:
&&下载次数: 91
&&提 供 者:
&详细说明:一个在图象处理中有用的图象二值化源程序,要用快下!-image processing in a useful image binary source, use under fast!
文件列表(日期:)(点击判断是否您需要的文件,如果是垃圾请在下面评价投诉):
&&图象二值化代码.txt
&相关搜索:
&输入关键字,在本站240万海量源码库中尽情搜索:
&[] - 对一副图片进行阈植处理,把图象二值化.
&[] - 目前准确度最好的支持向量机分类算法,用C++编写.
&[] - 自动域值变换,见程序,用于图象二值化,可用于电子***中的号拍定位
&[] - 将特定图象进行二值化,去掉背景
&[] - 本人搜集的Ostu图像二值化的算法,是在MATLAB环境下写的,不过上传的代码是文本格式的,各位可以根据自己需要参照一下
&[] - Otsu-最大类间方差Matlab代码 最大类间方差法原理:最大类间方差法是由日本学者大津于1979年提出的,是一种自适应的阈值确定的方法,又叫大津法,简称OTSU。它是按图像的灰度特性,将图像分成背景和目标2 部分。背景和目标之间的类间方差
% 大,说明构成图像的2 部分的差别越大,当部分目标错
&[] - 最佳阈值分割,能在两个波谷中找到最佳分割点,从图像上来看效果不错!
&[] - 腐蚀的算法
&[] - 灰度指纹图像分割
function DestJu=MyCutWhite(SourJu,BloWide)
%分割白背景区
%InImage输入图像,自动确定阈值在Altium Designer13 中插入图片,制作书签
在Altium Designer13 中插入图片,制作书签
& & & & &在绘制PCB电路板时,我们可能会添加一些Logo或一些感兴趣的图片,使我们制作出来的PCB电路板更加好看吸引人。
问题:我为什么会要研究一下这个小问题(小技术)? &
原因:我的一位同学在图书馆借到的一本书中夹了一张书签。这不是普通的书签,是用PCB电路板制成的书签,是双面的,每一面都有图画而且配有古诗。当时感觉特别NBNB。于是决定做一个。
工具:1.opencv+vs2013或matlab。&
& & & & & &2.PhotoZoom.Pro.v6.0.2 &图片无损放大工具
& & & & & &3.Bmp2Pcb & & & & & & & & &bmp图像文件 to pcb 工具
& & &1.找到一张喜欢的图片,将彩色图片进行二值化变成黑白图片。这里可以采用opencv+vs2013或matlab。刚好我电脑里装了opencv所以我选择opencv。主要是没装matlab,其实用matlab也挺简单的。& &
&这是我选的图片。这是我们学院社团的Logo,学弟刚好需要把Logo加到PCB中。
&这里我使用的opencv2.4.9 程序: 程序我是在网上资料的基础上改过来的,有些地方有些问题,但是大体是好用的。
至于具体的函数使用方法在这里我就不仔细讲解了,可以看看网上的资料。
&#include&stdafx.h&
#include &opencv2/opencv.hpp& &
#include &opencv2/core/core.hpp&
#include &opencv2/highgui/highgui.hpp&
#include &iostream&
#include &string&
#pragma comment(linker, &/subsystem:\&windows\& /entry:\&mainCRTStartup\&&)//运行时不显示DOS框 &
void sum_rgb(IplImage* src, IplImage* dst) &//该函数的作用就是转灰度后二值化
IplImage* r = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
IplImage* g = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
IplImage* b = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
//函数 cvSplit 分割多通道数组成分离的单通道数组d
cvSplit(src, r, g, b, NULL);
IplImage* s = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
cvAddWeighted(r, 1. / 3, g, 1. / 3, 0.0, s);
cvAddWeighted(s, 2. / 3, b, 1. / 3, 0.0, s);
cvThreshold(s, dst, 100, 255, CV_THRESH_BINARY);
cvReleaseImage(&r);
cvReleaseImage(&g);
cvReleaseImage(&b);
cvReleaseImage(&s);
IplImage* s1 = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
cvCvtColor(src, s1, CV_BGR2GRAY);
cvThreshold(s1, dst,240, 255, CV_THRESH_BINARY);
int main()
cvNamedWindow(&aaa&, 1);
IplImage* src = cvLoadImage(&D:\ha.JPG&);
IplImage* dst = cvCreateImage(cvGetSize(src), src-&depth, 1);
sum_rgb(src, dst);
cvShowImage(&aaa&, dst);
cvSaveImage(&D:\ha2.png&, dst);
cvWaitKey(0);
cvDestroyAllWindows();
cvReleaseImage(&src);
cvReleaseImage(&dst);
&二值化后的图片
& 2.二值化后的图片格式PNG格式,运用美图秀秀将格式改为bmp格式。因为bmptopcb软件只能利用bmp格式的图片,所以要转换。
&3.使用bmptopcb软件将图片转换至pcb文件,这里要选择分辨率,那一层,使用比较简单,这里不再赘述。
&&用Altium
Designer软件打开转换后的文件时看到的效果。
& & & & & & &讲到这里,主体部分已经讲完了。建议大家可以建立一个Logo库把一些将常用到的Logo放到一个库中,方便调用。
注意事项:
& 1.图片大小问题:你选的图片可能过小,在Altium Designer中很小,以后在实际在Pcb电路板中会很小不符合实际。
因此需要放大图片。就用到了PhotoZoom.Pro.v6.0.2 &图片无损放大工具。使用方法很简单,大家一看就会用。
&2.在bmptopcb软件中,需要调整分辨率,直接影响pcb文件中的图片清晰程度。
&3.在opencv二值化程序中,可以通过改变阈值,来调整转后的黑白图片的清晰程度。
下面展示一下我做的书签,现在还没有发板子,等板子做好后我再传一张图给大家看看。
有什么问题,欢饮大家留言 ps我邮箱
-------------------------------------------------- 更新----------------------------------------------------------------
好久没有做logo了,这次又心血来潮想在自己画的板子上做上一点自己特有的标记图案,所以又把这篇技术文档又翻出来了。现在对上边的一些问题做下跟新。
1.前面是用的opencv对彩色图像进行的处理,但是配置opencv太麻烦了 所以现在改用matalab来进行图像处理。
aa=imread('d:\1.jpg');
figure(1);
imshow(aa);
bb=rgb2gray(aa);
%彩色图转灰度图
figure(2);
imshow(bb);
cc=im2bw(bb,0.45);
%灰度图转二值黑白图
后面一个参数是调阈值
figure(3);
imshow(cc);
将图片处理好后,要保存为bmp图片格式的,应为下一步软件需要bmp的图片格式。
2.BMP2PCB用法
先加载图片,选择转换操作的格式,选择分辨率的,按住ctrl键,选择图片上需要保存的颜色。
说明一下:该软件可以转换彩色的图片,但是转换的效果并不好,所以我建议还是将彩色图片先转换为二值化的黑白图片在用这个工具比较好。
3.转换好后会生成一个pcb文件,但是会遇到用 Altium designer(本人用的是AD13版本也没有pcb显示出来) 去打开,但是没有pcb图显示出来。这是因为AD13版本需要***导入插件。好像BMP2PCB生成的pcb文件是支持protel软件的,对新版本的AD软件不太支持。需要在AD里***导入文件的插件。
点击DXP-》Plug-ins and updates -》选择importers and Exporters
现在需要选择一些插件了,其实我也不知道哪个插件能解决这个问题,最后将所有插件都***了,就好使了。
就是为了这个头像又把这个老技术又翻了出来。
我的热门文章
即使是一小步也想与你分享一种光照不均匀图像的二值化方法--《计算机应用与软件》2014年03期
一种光照不均匀图像的二值化方法
【摘要】:在图像处理与分析中,二值化方法能把特征或目标从图像中分割出来,以便识别。在实际拍摄的图像中,图像光照不均匀使得图像二值化阈值确定困难。针对一类光照不均匀图像的二值化问题,提出一种单列处理及改进OSTU的二值化方法,通过分析该类图像上不均匀光照的分布特点,首先应用单列二值化处理方案,在省去专门光照均匀化处理步骤的同时,解决统一阈值二值化方法所造成的信息丢失问题。在逐列二值化处理过程中,首先采用传统OSTU方法获取图像各列的初始二值化阈值,然后根据各列的光照强度计算出该列二值化阈值的自适应微调量,实现对初始二值化阈值的优化。一组缺陷钢坯图片处理结果证实了所述方法的有效性。
【作者单位】:
【关键词】:
【基金】:
【分类号】:TP391.41【正文快照】:
0引言在数字图像处理中,二值化方法通过选取适当的阈值对图像进行分割,从而突出图像中的某些特征。对于光照均匀的图片,应用经典的全局阈值方法就能取得较好的效果,这些方法主要有:根据直方图谷底确定阈值法、迭代选择阈值法、最大类间方差法(OSTU)法等[1-3]。但是在实际图片
欢迎:、、)
支持CAJ、PDF文件格式,仅支持PDF格式
【参考文献】
中国期刊全文数据库
叶芗芸,戚飞虎,吴健渊,许磊;[J];红外与毫米波学报;1997年05期
何昕;李晓华;周激流;;[J];计算机工程;2011年17期
张德刚;戴冠中;刘航;郝兴茂;李美峰;;[J];计算机应用研究;2008年06期
程培英;沈会良;;[J];计算机应用与软件;2008年10期
何晶;范九伦;李利;;[J];计算机工程与设计;2008年14期
闫三虎;胡卫东;罗小平;;[J];计算机系统应用;2011年06期
张引;[J];浙江大学学报(工学版);2001年03期
【共引文献】
中国期刊全文数据库
王恒迪,涂承媛;[J];北京工业大学学报;2002年04期
杨晓娟;宋凯;;[J];成都大学学报(自然科学版);2009年02期
杨波,叶俊勇,汪同庆,彭健;[J];传感器技术;2002年06期
钱雪彪,刘永智;[J];电子科技大学学报;2003年03期
程红;王志强;白新伟;;[J];地理与地理信息科学;2011年04期
汪毅;郭显久;于晓静;尹祥贵;;[J];大连水产学院学报;2008年06期
李凌;;[J];电脑知识与技术;2006年35期
韩配富;王航楠;李忠君;王洋;;[J];电子技术;2009年04期
陈燕龙;;[J];电子质量;2007年11期
李晓东;李志强;雷晓平;;[J];佛山科学技术学院学报(自然科学版);2010年05期
中国重要会议论文全文数据库
田原;蔡国瑞;王力;都东;;[A];第十一次全国焊接会议论文集(第2册)[C];2005年
中国博士学位论文全文数据库
张文涛;[D];电子科技大学;2000年
杨波;[D];重庆大学;2002年
居琰;[D];重庆大学;2002年
左奇;[D];西北工业大学;2003年
陈振学;[D];华中科技大学;2007年
王钰;[D];北京交通大学;2010年
魏宏喜;[D];内蒙古大学;2012年
郑煜;[D];中南大学;2012年
中国硕士学位论文全文数据库
范玉凤;[D];中国海洋大学;2010年
陈思;[D];哈尔滨理工大学;2010年
邹明明;[D];哈尔滨理工大学;2010年
樊剑剑;[D];南昌大学;2010年
谭川;[D];北京交通大学;2010年
张晨光;[D];昆明理工大学;2009年
张振;[D];解放军信息工程大学;2010年
闫青;[D];山东大学;2010年
胡惠灵;[D];合肥工业大学;2011年
强浩;[D];兰州理工大学;2011年
【二级参考文献】
中国期刊全文数据库
耿茵茵,唐良瑞;[J];北方工业大学学报;2000年03期
解梅,佟异;[J];电子学报;2003年10期
陆颖;[J];工程数学学报;2004年06期
叶芗芸,戚飞虎,吴健渊,许磊;[J];红外与毫米波学报;1997年05期
甘树坤;欧宗瑛;魏鸿磊;;[J];吉林化工学院学报;2006年01期
马银平;江伟;;[J];计算机工程;2009年22期
赵磊;杨路明;吴建辉;;[J];计算机应用;2007年04期
张引,潘云鹤;[J];计算机应用研究;1999年07期
冯星奎,颜祖泉,肖兴明,尹洪君;[J];计算机应用研究;2000年01期
戚飞虎,叶芗芸,李卫东,孙晓阳;[J];交通与计算机;1997年01期
【相似文献】
中国期刊全文数据库
秦琴;柴震海;王汝笠;;[J];科学技术与工程;2006年03期
孙忠贵;;[J];微计算机信息;2008年12期
蒋晓红;郑秋梅;杨发科;;[J];微计算机应用;2008年03期
洪健;陈继荣;;[J];计算机工程;2007年08期
周战荣;赵晓铭;刘皓淳;张瑜;郑立林;;[J];光学技术;2007年S1期
杨欢;;[J];微计算机信息;2009年21期
王俊杰,黄心汉;[J];电子技术应用;1998年10期
王建平,王竹林,王金玲,罗国军;[J];仪器仪表用户;2005年04期
张洪刚;陈光;刘刚;郭军;;[J];北京邮电大学学报;2006年02期
顾茂松;杨小冈;缪栋;刘云峰;;[J];计算机工程;2007年05期
中国重要会议论文全文数据库
黄金英;石国峰;王微微;;[A];2010年第三届尾矿库安全运行技术高峰论坛论文集[C];2010年
王青;陈磊;吴帧;;[A];2002年中国光学学会年会论文集[C];2002年
中国硕士学位论文全文数据库
魏宇璋;[D];南京信息工程大学;2008年
吴芳;[D];上海交通大学;2013年
吴倩;[D];武汉纺织大学;2010年
李江;[D];中国计量学院;2013年
梁宏希;[D];广东工业大学;2013年
郭佳;[D];武汉科技大学;2013年
罗超;[D];武汉理工大学;2013年
王刚;[D];山东师范大学;2013年
高美琴;[D];北京工业大学;2013年
方俊;[D];浙江工业大学;2011年
&快捷付款方式
&订购知网充值卡
400-819-9993
《中国学术期刊(光盘版)》电子杂志社有限公司
同方知网数字出版技术股份有限公司
地址:北京清华大学 84-48信箱 大众知识服务
出版物经营许可证 新出发京批字第直0595号
订购***:400-819-82499
服务***:010--
在线咨询:
传真:010-
京公网安备75号基于Java对图片进行二值化处理
一直以来对Java的图形处理能力表无力,但好像又不是那么一回事,之前用PHP做过一些应用,涉及到验证码的识别,其中有个图片二值化的步骤,今天换成Java来实现下
在java的扩展包javax.imageio中为我们提供了一个类叫ImageIO,这个类提供了一些执行简单编码和解码的静态便捷方法,具体说明大家可以翻下API看看
下面来说下关于图片二值化的原理:
1、首先要获取每个像素点的灰度值。
2、定义一个阀值。
3、将每个像素点的灰度值和它周围的8个像素点的灰度值相叠加再除以9,然后和阀值进行比较。
4、大于阀值则设为黑色,小雨则为白色。
下面贴下具体代码,注释很全
separator是File类的一个常量,因年代久远的关系,那时候的代码规范没有和现在一样,常量必须大写,属于历史遗留问题,不必太纠结(建议使用separator而不是"/",便于跨平台) 。
BufferedImage里的getRGB得到的是一个ARGB,A代表透明,R代表红色,G代表绿色,B代表蓝色。
包装类Integer里的parseInt方法,第二个可选参数为"要处理几进制的数"。
关于阀值,网上有许多算法,有兴趣的朋友可以自己研究下,这里我随机给出了一个中间数130。
关于图片的灰度值,这里使用简单的(R+G+B)/3。
1 import java.awt.C
2 import java.awt.image.BufferedI
3 import java.io.F
4 import java.io.IOE
6 import javax.imageio.ImageIO;
8 public class ImageTest {
public static void main(String[] args) throws IOException {
String filename = "D:" + File.separator + "/123.jpg";// separator是File里的一个常量,由于java历史遗留问题故为小写
File file = new File(filename);
BufferedImage bi = ImageIO.read(file);
// 获取当前图片的高,宽,ARGB
int h = bi.getHeight();
int w = bi.getWidth();
int rgb = bi.getRGB(0, 0);
int arr[][] = new int[w][h];
// 获取图片每一像素点的灰度值
for (int i = 0; i & i++) {
for (int j = 0; j & j++) {
// getRGB()返回默认的RGB颜色模型(十进制)
arr[i][j] = getImageRgb(bi.getRGB(i, j));//该点的灰度值
BufferedImage bufferedImage=new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);//
构造一个类型为预定义图像类型之一的 BufferedImage,TYPE_BYTE_BINARY(表示一个不透明的以字节打包的 1、2 或 4 位图像。)
int FZ=130;
for (int i = 0; i & i++) {
for (int j = 0; j & j++) {
if(getGray(arr,i,j,w,h)&FZ){
int black=new Color(255,255,255).getRGB();
bufferedImage.setRGB(i, j, black);
int white=new Color(0,0,0).getRGB();
bufferedImage.setRGB(i, j, white);
ImageIO.write(bufferedImage, "jpg", new File("D:"+File.separator+"new123.jpg"));
private static int getImageRgb(int i) {
String argb = Integer.toHexString(i);// 将十进制的颜色值转为十六进制
// argb分别代表透明,红,绿,蓝 分别占16进制2位
int r = Integer.parseInt(argb.substring(2, 4),16);//后面参数为使用进制
int g = Integer.parseInt(argb.substring(4, 6),16);
int b = Integer.parseInt(argb.substring(6, 8),16);
int result=(int)((r+g+b)/3);
//自己加周围8个灰度值再除以9,算出其相对灰度值
public static int
getGray(int gray[][], int x, int y, int w, int h)
int rs = gray[x][y]
+ (x == 0 ? 255 : gray[x - 1][y])
y == 0 ? 255 : gray[x - 1][y - 1])
y == h - 1 ? 255 : gray[x - 1][y + 1])
+ (y == 0 ? 255 : gray[x][y - 1])
+ (y == h - 1 ? 255 : gray[x][y + 1])
+ (x == w - 1 ? 255 : gray[x + 1][ y])
+ (x == w - 1
y == 0 ? 255 : gray[x + 1][y - 1])
+ (x == w - 1
y == h - 1 ? 255 : gray[x + 1][y + 1]);
return rs / 9;
看下效果吧:
> 本站内容系网友提交或本网编辑转载,其目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请及时与本网联系,我们将在第一时间删除内容!
车牌识别包括预处理.定位.字符分割和字符识别等几部分.在本文中,我们仅讨论预处理的二值化过程.二值化的好坏决定着车牌识别的精度.事实上,要提高车牌识别精度必须要有好的二值化方法.本文提出了一种新的直接基于彩色图像的二值化方法. 车牌识别,一直存在两种思路.一是将彩色图像灰度化,然后二值化等等:二是直接基于彩色图像. 由于直接基于彩色图像的方法大都未取得很好的 ...
一:基本原理该方法是图像二值化处理常见方法之一,在Matlab与OpenCV中均有实现.Otsu Threshing方法是一种基于寻找合适阈值实现二值化的方法,其最重要的部分是寻找图像二值化阈值,然后根据阈值将图像分为前景(白色)或者背景(黑色).假设有6x6的灰度图像,其像素数据及其对应的直方图如下图:阈值寻找方法首先假设是为T=3,则背景像素的比重.均值 ...
Kittler二值化方法,是一种经典的基于直方图的二值化方法.由J. Kittler在1986年发表的论文“Minimum Error Thresholding”提出.论文是对贝叶斯最小错误阈值的准则做了改进,使得计算更加的简单和有效. Divijver 和 Kittler的贝叶斯最小错误准则为:
因为需要求解二次方程和对正态分布的均值和方差进 ...
图像二值化的目的是最大限度的将图象中感兴趣的部分保留下来,在很多情况下,也是进行图像分析.特征提取与模式识别之前的必要的图像预处理过程.这个看似简单的问题,在过去的四十年里受到国内外学者的广泛关注,产生了数以百计的阈值选取方法,但如同其他图像分割算法一样,没有一个现有方法对各种各样的图像都能得到令人满意的结果.
在这些庞大的分类方法中, ...
灰度图imggray 有了上面的基础,灰度图就相当简单了 彩色图转灰度方法: 1.浮点算法:Gray=R*0.3+G*0.59+B*0.11 2.整数方法:Gray=(R*30+G*59+B*11)/100 3.移位方法:Gray =(R*28+G*151+B*77)&&8;
??4.平均值法:Gray=(R+G+B)/3; 5.仅取绿色:Gr ...
这是篇很古老的论文中的算法,发表与1994年,是清华大学黄良凯(Liang-kai Huang) 所写,因此国外一些论文里和代码里称之为Huang's fuzzy thresholding method.虽然古老也很简单,但是其算法的原理还是值得学习的.
该论文的原文可从此处下载: Image thresholding by minimizing
在图像处理应用中二值化操作是一个很常用的处理方式,例如零器件图片的处理.文本图片和验证码图片中字符的提取.车牌识别中的字符分割,以及视频图像中的运动目标检测中的前景分割,等等.
较为常用的图像二值化方法有:1)全局固定阈值:2)局部自适应阈值:3)OTSU等.
全局固定阈值很容易理解,就是对整幅图像都是用一个统一的阈值来进行二值化:
局部自适应阈 ...
转自:/Imageshop/p/3302850.html 正文:
这是篇很古老的论文中的算法,发表与1994年,是清华大学黄良凯(Liang-kai Huang) 所写,因此国外一些论文里和代码里称之为Huang's fuzzy thresholding method.虽然古老也很简单,但是其算法的原理还 ...posts - 79,&
comments - 588,&
trackbacks - 0
& & & 参考文档:
      & & &&
一、问题的由来
&&&&& 一个现实: 当用照像机拍摄一副黑纸白字的纸张时,照相机获得的图像并不是真正的黑白图像。不管从什么角度拍摄,这幅图像实际上是灰度或者彩色的。除非仔细的设置灯光,否则照相机所拍摄的放在桌子上的纸张图像并不能代表原始效果。不像在扫描仪或打印机内部,想控制好桌子表面的光源是非常困难的。这个开放的空间可能会受到台灯、吊灯、窗户、移动的影子等影响。人类的视觉系统能自动补偿这些,但是机器没有考虑到这些因素因此拍出的效果会很差。
& & &这个问题在处理那种高对比度的艺术线条或文字时尤为突出,因为这些东西都是真正的黑色或白色。而摄像头会产生一副具有不同等级的灰度图像。许多应用都必须清楚的知道图像的那一部分是纯黑或纯白,以便将文字传递给OCR软件去识别。这些系统无法使用灰度图像(典型的是8位每像素),因此必须将他们转换为黑白图像。这有很多种方式去实现。在某些情况下,如果这些图像最终是给人看的,这些图像会使用一些抖动技术,以便使他们看起来更像灰度图像。但是对于机器处理的过程,比如文字识别,选择复制操作,或多个图像合成,系统就不可以使用抖动的图像。系统仅仅需要简单的线条、文字或相对大块的黑色和白色。从灰度图像获得这种黑白图像的过程通常称作为阈值化。
& & &有很多种方式来阈值化一副图像,但是基本的处理过程都是检查每一个灰度像素,然后决定他是白色和还是黑色。本文描述了已经开发的不同的算法来阈值一副图像,然后提出了一种比较合适的算法。这个算法(这里我们称之为快速自适应阈值法)可能不是最合适的。但是他对我们所描述的问题处理的相当好。
二、全局阈值法
&&&&&& 在某种程度上说,阈值法是对比度增强的极端形式,或者说他使得亮的像素更亮而暗的像素更暗。最简单的(也是最常用的)方法就是将图像中低于某个阈值的像素设置为黑色,而其他的设置为白色。那么接着问题就是如何设置这个阈值。一种可能性就是选择所有可能取值的中间值,因此对于8位深的图像(范围从0到255),128将会被选中。这个方法在图像黑色像素确实在128以下,而白色也在128以上时工作的很好。但是如果图像过或欠曝光,图像可能全白或全黑。所以找到图像实际的取值范围代替可能取值范围会更好些。首先找到图像中所有像素的最大值和最小值,然后取中点作为阈值。一个更好的选择阈值的方法是不仅查看图像实际的范围,还要看其分布。比如说,你希望图像类似于一副黑色线条画,或者在白纸上的文字效果,那么你就期望大部分像素是背景颜色,而少部分是黑色。一副像素的直方图可能如图1所示。
& & & & & & & & & & & & & & & & & && &
& &&                            图1&
& & & &上图中,可以发现一个背景颜色的大峰值,以及一个黑色墨水的小的峰值。根据周围的光线整个曲线可想向左或者向右偏移,但是在任何情况下,最理想的阈值就是在两个峰值之间的波谷处。这在理论上很好,但是他在实际中到底表现如何呢。
& & &                              图 2&
& & & 图2及其直方图显示整个技术工作的很好。平滑后的直方图显示出2个潜在的峰值,通过拟合直方图曲线或简单的取两个峰值之间的平均值来计算出一个近似理想阈值并不是一件困难的事情。这不是一个典型的图像,因为他有大量的黑色和白色的像素点。算法必须还要对类似图3这样的图像进行阈值处理。这这幅图像的直方图中,较小的黑色峰值已经掩埋在噪音中,因此要可靠地在峰值之间确定哈一个最小值是不太可能的。
& & & & & &
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & 图 & 3
& & & &在任何情况下,一个大的(背景)峰值总是存在的并且也容易找到,因此,一个有用的阈值策略可描述如下:
  1)& 计算直方图。
& & &2)& 按照一定的半径对直方图数据进行平滑,并计算平滑后数据的最大值。平滑的目的减少噪音对最大值的影响,如图2和图3所示。
& & &3)& 根据上述峰值和最小值(不包括在直方图中为0的项)的距离按照一定的比例选择阈值。
& & & 试验表明这个距离的一半能够对很大范围内的图像产生相当好的效果,从非常亮到几乎完全黑的图像。比如,在图3中,峰值在215处,而最小值为75,因此可以使用的阈值为145。图4是四副在不同的光照条件下抓取的图像以及根据上述基于直方图技术阈值处理后的效果。尽管私服图像有这较广的光照范围(可以从直方图中看出),该算法都选择了较为合适的阈值,而阈值处理后的图像基本一样。
& & & & & & & & & & &&
& & & & & & & & & & & & &&
& & & & & & & & & & &&
& & & & & & & & & & &
                                图 & & & & 4
& & & &这个基于直方图的全局阈值技术对于如上面所举的那些光线条件均匀或那些光线变化不多的部分图像处理的很好。但是对于在正常办公室光照条件下他无法获得满意的结果。因为对整个图像使用一个相同的阈值,图像的部分区域变得太白而其他地区又太黑。因此大部分文字变得不可读,如图5所示。
& & & & & & &
                                  图 & & & & 5
& & & &从光照不均匀的纸张图像中产生较好的二值化图像需要一种自适应的阈值算法。这个技术根据每个像素的背景亮度来改变阈值。下面的讨论都配以图5先显示新算法的效果。这是一个具有挑战性的测试,因为图像边缘有光源,并且其在白色背景上有黑色文字(PaperWorks整个词,以及黑色背景中的白色文字(&XEROX&),还有白色背景中的灰色文字(&The best way。。。&)还有不同的阴影和一个在单词&PaperWorks&下很细小的水平黑色线。
三 自适应阈值
&&&&&& 一个理想的自适应阈值算法应该能够对光照不均匀的图像产生类似上述全局阈值算法对光照均匀图像产生的效果一样好。 为了补偿或多或少的照明,每个像素的亮度需要正规化,之后才能决定某个像素时黑色还是白色。问题是如何决定每个点的背景亮度。一个简单的方式就是在拍摄需要二值图片之前先拍一张空白的页面。这个空白的页面可以当做参考图像。对于每一个要处理的像素,在处理前对应的参考图像像素都将从其中减去。
&&&&&& 只要在参考图像和实际要处理的图像拍摄时光照条件没有发生任何变化,这个方法能产生非常好的效果,但是,光照条件会收到人、台灯或其他移动物体的影子的影响。如果房间有窗户,那么光照条件还会随着时间变化而改变。一个解决方案就是在同样的位置,同样的时刻拍摄一种空白的页面作为参考,但是这如果使用扫描仪一样不太方便
&&&&&& 另外一种方式就是通过一些关于图像实际该是什么样的假设来估计每个像素的背景亮度。例如,我们可以假设,图像大部分是背景(也就是白色),黑色只占图像的小部分。另外一个假设就是背景光改变相对较为缓慢。基于以上假设有很多算法都可行。由于没有关于自适应阈值的数学理论,因此,也就没有一个标准或者最优的方法来实现它。代替的是,有一些特别的方法要比另外一些更为使用的多。由于这些方法比较特别,因此测量他们的性能比较有用。为此,Haralick 和 Shapiro提出了以下建议:区域需和灰度调统一;区域内部应该简单,没有过多的小孔;相邻的区域应该有显著的不同值;每个部分的边缘也应该简单,不应凹凸不平,其空间上要准确。
&&&&&& 根据Pratt的理论,对于图像二值化,还没有任何量化性能指标提出过。似乎主要评价算法性能的方式就是简单看看结果然后判断其是否很好。对于文字图像,有一个可行的量化办法:不同光照条件下的图片使用不同的二值化算法处理的后的结果被送往OCR系统,然后将OCR识别的结果和原文字比较。虽然该法可能有用,但是他不能用在以下描述的算法中,因为不可能给出一个看起来好的标准。对于一些交互式的应用,比如复制黏贴操作用户必须等到二值的处理。因此另外一个重要的指标就是速度。以下部分提出了不同的自适应阈值算法已经他们产生的结果。
四、基于Wall算法的自适应阈值
&&&&&& R. J. Wall开发的根据背景亮度动态计算阈值的算法描述可见《Castleman, K. Digital Image Processing. Prentice-Hall Signal Pro-cessing Series, 1979.》 。以下描述基本是按照其论文的。首先,将图像分成较小的块,然后分别计算每块的直方图。根据每个直方图的峰值,然后为每个块计算其阈值。然后,每个像素点的阈值根据相邻的块的阈值进行插值获得。图6是用该算法对图5进行处理的结果。
& & & & & & & & & & & & & & & & & & & & & & & & & & & &&
                          & & & & & &  图 & & 6
& & &这个图像被分成9个块(3*3),每个块的阈值选择为比峰值低20%。这个结果比全局阈值要好,但是他的计算量大,速度交慢。另外一个问题就是,对于有些图像,局部的直方图可能会被大量的黑色或白色点欺骗,导致阈值在整幅图像中不是平滑的变化,结果可能非常糟糕,见图7.
& & & & & &&
                           & & &图 & &7&
五、快速自适应阈值
&&&&&& 文献中记载的大部分算法都比Wall算法更为复杂,因此需要更多的运行时间。开发一个简单的更快的自适应阈值算法是可行的,因此这接我们介绍下相关的理论。
& & & &算法基本的细想就是遍历图像,计算一个移动的平均值。如果某个像素明显的低于这个平均值,则设置为黑色,否则设置为白色。仅需一个遍历就够了,用硬件去实现算法也很简答。注意到下面的算法和IBM 1968年用硬件实现的算法的相似性是比较有趣的。
& & & 假设Pn为图像中位于点n处的像素。此刻我们假设图像是由所有行按顺序连接起来的一个单行。这这导致了在每行开始的时候会产生一些异常,但这个异常要比每行都从零开始要小。
& & & &假设fs(n)是点n处最后 s个像素的总和:
& & & & & & & &&&
& & & &最后的图像T(n)是1(黑色)或0(白色)则依赖于其是否比其前s个像素的平均值的百分之t的暗。
& & & &对于s使用图像的1/8宽而t取值15似乎对不同的图像都能产生较好的效果。图8显示了使用该算法从左到右扫描行的结果。
& & & & & &
            图 & 8                            图 & 9 &
& & & &图9是使用相同算法从右到左处理的结果,注意在这个图像中,最左侧的较小的文字是不完整的。在字符PaperWorks中也有更多的孔洞。同样,最右侧的黑色边缘也窄很多。这主要是由于图像的背景光源是从左到右逐渐变黑的。
& & & &另外一个问题就是如何开始算法,或者说怎么计算g(0)。一个可能性是使用s*p0,但是由于边缘的结果,P0不是一个典型的值。因此另外一个可行是127*s(基于8位图像的中值)。不论如何,这两种方案都只会影响到g的很少一部分值。在计算gs(n)时,g(0)的权重是:
& & & & & & &
& & & 因此如果s=10,那么对于任何的n&6,g(0)的贡献则少于g10(n)的10%,对于n&22,g(0)的贡献值则少于1%。对于s=100,在8个像素之后g(0)的共享就小于10%,在68像素后则少于1%.
& & & &如果计算均值时不是从某一个方向效果应该会更好,图12显示使用另外一种方法来计算平均值的效果。该方法通过计算点n对称两侧的像素的平均值来代替某一个方向的平均值。此时f(n)的定义如下:
& & & 另外一种替代的方法就是交替的从左到右及从右到左计算平均值,如下所示:
& & & &这产生的效果和中心平均相比,没有多大的区别。
& & & & 一个小小的修改可能会对大部分图像产生更好的效果,那就是保留前一行的平均效果(和当前行反方向的),然后把当前行的平均值和上一上的平均值再取平均作为新的平均值,即使用:
& & & &这使得阈值的计算考虑了垂直方向上的信息,产生的结果如图:
& & & & & & & & &
& & & &请注意他对字符的分割的效果。这也是为数不多的保留了PaperWorks下那条水平线的算法之一。
   部分原文因现在看来已经不合理了,未做翻译。
& & & 从上面的东西来看,Wellner 自适应滤波阈值实际上就是对像素做指定半径的一维平滑,然后原像素和平滑后的值做比较来决定黑还是白。文章中很大一部分篇幅都是在讨论取样的那些像素的方向问题,是完全在左侧、完全在右侧还是左右对称,抑或是考虑到前一行的效果。 但是,总的来看,他只考虑到了行方向上的像素对平滑的影响。之后,Derek Bradley和Gerhard Roth 在他们的论文Adaptive Thresholding Using the Integral Image 中 提出了以W*W为模板的矩形区域的二维平滑值来代替一维加权值。从而抛开了一维平滑的方向性问题。
& & &当然,对于二维平滑他们提出了0(1)时间复杂度的算法,其实很简单,就是先计算整幅图像的累加表。然后再一次循环通过加单的加减获得以某个像素为中心的累加值。
& & 下面给出一个简答的从左到右的原始的Wellner算法的代码(我认为那个所有行并成一行并不会好,并且如果那样做还要考虑扫描行的无效数据):
public static void WellneradaptiveThreshold1(FastBitmap bmp, int Radius = 5, int Threshold = 15)
if (bmp == null) throw new ArgumentNullException();
if (bmp.Handle == IntPtr.Zero) throw new ArgumentNullException();
if (bmp.IsGrayBitmap() == false) throw new ArgumentException("Binaryzation functions can only be applied to 8bpp graymode Image.");
if (Radius & 0 || Radius & 255) throw new ArgumentOutOfRangeException();
if (Threshold & 0 || Threshold & 100) throw new ArgumentOutOfRangeException();
int Width, Height, Stride, X, Y;
int Sum, InvertThreshold, XX, OldV
Width = bmp.W Height = bmp.H Stride = bmp.S Pointer = bmp.P InvertThreshold = 100 - T
byte* Row = (byte*)Marshal.AllocHGlobal(Width);
for (Y = 0; Y & H Y++)
Pointer = bmp.Pointer + Stride * Y;
Sum = *Pointer * R
Win32Api.CopyMemory(Row, Pointer, Width);
for (X = 0; X & W X++)
XX = X - R
if (XX & 0) XX = 0;
Sum += Row[X] - Row[XX];
if (Row[X] * 100 * Radius & Sum * InvertThreshold)
Pointer[X] = 0;
Pointer[X] = 255;
Marshal.FreeHGlobal((IntPtr)Row);
  这个是基于我自己的一个FastBitmap类的,要改成GDI+的 Bitmap 类也很简单,注意二值处理一般只针对灰度图像。
& & &操作中必须先对于行数据进行一个备份,因为在计算过程中会改变像素值的。
& & &同时也给出二维的Wellner算法的代码供大家参考:
public static void WellneradaptiveThreshold2(FastBitmap bmp, int Radius = 5, int Threshold = 50)
if (bmp == null) throw new ArgumentNullException();
if (bmp.Handle == IntPtr.Zero) throw new ArgumentNullException();
if (bmp.IsGrayBitmap() == false) throw new ArgumentException("Binaryzation functions can only be applied to 8bpp graymode Image.");
if (Radius & 0 || Radius & 255) throw new ArgumentOutOfRangeException();
if (Threshold & 0 || Threshold & 100) throw new ArgumentOutOfRangeException();
int Width, Height, Stride, X, Y;
int Sum, X1, X2, Y1, Y2, Y2Y1, InvertT
Width = bmp.W Height = bmp.H Stride = bmp.S Pointer = bmp.P InvertThreshold = 100 - T
int* Integral = (int*)Marshal.AllocHGlobal(Width * Height * 4);
int* IndexOne, IndexT
for (Y = 0; Y & H Y++)
Pointer = bmp.Pointer + Stride * Y;
IndexOne = Integral + Width * Y;
for (X = 0; X & W X++)
if (Y == 0)
*IndexOne = S
*IndexOne = *(IndexOne - Width) + S
IndexOne++;
Pointer++;
for (Y = 0; Y & H Y++)
Pointer = bmp.Pointer + Stride * Y;
Y1 = Y - R Y2 = Y + R
if (Y1 & 0) Y1 = 0;
if (Y2 &= Height) Y2 = Height - 1;
IndexOne = Integral + Y1 * W
IndexTwo = Integral + Y2 * W
Y2Y1 = (Y2 - Y1) * 100;
for (X = 0; X & W X++)
X1 = X - R X2 = X + R
if (X1 & 0) X1 = 0;
if (X2 &= Width) X2 = Width - 1;
Sum = *(IndexTwo + X2) - *(IndexOne + X2) - *(IndexTwo + X1) + *(IndexOne + X1);
if (*Pointer * (X2 - X1) * Y2Y1 & Sum * InvertThreshold)
*Pointer = 0;
*Pointer = 255;
Pointer++;
Marshal.FreeHGlobal((IntPtr)Integral);
  其中if (*Pointer * (X2 - X1) * Y2Y1 & Sum * InvertThreshold) 是为了避免耗时的除操作,提高程序速度。
& & & 其实,上述计算平均值的方式并不是最快的,有能达到其2倍以上速度的代码。 并且上述算法还存在一个问题,就是对于稍微大一点的图像,累加的过程会超出int所能表达的范围,从而使得结果不正确,当然,在C#中,我们可以使用long类型来保存结果,但是这造成2个后果:一是程序占用内存更大,二十对于现在大部分的32位操作系统,long所代表的64位数的计算速度比32位要慢不少。当然对于64位就不同了。
& & & 关于论文中的贴的效果,似乎按照他的算法的参数是达不到的,不知道是不是因为我们的原始图片是从其论文中截图得到而有降质的原因。
& & & 总的而言,这种基于局部特征的二值,在不少情况下比全局阈值的一刀切的效果要好些,对于Wellner来说,搜索的半径的大小对于结果的影响还是很大的,不过也不一定。比如Lena这个美女图:
& && && & &
& & & & & & & & & & & & & 原图 & & & & & & & & & & & & & & & & & & & & & & & & & & & & & 大律法                   & & S=50,T=15的效果。
阅读(...) 评论()

参考资料

 

随机推荐