上图就是将相机定位后,辅以打光在离心机正上方取像而成的。由图可知,离心机内部分为四块区域,四块区域内部又分为半径大小不一的试管槽若干个,本篇文章主要就是讨论如何从相机取得的这些图像中,通过一系列算法将试管槽是否存在试管进行判断。

一、建模

建模的目的就是为了方便离心机内部旋转各种不同角度后,所取得的图像进行信息判断。
为了增强模型的参照度,我们一般选取的图片必须具备原始性。如下图所示:

为了方便进行图像处理,我们需要先把图像分离出三基色,利用单色调图像进行处理。

decompose3 (Image, R, G, B)

分离效果如下图所示:

  1. 小试管槽区域的手动定位建模
draw_circle (WindowHandle, Row, Column, Radius)  //手动画小试管槽轮廓
gen_circle_contour_xld (ContCircle, Row, Column, Radius, 0, 6.28318, 'positive', 1)  //显示所画圆形轮廓,并建立XLD模型ContCircle
gen_circle (Circle, Row, Column, Radius+10)  //自动显示一个比所画圆形“轮廓”半径大10个像素的圆形“区域”
reduce_domain (R, Circle, ImageReduced)  //将圆形区域隐藏
create_shape_model_xld (ContCircle, 'auto', 0, 0, 'auto', 'auto', 'ignore_local_polarity', 5, ModelID)  //根据之前建立的XLD模型ContCircle创建小试管槽的模板
find_shape_model (ImageReduced, ModelID, 0, 0, 0.5, 1, 0.5, 'least_squares', 0, 0, Row1, Column1, Angle, Score)  //在大圆区域内查找1个小试管槽模板
find_shape_model (R, ModelID, 0, 0, 0.5, 18, 0.5, 'least_squares', 0, 0, Row2, Column2, Angle1, Score1)  //在图片R内查找18个小试管槽模板
dev_display_shape_matching_results (ModelID, 'red', Row2, Column2, Angle1, 1, 1, 0)  //显示查找到的小试管槽模板

小试管槽建模效果如下图所示:

  1. 大试管槽区域的手动定位建模(与小试管槽同理)
draw_circle (WindowHandle, Row3, Column3, Radius1)
gen_circle_contour_xld (ContCircle1, Row3, Column3, Radius1, 0, 6.28318, 'positive', 1)
gen_circle (Circle1, Row3, Column3, Radius1+10)
reduce_domain (G, Circle1, ImageReduced1)
create_shape_model_xld (ContCircle1, 'auto', 0, 0, 'auto', 'auto', 'ignore_local_polarity', 5, ModelID1)
find_shape_model (ImageReduced1, ModelID1, 0, 0, 0.5, 1, 0.5, 'least_squares', 0, 0, Row4, Column4, Angle2, Score2)
find_shape_model (G, ModelID1, 0, 0, 0.5, 8, 0.5, 'least_squares', 0, 0, Row5, Column5, Angle3, Score3)
dev_display_shape_matching_results (ModelID1, 'green', Row5, Column5, Angle3, 1, 1, 0)

效果如下图所示:

二、查找离心机内部区域中心点坐标

因为我们只关心离心机内部区域,不必要的区域我们可以省去,不去处理。

gen_circle (Circle2, zhongxindian[1], zhongxindian[0], 830)  //以中心点为圆心,画一个半径为830的圆形区域(这里的中心点区域是大概预估的,并不是计算得来)
reduce_domain (Image, Circle2, ImageReduced)  //将Circle2区域轮廓线隐藏
decompose3 (ImageReduced, ImageReduced_R, ImageReduced_G, ImageReduced_B)
trans_from_rgb (ImageReduced_R, ImageReduced_G, ImageReduced_B, ImageReduced_H, ImageReduced_S, ImageReduced_V, 'hsv')  //转换成hsv颜色空间

ImageReduced_B效果如下图所示:

ImageReduced_V效果如下图所示:

由于中心点肯定是存在于中心原盘内,所以我们可以进一步缩小筛选区域。

gen_circle (Circle3, zhongxindian[1], zhongxindian[0], 200)  //以中心点为圆心,画一个比中心圆盘稍大的圆形区域
reduce_domain (ImageReduced_B, Circle3, ImageReduced1)

具体区域如下图所示:

由于圆盘的背景与圆盘的阈值相差较大,我们很容易就通过一系列算子将图中的圆盘区域筛选出来。

threshold (ImageReduced1, Region, 80, 255)  //在ImageReduced1区域选取阈值在80到255这个范围内的区域
fill_up (Region, RegionFillUp)  //填满Region内部中空区域
connection (RegionFillUp, ConnectedRegions2)  //将RegionFillUp区域分离成独立的一个个区域
select_shape (ConnectedRegions2, SelectedRegions2, 'area', 'and', 1000, 999999)  //将目标区域SelectedRegions2筛选出来
shape_trans (SelectedRegions2, RegionTrans, 'outer_circle')  //沿着SelectedRegions2区域塑造一个最小的外包圆形区域
dev_display (ImageReduced_V)
dev_display (RegionTrans)
area_center (RegionTrans, Area, Row, Column)  //取得RegionTrans区域的圆心
gen_cross_contour_xld (Cross, Row, Column, 80, 0)  //以RegionTrans区域的圆心做原点,建立坐标系

此时,我们就可以获得误差极小的中心点坐标。效果如下图所示:

三、计算离心机的旋转角度

由于我们的试管槽模板是在一个标准工位上设立的,离心机旋转各个角度后,为了能够准确地匹配试管槽模板,我们需要将模板的各个中心点坐标乘以离心机的旋转角度,这就是我们计算离心机旋转角度的必要性。
为了能够计算出离心机的旋转角度,我们需要设立一个参照点,通过计算参照点的旋转角度,从而得出离心机旋转角度,于是我们利用下图标定部分所示的参照点进行预估。

为了得到准确的旋转角度,我们需要计算出该点的中心点坐标。
同理,我们也可以缩小筛选区域,将中心原盘和外层圆环区域省去。

gen_circle (Circle4, Row, Column, 185)  //以中心点为圆心,画一个半径为185的圆形区域
gen_circle (Circle5, Row, Column, 285)  //以中心点为圆心,画一个半径为285的圆形区域
difference (Circle5, Circle4, RegionDifference)  //取大圆区域减去小圆区域,输出RegionDifference
reduce_domain (ImageReduced_V, RegionDifference, ImageReduced2)  //在ImageReduced_V图片上隐藏RegionDifference区域
sub_image (ImageReduced_V, ImageReduced_B, ImageSub, 1, 135)  //让小圆圈的色差更明显
dev_display (RegionDifference)

结果如下图所示:

bin_threshold (ImageReduced2, Region1)  //取ImageReduced2区域较暗的区域

由于参考点的阈值明显比周围区域大,于是我们直接在ImageReduced2区域内,用自动阈值法取出较暗的区域。

结果如下图所示:

为了得到参考点区域,我们直接利用已有的区域RegionDifference与区域Region1相减,就能得到。

difference (RegionDifference, Region1, RegionDifference1)  //RegionDifference区域减去Region1区域
fill_up (RegionDifference1, RegionFillUp1)
connection (RegionFillUp1, ConnectedRegions3)
select_shape (ConnectedRegions3, SelectedRegions3, 'area', 'and', 150, 99999)
shape_trans (SelectedRegions3, RegionTrans1, 'outer_circle')
dev_display (ImageSub)
dev_display (RegionTrans1)
area_center (RegionTrans1, Area1, Row1, Column1)  //取得RegionTrans1的圆心
gen_cross_contour_xld (Cross1, Row1, Column1, 40, 0)  //以RegionOpening1区域的圆心做原点,建立坐标系

此时,我们可以准确地查找到参考点的中心点坐标。
效果如下图所示:

只要我们将离心机内部的中心点坐标与参考点的中心点坐标相连,我们就可以通过这一条直线判断出离心机的旋转角度。

gen_region_line (RegionLines, Row1, Column1, Row, Column)  //连接两点

效果如下图所示:

具体的判断方法需要用到一些简单的初中数学知识。首先,我们可以根据中心原盘的中心点坐标建立一个坐标系,效果如下图所示:

从这个坐标轴我们可以清楚地判断旋转角度表示直线位于哪个象限,然后再根据三角关系,计算出与y轴正半轴之间的顺时针夹角。

if(Row1 < Row and Column1 > Column)  //第一象限x1 := Column1 - Columny1 := Row - Row1tuple_atan (y1/x1, ATan)xuanzhuanjiaodu := 6.28318 - (1.57080 - ATan)
elseif(Row1 < Row and Column1 < Column)  //第二象限x2 := Column - Column1y2 := Row - Row1tuple_atan (y2/x2, ATan1)
xuanzhuanjiaodu := 1.57080 - ATan1
elseif(Row1 > Row and Column1 < Column)  //第三象限x3 := Column - Column1y3 := Row1 - Rowtuple_atan (y3/x3, ATan2)xuanzhuanjiaodu := 1.57080 + ATan2
elseif(Row1 > Row and Column1 > Column)  //第四象限x4 := Column1 - Columny4 := Row1 - Rowtuple_atan (y4/x4, ATan3)xuanzhuanjiaodu := 6.28318 - ATan3 - 1.57080
endif
hom_mat2d_identity (HomMat2DIdentity)  //建立一个空的矩阵
hom_mat2d_rotate (HomMat2DIdentity, xuanzhuanjiaodu, Row, Column, HomMat2DRotate)  //将空矩阵乘上旋转角度
affine_trans_point_2d (HomMat2DRotate, y_shiguan, x_shiguan, y_xuanzhuan, x_xuanzhuan)  //把圆孔的中心点坐标都乘以旋转角度

通过求得的旋转角度,计算出旋转矩阵。此时,经过旋转过后的试管槽中心点坐标乘以旋转矩阵就可以直接使用。

四、判断试管槽内是否存在试管

由于试管槽不存在试管的时候,槽内都是黑漆漆一片的,而试管盖确实白色的,这样就非常好区分判断了。我们利用试管槽内区域的平均阈值与ImageReduced_R图片内的平均阈值进行对比,假如阈值差小于30,我们就可以判断这个试管槽内不存在试管;反之,假如阈值大于30,我们亦可以判断这个试管槽内存在试管。
我们以小试管槽为例:

gen_circle (Circle6, y_xuanzhuan[i_xiaoshiguan], x_xuanzhuan[i_xiaoshiguan], 50)  //以中心点为圆心,画一个半径为50的圆
intensity (Circle6, ImageReduced_R, Mean, Deviation)  //检测Circle6的平均灰度值以及与ImageReduced_R图片平均灰度值的差值

效果如下图所示:

假设试管槽内没有试管,我们可以用以下代码准确定位试管槽中心点:

gen_circle (Circle8, y_xuanzhuan[i_xiaoshiguan], x_xuanzhuan[i_xiaoshiguan], 70)  //以中心点为圆心,画一个比原来圆形区域稍大的圆形区域
reduce_domain (ImageReduced_R, Circle8, ImageReduced3)
find_shape_model (ImageReduced3, ModelID_Small, 0, 0, 0.5, 1, 0.5, 'least_squares', 0, 0, Row2, Column2, Angle, Score)  //在ImageReduced3区域内查找小试管槽的模板
dev_display_shape_matching_results (ModelID_Small, 'red', Row2, Column2, Angle, 1, 1, 0)  //显示查找到的模板
gen_cross_contour_xld (Cross3, Row2, Column2, 80, 0)  //以(Row2,Column2)为原点建立半径为80的坐标系

效果如下图所示:

假设试管槽内存在试管,我们可以用以下代码定位试管盖的中心点坐标:

gen_circle (Circle9, y_xuanzhuan[i_xiaoshiguan], x_xuanzhuan[i_xiaoshiguan], 110)  //以中心点为圆心,画一个半径为110的圆
reduce_domain (ImageReduced_R, Circle9, ImageReduced4)
bin_threshold (ImageReduced4, Region2)  //取出ImageReduced4区域内较暗的区域
difference (Circle9, Region2, RegionDifference2)  //找到两个区域不相交的区域
connection (RegionDifference2, ConnectedRegions)
select_shape_std (ConnectedRegions, SelectedRegions, 'max_area', 70)
fill_up (SelectedRegions, RegionFillUp2)  //填满SelectedRegions区域
shape_trans (RegionFillUp2, RegionTrans2, 'outer_circle')
reduce_domain (ImageReduced_R, RegionTrans2, ImageReduced10)
dev_display (ImageReduced10)
dev_display (RegionTrans2)
gen_cross_contour_xld (RegionTrans2, Row3, Column3, 75, 0)  //以最小圆的圆心为原点,建立半径为90的坐标系

效果如下图所示:

大试管槽的分析与小试管槽如出一辙。
最后,将所有的检测结果汇聚在一起,效果如下图所示:

谢谢观看!

关于Halcon的离心机试管槽定位相关推荐

  1. Halcon基于形状的几何定位函数说明

    Halcon基于形状的几何定位函数说明 1. create_shape_model(Template: : //reduce_domain后的模板图像 NumLevels,//金字塔的层数,可设为&q ...

  2. Halcon实战项目讲解,定位,基于汽车离合片精密定位尝试。

    Halcon实战项目讲解,定位,基于汽车离合片精密定位尝试. 在离合片的凸出齿部任意的一个齿下刻蚀一个23mm的数字字符.单齿的空间为34mm. 所需要完成内容,定位到齿靠下部分的位置,并传输坐标和角 ...

  3. halcon学习之运动跟踪定位

    大家去研究这个例子就可以了:optical_flow_hydraulic_engineering.hdev,这里只是记录一下,备忘 * This example demonstrates the us ...

  4. halcon与QT联合:(5.1)瓶盖检测以及QT界面搭建

    halcon实现瓶盖检测与定位代码: dev_close_window() dev_open_window(0, 0, 1024, 1024, 'black', WindowHandle) list_ ...

  5. Selenium2 Python 自己主动化測试实战学习笔记(五)

    7.1 自己主动化測试用例 无论是功能測试.性能測试和自己主动化測试时都须要编写測试用例,測试用例的好坏能准确的体现了測试人员的经验.能力以及对项目的深度理解. 7.1.1 手工測试用例与自己主动化測 ...

  6. Android 高德地图(带有定位和点击显示经度纬度)

    Android高德地图测试,如下: 1.Android高德地图Demo地址下载:       下载android高德地图Demo 1.2 Android定位SDK 一键下载 1.3 下载好的文件zip ...

  7. (1)-Halcon入门学习路线

    Halcon学习路线 01. Blob分析.定位.图像预处理.仿射变换(目的:得到目标区域) 02. 字符识别(一二维码.OCR) 03. 识别定位:模板匹配(灰度.相关性.形状) 04. 尺寸测量: ...

  8. python+selenium自动化(四)__八大元素定位之class_name、tag_name、partial_link_text、css_selector

    selenium八大元素定位(二) 上节讲了4种定位ID.NAME.LINK_TEXT.XPATH,这节继续学习剩下的4种元素定位方式 1.通过class_name定位 我们需定位上图中的" ...

  9. Watir-webdriver处理table

    最近大脸猫同学给了我一个popup的demo,让我试着定位弹出窗口中的按钮元素.在研究过程中,发现webdriver与watir代码有区别,一度让我很郁闷,在网上也找不到相应的解决方案,刚才code运 ...

最新文章

  1. 串口监视软件_ESP32 Arduino教程:软件重置
  2. 超强图文|并发编程【等待/通知机制】就是这个feel~
  3. 看固态存储厂商在硝烟四起的市场中如何发展?
  4. CF-1140 E - Palindrome-less Arrays
  5. boost::hana::product用法的测试程序
  6. 说说MaxTenuringThreshold这个参数
  7. linux nuttx 环境搭建,ubuntu14.04 nuttx开发环境的搭建
  8. timerfd与epoll
  9. MySQL数据的重复处理
  10. MySQL设置或修改系统变量的几种方法
  11. 8.5 意境级讲解迁移学习
  12. 数据之路 - Python爬虫 - 免费代理
  13. 【迅雷VIP体验】免费获得迅雷会员,享受高速下载通道
  14. 关于数字签名驱动解决方法
  15. python太阳花画法_Python——教你画朵太阳花
  16. 小学计算机小知识,小学生电脑基础知识
  17. 海绵城市工程_海绵城市工程案例详解—雨水调蓄池
  18. 待机时反复按Power键概率性重启-定位问题
  19. HDUOJ 2955 Robberies
  20. 当你看不清自己的时候,读一些句子会有启发

热门文章

  1. focusky导出html修改,Focusky输出HTML MP4 EXE APP ZIP动画演示文件
  2. php 删除其他盘符,Linux_自动清除电脑垃圾及删除windows默认共享盘符的批处理bat,by:zuifeng258Windows在默认情况下 - phpStudy...
  3. NR modulation 4-AM
  4. 啊哈添柴挑战1222输出菱形C++
  5. 基本逻辑门电路 - 异或
  6. ORA-01654错误:表空间满了,插入失败
  7. excel 作图-- 主次纵坐标轴 横坐标名称太长
  8. 计算机毕业设计 SSM的房屋租赁管理系统(源码+论文)
  9. JSAPI支付——H5网页端调起支付接口
  10. 《web前端面试题》第一问-如何快速居中对齐?