目录
击中击不中有两种情形,本篇只讨论连通子图的匹配和定位。
击中击不中相关知识
看了很多篇文章。感觉下面这篇的图文讲解是比较清晰的
击中击不中相关知识http://t.csdnimg.cn/cYOXP
模板的制作及代码实现
击中击不中的关键是模板的制作,如果本身就有模板,那么模板制作就很简单了,但有时要匹配的模板来源于图像的某部分,那么你就需要自己制作模板。找了很多篇都没有说模板的细节,无奈只能自己根据原理来尝试制作模板,不知道思路对不对。
模板A是要匹配的子图, 模板B是要匹配的子图的补集。在制作模板时,模板A和B的中心点要一致且不能有交集。
以下图为例,假设我们要匹配字母o,
*创建圆形
gen_circle (Circle1, 64, 69, 37)
*得到区域边缘
boundary (Circle1, o1, 'outer')
gen_circle (Circle2, 64, 69, 50)
boundary (Circle2, o2, 'outer')
*显示
dev_display (Image3)
dev_display (o1)
dev_display (o2)
在这里我们使用圆形来匹配,其中(64, 69)为字母o的中心位置,其实位置随便选都行,并不一定要求在中心处,只是一般都选这里而已。所以你的位置并不一定要与(64, 69)相同,根据自身实际情况来定。需要注意,两个模板都应该是边缘图,我在开头贴出来的文章里貌似没有表现出A也要是边缘,这是错误的,两个模板都应该是边缘图。所以都要进行boundary处理。
然后就可以得到上图,其中小圆是模板A,大圆是模板B,模板A要尽可能的体现出待匹配模板的形状,如果用矩形,然后只有两条边重叠那么匹配的结果大概率不准确。原因也很简单,因为模板A要和图像做腐蚀,腐蚀的原理可自行搜索。如果你的模板A如下边左图所示,那么你的腐蚀结果就如右图所示出现了很多的错误匹配
正确的匹配应该是下图一样,在两个字母o处才匹配成功。这就说明模板A击中了。(为方便查看,红色的感兴趣区域被我用膨胀放大了)
接下来就是模板B,模板B需要注意的就是不能与你的模板A以及待匹配图像重叠,所以B的设置可以大些,但也不要太大了防止出问题,下图即为B的匹配结果
最后取两个的交集即可得到击中击不中的结果。(为方便查看,红色的感兴趣区域被我用膨胀放大了)
完整代码如下
read_image (Image3, '3')
get_image_size (Image3, Width, Height)
*二值化
rgb1_to_gray (Image3, GrayImage3)
threshold (GrayImage3, Region, 128, 255)
region_to_bin (Region, BinImage, 0, 255, Width, Height)
*做模板 o
gen_circle (Circle1, 64, 69, 37)
boundary (Circle1, o1, 'outer')
gen_circle (Circle2, 64, 69, 50)
boundary (Circle2, o2, 'outer')
dev_display (Image3)
dev_display (o1)
dev_display (o2)
threshold (BinImage, Region1, 0, 128)
erosion1 (Region1, o1, RegionErosion4, 1)
dev_display (BinImage)
dev_display (o1)
threshold (BinImage, Region2, 128, 255)
erosion1 (Region2, o2, RegionErosion5, 1)
dev_display (BinImage)
dev_display (RegionErosion5)
intersection (RegionErosion4, RegionErosion5, RegionIntersection)
dev_display (Image3)
dev_display (RegionIntersection)
值得一提的是,本例不用二值图也能匹配成功,但估计是这张图片比较简单。一般情况下还是建议在二值图下使用击中击不中。
总结一下,模板A要尽量和待匹配图像贴合,模板B不能与A和图像有交集。
使用腐蚀和膨胀制作模板
所以,其实直接使用腐蚀和膨胀就可以做出模板A和B了(*゜ー゜*)
代码如下
*选择图像o
threshold (GrayImage, Region, 240, 255)
connection (Region, ConnectedRegions)
select_obj (ConnectedRegions, ObjectSelected, 1)
*膨胀
dilation_circle (ObjectSelected, RegionDilation, 7)
boundary (RegionDilation, B, 'inner')
*腐蚀
erosion_circle (ObjectSelected, RegionErosion, 3.5)
boundary (RegionErosion, A, 'inner')
dev_display (Image3)
dev_set_color ('blue')
dev_display (A)
dev_set_color ('yellow')
dev_display (B)
结果如下图所示,蓝色为模板A,黄色为模板B,中间的黄点就是击中的结果。
hit_or_miss算子
当然Halcon中也有现成的算子来实现击中击不中,代码如下
read_image (Image3, '3')
get_image_size (Image3, Width, Height)
*二值化
rgb1_to_gray (Image3, GrayImage3)
threshold (GrayImage3, Region, 128, 255)
region_to_bin (Region, BinImage, 0, 255, Width, Height)
*做模板 o
gen_circle (Circle1, 64, 69, 37)
boundary (Circle1, o1, 'outer')
gen_circle (Circle2, 64, 69, 50)
boundary (Circle2, o2, 'outer')
dev_display (Image3)
dev_display (o1)
dev_display (o2)
threshold (BinImage, Region1, 0, 128)
hit_or_miss (Region1, o1, o2, RegionHitMiss2,64, 69)
需要注意,hit_or_miss的参数1你就算不用区域,输入图像也能运行(此时Halcon自动将图像转为图像的域),但有时可能会得不到你想要的结果,可能的原因是Halcon前景和背景搞错了的原因,所以保守的话就是老实的输入自己的感兴趣区域进去吧(╮(╯▽╰)╭)