码迷,mamicode.com
首页 > 其他好文 > 详细

骰子定位识别

时间:2015-08-05 01:04:40      阅读:1018      评论:0      收藏:0      [点我收藏+]

标签:机器视觉   模式识别   图像分割   

引言

一年前我还在上海从事过机器视觉软件的开发,时光荏苒。这是在公司期间做了一个有趣的项目,现讲一下其主要思想及如何实现。
先来看一下效果图,Look
技术分享
嗯,看的出来,虽然背景光线不均匀,虽然骰子挨的那么近,还是很好的识别出来,程序的健壮性很强嘛。PS.为避免不必要的麻烦,我将自己的姓名和联系方式马赛克掉,嘿嘿。
这里程序的主要功能是识别出场景中存在多少粒骰子,以及每个骰子的位置,点子数,还有一些其他统计信息。当然,这只是一个机器视觉里的一个小Demo,可以继续完善。

思路

这是怎么做到的呢?这属于模式识别问题了。思路如下:

  1. 首先需要将目标(这里是整个骰子区域)从背景中正确分离出来;
  2. 将目标正确分离开来,即骰子之间要分离正确;
  3. 对单个骰子进行阈值分割,统计其中心坐标。

问题的关键点在于,第一步中如何正确将目标从背景中分离以及第二步沾黏的物体如何分离开来。

方法

顶帽变换

非均匀光照的最终结果导致了区域的分割错误(一些区域错误地分类了),且骰子的某些部分没有提取出来。顶帽变换的一个重要用途就是校正不均匀光照的影响。
顶帽(Top-hat)变换
原图像与开运算结果图之差。

dst=tophat(src,element)=src?open(src,element)

与顶帽变换相反的是底帽(bottom-hat)变换:
闭运算结果图与原图像之差。
dst=blackhat(src,element)=close(src,element)?src

技术分享
下面分割花生为例。用手机在室内环境下将花生放在黑色鼠标垫上拍摄的。没有额外打光,只是打开相机的闪灯光,拍摄效果还行。但是,这样的结果很容易受到光照影响,可以看出,图像中间最为明亮,边缘都有些黑暗,对比度不是太明显。用一个半径为40的圆盘形结构元进行开运算,可以看出图像背景已经均匀了,有点类似于执行了一次滤波操作。图3-4依次展示了顶帽变换之后的图像(图像减去其开操作),底帽变换之后的图像(闭操作减去原图像),顶帽变换联合底帽变换(原图像加上顶帽变换减去底帽变换)。经过处理之后的图像对比度明显变大,这样经过阈值分割之后,就可以得到正确的分割结果了。

距离变换与分水岭算法

距离变换

距离变换图算法是一种针对栅格图像的特殊变换,是把二值图像变换为灰度图像,其中每个像素的灰度值等于它到栅格地图上相邻物体的最近距离。目前被广泛应用于计算机图形学、GIS空间分析和模式识别等领域。
按距离类型划分,距离变换可分为:非欧氏距离变换和欧氏距离变换(EDT)。其中EDT精度高,与实际距离相符,应用更广泛。
基本思想是把离散分布在空间中的目标根据一定的距离定义方式生成距离图, 其中每一点的距离值是到所有空间目标距离中最小的一个。
基于“欧几里德距离”公式的距离变换图算法 :
在二维平面上定义两点,那么他们之间的欧氏距离表示为 :

D=(x1?x2)2+(y1?y2)2???????????????????

在二值图像中,1代表目标点,0代表背景;在灰度图像中,栅格的灰度值表示该栅格点到最近目标点的距离值。这样一张M×N的图像可以表示为一个二维数组A[M][N],其中A[i][j]=1对应的栅格表示目标点,A[i][j]=0对应的栅格表示背景点。设B=(x,y)|A[i][j]=1为目标点集合,则欧氏距离变换就是对A中所有的栅格点求:
D[i][j]=min{Distance[(i,j),(x,y)]}

其中 ,从而得到二值图像A的欧氏距离变换图。

分水岭算法

分水岭分割方法,是一种基于拓扑理论的数学形态学的分割方法,其基本思想是把图像看作是测地学上的拓扑地貌,图像中每一点像素的灰度值表示该点的海拔高度,每一个局部极小值及其影响区域称为集水盆,而集水盆的边界则形成分水岭。分水岭的概念和形成可以通过模拟浸入过程来说明。在每一个局部极小值表面,刺穿一个小孔,然后把整个模型慢慢浸入水中,随着浸入的加深,每一个局部极小值的影响域慢慢向外扩展,在两个集水盆汇合处构筑大坝,即形成分水岭。
直接应用分水岭分割算法的效果往往并不好,通常会由于噪声和梯度的其他局部不规则形造成过度分割。所以在图像中先用距离变换、梯度或者控制标记符对前景对象和背景对象进行标注区别,再应用分水岭算法会取得较好的分割效果。
使用距离变换的分水岭分割如图所示。经过从图中可以看出,区域被很好的分割开了,结果是令人满意的。
技术分享

统计信息

将分水岭分割后的区域与二值图像做交集,就可以得到分割后的目标区域。对每一个目标区域去求它的面积,周长等感兴趣信息。很多图像处理函数库都有计算面积、周长等图像处理基础的算子。

代码

这里,我使用的了Halcon说明,但所幸代码很短,而且Halcon支持生成其他语言,代码也容易理解,可以改成其他语言的。注意,我这里没有添加消除不均匀光影响的代码。

dev_close_window()
dev_open_window (0, 0, 744, 480, ‘black‘, WindowHandle)

for Num := 1 to 10 by 1
    read_image (Image, Num+‘.bmp‘)
    get_image_size (Image, Width, Height)

    dev_set_colored (12) 
    decompose3 (Image, ImageR, ImageG, ImageB)
    threshold (ImageR, Region, 100, 255)
    fill_up (Region, RegionFillUp)

    connection (RegionFillUp, ConnectedRegions)

    ********************距离变换算法*************************
    distance_transform (ConnectedRegions, DistanceImage, ‘octagonal‘, ‘true‘, 744, 480)
    convert_image_type (DistanceImage, DistanceImageByte, ‘byte‘)
    invert_image (DistanceImageByte, DistanceImageInv)
    scale_image_max (DistanceImageInv, DistanceImageInvScaled)
    *******************提取分水岭和盆地***********************
    watersheds_threshold (DistanceImageInv, Basins, 5)

    *******************取交集*******************************
    intersection (Basins, ConnectedRegions, SegmentedDices)
    dev_display (Image)
    dev_display (SegmentedDices)

    count_obj (SegmentedDices, Number)

    Sum:=0
    Min:=6
    Max:=0
    for Index := 1 to Number by 1
        select_obj (SegmentedDices, Obj, Index)
        reduce_domain (ImageB, Obj, ImageReduced)
        mean_image (ImageReduced, ThresholdImage, 31, 31)
        dev_display (ImageReduced)
        dyn_threshold (ImageReduced, ThresholdImage, RegionDynThresh, 20, ‘dark‘)
        erosion_circle (RegionDynThresh, RegionErosion, 1.5)
        connection (RegionErosion, ConnectedDotRegions)
        select_shape (ConnectedDotRegions, ConnectedDotRegions, [‘area‘,‘roundness‘], ‘and‘, [150,0.5808], [950,1])
        count_obj (ConnectedDotRegions, DotNumber)

        if(Max<DotNumber)
            Max:=DotNumber
        endif

        if(Min>DotNumber)
            Min:=DotNumber
        endif

        Sum:=Sum+DotNumber
        area_center (Obj, Area, CenterY, CenterX)
        disp_message (WindowHandle, ‘点数:‘+DotNumber+‘(‘+CenterX$‘.1f‘+‘,‘+CenterY$‘.1f‘+‘)‘, ‘image‘, CenterY, CenterX, ‘red‘, ‘false‘) 
    endfor

    disp_message (WindowHandle, ‘区域内共有:‘+Number+‘个骰子‘, ‘image‘, 20, 20, ‘red‘, ‘false‘)
    disp_message (WindowHandle, ‘点数之和:‘+Sum, ‘image‘, 40, 20, ‘red‘, ‘false‘)
    disp_message (WindowHandle, ‘最小点数:‘+Min+‘ 最大点数:‘+Max, ‘image‘, 60, 20, ‘red‘, ‘false‘)

    disp_continue_message (WindowHandle, ‘black‘, ‘true‘)
    stop ( )
endfor

更多阅读

数字图像处理(第三版) 冈萨雷斯著 chapter 9.6, 灰度级形态学
数字图像处理(第三版) 冈萨雷斯著 chapter 10.5, 使用形态学分水岭的分割

转载请保留以下信息

作者 日期 联系方式
风吹夏天 2015年8月5日 wincoder@qq.com

版权声明:本文为博主原创文章,未经博主允许不得转载。

骰子定位识别

标签:机器视觉   模式识别   图像分割   

原文地址:http://blog.csdn.net/bluecol/article/details/47285593

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!