前言
好几天没有更新了,最近心情不太顺畅,休息了几天!
最近在研究户外宽温条件下汽车油箱口的识别与检测,因技术路线限制,不能更换特制的油箱盖与油箱口,所以需要找寻其他可行的方法。经过多次调研与针对市面上主流相机的识别精度与识别定位方式,最终还是选用了模板匹配的方式。但有一些问题是现实存在的,比如户外光照对成像的影响,拍照角度对成像的影响等等,但万事开头难,一定要知道我们现在能做到什么程度,能取得什么样的效果,Let's GO!
什么是模板匹配
模板就是一副已知的小图像,而模板匹配就是在一副大图像中用已知的模板去搜寻目标,已知该图中有要找的目标,且该目标同模板有相同的尺寸、方向和图像元素,通过一定的算法可以在图中找到目标,确定其坐标位置。但得到的行列位置不建议直接使用。
模板匹配方式
halcon的模板匹配种类有很多种,方法各有优缺点。一般有基于灰度的匹配,基于形状,基于相关性的匹配等等,再次不在多做赘述,但考虑到项目的特殊情况,需要考虑图像的旋转,图像匹配一般需要对旋转放缩进行处理,另外为了提高搜索效率,常用用图像金字塔来处理模板图像,图像金子塔就是把图像按一定算法,缩小为不同比例的模板,减少像素。一般的模板匹配流程如下:图像来自https://blog.csdn.net/thisiszdy/article/details/108000083
综上:选用了局部可变性的模板以及可缩放的模板两种方式进行模板匹配。
算子介绍
//创建普通模板
create_shape_model(
Template , // 模板图像
NumLevels, // 图像金字塔
AngleStart, // 起始角度
AngleExtent, // 角度范围
AngleStep, // 角度步长
Optimization, // 优化算法
Metric, // 极性
Contrast, // 对比度
MinContrast, // 最小对比度
ModelID // 生成模板ID)
///
//匹配模板
find_shape_model(Image, // 匹配图像
ModelID, //模板句柄
AngleStart, // 起始角度
AngleExtent, //角度范围
MinScore, // 最低得分输出的匹配的得分Score 大于该值
NumMatches, // 匹配数量
MaxOverlap, // 最大重叠
SubPixel, //计算精度的设置,五种模式,多选2,3
NumLevels, //搜索时金字塔的层数
Greediness : //贪婪度,搜索启发式,一般都设为0.9,越高速度快,容易出现找不到的情况
Row,Column,Angle,Score) //输出匹配位置的行和列坐标、角度、得分。
//创建一个形状的表示模型
create_scaled_shape_model (ImageReduced3, 'auto', rad(-45), rad(90), 'auto', 0.9, 1, 0, 'no_pregeneration', 'ignore_global_polarity', 'auto', 'auto', ModelID)
//使用用图像创建带有缩放的匹配模板,上面的灰度分割什么的其实可以不要
//NumLevels 最高金子塔层数
//AngleStart 开始角度加rad(90)是将弧度制转为角度值
//AngleExtent 角度范围
//AngleStep 旋转角度步长
//ScaleMin 模板行方向缩放最小尺度
//ScaleMax 模板行方向缩放最大尺寸
//MinScore 最低匹配分值 百分比
//ScaleStep 步长
//Optimization 优化选项 是否减少模板点数
//Metric 匹配度量级性旋转
//MinContrast 最小对比度
//ModelID 生成模板ID
///
//可缩放的模板匹配(//寻找单个带尺度形状模板最佳匹配)
find_scaled_shape_model (ImageRectifiedFixed, ModelID, rad(-180), rad(180), 0.5, 1.2, 0.3, 1, 0.5, 'none', 4, 0.9, Row, Column, Angle, Scale, Score)
//ImageRectifiedFixed 要搜索的图像
//ModelID 模板ID
//AngleStart 开始角度加rad(90)是将弧度制转为角度值
//AngleExtent 角度范围
//ScaleMin 模板行方向缩放最小尺度
//ScaleMax 模板行方向缩放最大尺寸
//MinScore 最低匹配分值 百分比
//NumMatches 匹配实例的个数
//MaxOverlap 最大重叠 在有重叠时也可检测匹配
//SubPixel 是否亚像素精度
//NumLevels 金子塔层数
//Greediness 搜索贪婪度; 0安全慢;1块不稳定;其他就是介于中间值
//剩下的几个参数是匹配图像的位置状态等参数
/
//重点描述一下
create_local_deformable_model(Template : : NumLevels, AngleStart, AngleExtent, AngleStep, ScaleRMin, ScaleRMax, ScaleRStep, ScaleCMin, ScaleCMax, ScaleCStep, Optimization, Metric, Contrast, MinContrast, ParamName, ParamValue : ModelID)
create_local_deformable_model(
//Template:输入多通道图像,用来创建model
//NumLevels:输入integer,用来控制最多有多少层金字塔层数:'auto', 0,1,2,3,。。。
//AngleStart:输入角度,控制初始的最小角度(调整匹配时候开始的最小角度,默认-0.39)
//AngleExtent:输入角度,控制旋转的范围,默认0.79
//AngleStep:输入角度,控制旋转的最小角度,即分辨率,默认’auto'
//ScaleRMin:行方向的最小缩放比例,默认1.0,通常大于0小于1
//ScaleRMax:行方向的最大缩放比例,默认1.0,通常大于1小于1.5
//ScaleRStep:行方向的缩放步长,可影响行方向的分辨率,默认'auto', 0.01,0.02,0.05,。。
//ScaleCMin:
//ScaleCMax: 列方向,同上
//ScaleCStep:
//Optimization:生成模型时的优化方式,默认'none',可选,'auto','point_reduction_XXX'
//Metric: 比较时候的标准:默认'use_polarity'使用极坐标系进行比较
//Contrast:在模板图片的滤波或者磁滞滤波中,控制结果的对比度,默认'auto', 10, 20....
//MinContrast:在搜寻对象过程中的最小对比度,默认'auto', 1, 2, 3, 5....
//ParamName: 普通参数名字(不太清楚用途,后续研究)默认[], 'min_size','part_size'
//ParamValue:参数值, 默认[], 可选'small', 'medium', big'
//ModelID: 输出的模型handle
准备工作已就绪开搞!!!!
- 读取图像
dev_close_window() dev_open_window(0, 0, 512, 512, 'black', WindowHandle) read_image (Image3, 'C:/Users/siasun/Desktop/3.jpg') dev_display(Image3)
- 灰度处理
rgb1_to_gray(Image3,GrayImage) dev_display(GrayImage) get_image_size(GrayImage,Width,Height)
- ROI处理
draw_rectangle2(WindowHandle, Row, Column, Phi, Length1, Length2) gen_rectangle2(Rectangle1, Row, Column, Phi, Length1, Length2) reduce_domain (GrayImage, Rectangle, TemplateImage)
哈哈 1与2的区别就是2有方向 可以理解为交互式绘制任意有方向的矩形框 // YapethsDY真知灼见
- 模板保存
write_shape_model(ModelID2, 'C:/Users/siasun/Desktop/1/1.shm') *write_shape_model_3d(WindowHandle1, 'C:/Users/siasun/Desktop/1/1.shm')
使用Create_shape_model 以及Create_scale_shape_model时可调用该函数保存模板为.shm文件
但使用Create_local_deformable_model时该接口函数无法使用
- 模板创建与匹配
* create_local_deformable_model(TemplateImage, 'auto', 0, 360, 0.0175, 1, 1, 'auto', 1, 1, 'auto', 'none', 'use_polarity', 'auto', 'auto', [], [], ModelID) create_scaled_shape_model(TemplateImage, 'auto', 0, 360, 0.0175, 0.9, 1.1, 'auto', 'auto', 'use_polarity', 'auto', 'auto', ModelID) *inspect_shape_model (TemplateImage, ModelImages, ModelRegions, 3, 30) *create_shape_model (TemplateImage, 6, rad(0), rad(360), rad(0.6151), ['point_reduction_high','no_pregeneration'], 'use_polarity', [24,44,12], 4, ModelId) *get_shape_model_contours (ModelContours, ModelId, 1) *get_shape_model_contours(ModelContours, ModelID, 1) get_deformable_model_contours (ModelContours, ModelID, 1) ImgNum := 9 ImageNameStart := 'C:/Users/Administrator/Desktop/img_' for I := 0 to ImgNum - 1 by 1 read_image (Image1, ImageNameStart + I$'02d') rgb1_to_gray(Image1,GrayImage1) dev_display(GrayImage1) *auto_threshold(GrayImage1, Regions, 2) *connection (Regions, ConnectedRegions) *select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 50, 500) *find_local_deformable_model (GrayImage1, ImageRectified, VectorField, DeformedContours, ModelID, 0, 360, 1, 1, 1, 1, 0.5, 1, 1, 0, 0.9, [], [], [], ModelScore, ModelRow, ModelColumn) find_scaled_shape_model(GrayImage1, ModelID, 0, 360, 0.9, 1.1, 0.5, 1, 0.5, 'least_squares', 0, 0.9, ModelRow, ModelColumn, ModelAngle, ModelScale, ModelScore) *find_shape_model (GrayImage1, ModelId, rad(0), rad(360), 0.2, 9, 0.5, 'least_squares', [6,1], 0.8, ModelRow, ModelColumn, ModelAngle, ModelScore) * Matching 02: transform the model contours into the detected positions for MatchingObjIdx := 0 to |ModelScore| - 1 by 1 hom_mat2d_identity (HomMat) * hom_mat2d_rotate (HomMat, ModelAngle[MatchingObjIdx], 0, 0, HomMat) hom_mat2d_translate (HomMat, ModelRow[MatchingObjIdx], ModelColumn[MatchingObjIdx], HomMat) affine_trans_contour_xld (ModelContours, TransContours, HomMat)
在halcon里的整个处理过程已经完成,项目实际应用的话需要导出c++程序
测试结果如下图
等等 具体的后续再说吧 下班了