园博园,基于IBM SWT技术的图像差异检测 (博园首发)

声明:本文属魏强(乘风归去)(http://www.cnblogs.com/cfgq)原创
本文首发于博客园
转载请注明出处:http://www.cnblogs.com/cfgq,谢谢合作。
PDF下载,由于附件代码较大,如需要代码,请添加QQ群:174297097与我联系
基于IBM SWT技术的图像差异检测 (博园首发)园博园

引言

SWT(Standard Widget Toolkit,标准窗口小部件工具箱),是IBM公司提供的Java桌面应用的开发包,SWT中包含了处理图像的API,即SWT Image API,Java程序员可以利用此API进行简单的图像处理。本文使用SWT Image API实现了图像处理中较为复杂的二值化、腐蚀、膨胀等算法,并且使用图像差异检测的应用实例展示算法的应用,主要目的是让读者熟悉IBM SWT Image技术。

图像本质

图像是由像素点组成,像素是最小的颜色单位,每个像素又是由一个到多个的字节组成,一个字节是由0-255的数字表示,可以说图像数据就是一个0-255的字节数组,二维图像数据就是一个二维像素数组。
对于RGB色彩空间,像素的颜色是由R G B三个分量决定,每个分量是一个字节(0-255),也就是说对于一般图像某个字节数据就是某一像素的颜色分量的数值,本文介绍的算法主要是读取图像数据的字节数组,按照算法规则修改数组数据(也就是R G B颜色分量的数值),改变像素颜色。
SWT中使用org.eclipse.swt.graphics.Image类代表图像对象,org.eclipse.swt.graphics.ImageData代表图像中具体的图像数据,通过org.eclipse.swt.graphics.ImageLoader的load方法,可以加载ImageData对象。
ImageData的data属性代表图像数据的字节数组,height属性代表图像的高度(像素的个数),width属性代表图像的宽度(像素的个数),bytesPerLine属性代表每行的字节数组,对于一般的数字图像,可以认为bytesPerLine/width=每像素占的字节数,像素的每个字节代表颜色空间的一个分量值。

图像处理算法的应用

本文的例子,是使用两张相似图像(在图像显示的某些地方有不同点,大部分是相同的,类似《大家来找茬》游戏中的对比图片),经过一系列的处理,生成可以清晰显示两张图像不同点位置的图像,图1显示的是刚开始的两张对比图像。

图 1. 对比图像

基于IBM SWT技术的图像差异检测 (博园首发)园博园
如果用肉眼分辨图像中的不同点,是靠运气和观察力的,这也是“大家来找茬”游戏的乐趣所在。那么,如何用机器来识别呢?接下来,文章将根据如下列表的顺序,对两张图像进行处理
l 图像相减
l 灰度图像
l 二值化
l 图像膨胀
l 图像腐蚀
l 均值滤波
每个步骤都是在前一步骤的基础上进行,两张图像不同点的位置会随着一步一步的图像处理变的越来越清晰。读者还可以查看本文的附件代码进行学习。

图像相减

图像相减的目的是生成两张图片不同点的大致轮廓,首先获得上述两张图像数据的字节数组(即ImageData的data属性对象),由于两张图片大小相同,类型相同,将两个字节数组中的相同位置的数值进行相减并求绝对值,放置到新开辟字节数组中的同一位置,新数组的长度与原图像字节数组相同。然后,将新开辟的字节数组保存成图像,那么就完成了图像的相减,生成了新的一个图像,大小、类型都与原图像相同,清单1是将两个图像数据相减生成新的图像数据的方法。

清单 1. 图像相减代码

public static ImageData absDiff(ImageData source, ImageData target) {
byte[] sourceData = source.data;
byte[] tagetData = target.data;
if (sourceData.length == tagetData.length) {
for (int i = 0; i < sourceData.length; i++) {
sourceData[i] -= tagetData[i];
}
}
source.data = sourceData;
return source;
}
经过图像相减后生成的新图像如图2所示。

图 2. 图像相减结果

基于IBM SWT技术的图像差异检测 (博园首发)园博园
两张图像同一位置的像素点,如果是相等的话就代表两个像素点的颜色分量都相等。图像数据的字节数组相减,实际上就是颜色分量的相减,因为每个字节代表具体的分量值。相等像素相减后,新图像中对应的像素的颜色分量都将变为0,显示的就是纯黑色,不同像素进行相减,颜色分量不一定为0.,显示的也就不是黑色,结果也就成为图2所示了。

灰度图像

灰度图像是图像处理领域的基础,它使得图像就黑白两色,灰度图像更加突出图像的特征,并且容易处理,不容易受到干扰。图像灰度化的原理是将颜色分量设置为相同,比如R=G=B=0或者R=G=B=255,事实上只要RGB三个分量相同,并且取值在0-255之间即可,SWT中实现了这样的接口进行图像的灰度处理,清单3展示了该接口的使用。

清单 2. SWT灰度图像

//newImage为图2显示的图像,是Image对象
Image grayImage = new Image(null, newImage, SWT.IMAGE_GRAY);
SWT的灰度图像转换非常简单,效果如图3所示。

图 3. 灰度图像


基于IBM SWT技术的图像差异检测 (博园首发)园博园
灰度图像中,颜色只有黑色或者白色,这样更加方便计算机的处理。

二值化

图像的二值化是在灰度图像的基础上,一种突出特征的技术,实现二值化首先需要选定阀值,该阀值在0-255之间,遍历图像数据字节数组的每个字节,如果小于阀值,就将该数据置换为0,如果大于阀值,就置换为255,那么这样黑白关系将非常明显。从上面的描述中可以知道阀值的选择是关键,选大或者选小了都会影响图像关键部分的显示。目前也有很多具体的阀值选取算法,有兴趣的读者可以自行查阅,本文实现了通用的二值化算法,阀值作为参数任意设定。二值化算法如清单3所示。

清单 3. 二值化

public static ImageData threshold(int threshold, ImageData source) {
byte[] sourceData = source.data;
for (int i = 0; i < sourceData.length; i++) {
if (sourceData[i] <= threshold) {
sourceData[i] = 0;
} else {
sourceData[i] = (byte) 255;
}
}
source.data = sourceData;
return source;
}
清单3中方法参数threshold就是选取的阀值,source是原图像的图像数据,返回二值化后的图像数据。图4展示了阀值为40的二值化图像效果。

图 4. 二值化图像

基于IBM SWT技术的图像差异检测 (博园首发)园博园


图像膨胀

在了解图像膨胀和腐蚀之前,可以先了解数学形态学的概念,数学形态学在图像处理中的应用主要是利用形态学的基本运算,对图像进行观察和处理,从而达到改善图像质量的目的;描述和定义图像的各种几何参数和特征,如面积、周长、连通度、颗粒度、骨架和方向性等。图像膨胀属于形态学的一个操作,用术语来讲,膨胀是将与物体接触的所有背景点合并到物体中,使目标增大,可添补目标中的空洞。从本例中的直观效果来讲,膨胀的目的是消除白色块中黑色的零星的像素点,使得视觉上成为完全的白色一整块。效果如图5所示。

图 5. 膨胀图像

基于IBM SWT技术的图像差异检测 (博园首发)园博园


图像膨胀的算法是用一个结构元素(一般是3×3的大小)扫描图像中的每一个像素,移动结构元素使得扫描的当前像素作为结构元素的中心点,用结构元素中的每一个像素与其覆盖的像素做“与”操作,如果都为0,则该像素为0,否则为255。代码如清单4所示。

清单 4. 膨胀代码

public static ImageData dilate(ImageData source) {
byte[] sourceData = source.data;
int height = source.height;
int width = source.width;
byte[] tempData = new byte[sourceData.length];
System.arraycopy(sourceData, 0, tempData, 0, sourceData.length);
int flag = 1;
for (int i = 1; i < height - 1; i++) {
for (int j = 1; j < width - 1; j++) {
flag = 1;
for (int m = i - 1; m < i + 3; m++) {
for (int n = j - 1; n < j + 3; n++) {
if (tempData[i * width + j] == (byte) 255
|| tempData[m * width + n] == (byte) 255) {
flag = 0;
break;
}
}
if (flag == 0) {
break;
}
}
if (flag == 0) {
sourceData[i * width + j] = (byte) 255;
} else {
sourceData[i * width + j] = 0;
}
}
}
source.data = sourceData;
return source;
}

图像腐蚀

腐蚀的作用是消除物体边界点,使目标缩小,可以消除小于结构元素的噪声点。腐蚀后的效果如图6所示。

图 6. 腐蚀图像

基于IBM SWT技术的图像差异检测 (博园首发)园博园


腐蚀的算法思想是用一个结构元素(一般是3×3的大小)扫描图像中的每一个像素,移动结构元素使得扫描的当前像素作为结构元素的中心点,用结构元素中的每一个像素与其覆盖的像素做“与”操作,如果都为255,则该像素为255,否则为0。代码如清单5所示。

清单 5. 腐蚀代码

public static ImageData erode(ImageData source) {
byte[] sourceData = source.data;
int height = source.height;
int width = source.width;
byte[] tempData = new byte[sourceData.length];
System.arraycopy(sourceData, 0, tempData, 0, sourceData.length);
int flag = 1;
for (int i = 1; i < height - 1; i++) {
for (int j = 1; j < width - 1; j++) {
flag = 1;
for (int m = i - 1; m < i + 2; m++) {
for (int n = j - 1; n < j + 2; n++) {
if (tempData[i * width + j] == 0
|| tempData[m * width + n] == 0) {
flag = 0;
break;
}
}
if (flag == 0) {
break;
}
}
if (flag == 0) {
sourceData[i * width + j] = 0;
} else {
sourceData[i * width + j] = (byte) 255;
}
}
}
source.data = sourceData;
return source;
}

均值滤波

从图6中,读者可能已经发现,图中存在一些比较细微的小白点零星的分布在图像当中,白色大块的边缘也有一些散落的小白点,实际上这些从原图上看是察觉不出有什么不同的,也就是说这些点并不是图像的不同点。在这样的语境下,这些点都被称为噪声点,本例使用均值滤波算法对图像执行过滤操作,执行完过滤的图像如图7所示。

图 7. 均值滤波图像

基于IBM SWT技术的图像差异检测 (博园首发)园博园


经过滤波以后,图像的边缘显得平滑,轮廓更加清晰,这为计算机进行进一步处理提供了条件,图7到目前为止已经清晰的显示出两张图像不同点的位置(白色大块部分)。滤波算法如清单6所示。

清单 6. 均值滤波代码

public static ImageData middle(ImageData source) {
byte[] sourceData = source.data;
int height = source.height;
int width = source.width;
byte[] tempData = new byte[sourceData.length];
System.arraycopy(sourceData, 0, tempData, 0, sourceData.length);
for (int i = 1; i < height - 1; i++) {
for (int j = 1; j < width - 1; j++) {
int sum = 0;
for (int m = i - 1; m < i + 2; m++) {
for (int n = j - 1; n < j + 2; n++) {
byte b = tempData[m * width + n];
sum += b;
}
}
sum = sum / 9;
sourceData[i * width + j] = (byte) sum;
}
}
source.data = sourceData;
return source;
}
有兴趣的读者可以继续学习图像的相关算法,对图像做进一步的处理,更加突出图像的异同。

总结

本文利用具体的例子,介绍了如何使用SWT Image API开发复杂的图像应用,实现了几种常用的图像算法,相信读者可以从本文中进一步了解SWT Image API,掌握图像操作的一些基本原理。Java中的图像操作,SWT Image API是一个不可多得的选择。由于本人知识水平有限,如果有错误的地方请联系指正。
Tags:  绿博园 淘博园 济南园博园 深圳园博园 园博园

延伸阅读

最新评论

发表评论