halcon学习_模板匹配

模板匹配中有基于点、基于灰度值、基于描述符、基于相关性、基于形状、基于组件的方法。
大体流程:抠图 → 创建模板 → 寻找物体 → 仿射变换 → 显示

基于相关性的模板匹配在创建模板时,会将模板角度转为0°;
基于形状的模板匹配在创建模板时,会将模板角度转为0°,并且同时将坐标移到图像左上方(0,0)的位置。


基于相关性的模板匹配

1、 demo - 模板匹配(基于相关性) - find_ncc_model_exposure
2、 相关性适用于光照不均、明暗变化的场合(优点),但背景不能太复杂(缺点)。
当光照变化大时,用相关性好,不要用基于灰度的。
3、 可以通过调节参数改变匹配效果。且金字塔层数越多,搜索越快;反之,搜索越慢。
4、 相关性的值越接近1,越相关。
5、 模板匹配有两种方法实现:①助手 ②代码
6、 采集助手 - 创建参数 相对于create_ncc_model
…///采集助手 - 应用 相对于find_ncc_model
ps:匹配最大数为0,意味着找出所有匹配到的
7、 创建模板的方式可以手画,也可以是blob分析,然后都要抠出来。reduce_domain()

8、 助手方式,找出图中的飞机(注意我用的图像,不是视频)
步骤:
先读取一张图像 - 打开匹配助手
创建选项卡 - 模板资源:图像窗口(或用文件或用采集助手) - 画ROI区域 - 选择基于互相关
应用选项卡 - 图像文件 - 加载 - 选中加载出来的图像名称 - (勾选总是找到) - 调整最小分数
代码生成 - 插入代码
ps:我这里是先插入的图像,如果用的摄像头,可以直接在采集和应用的地方用采集助手
ps:使用基于互相关,显示的时候才是框框,如果是基于形状,则显示出来是轮廓
ps:使用基于互相关的时候,要使用灰度图像!!!
halcon学习_模板匹配_第1张图片halcon学习_模板匹配_第2张图片halcon学习_模板匹配_第3张图片

9、 代码方式,找出图中的飞机
步骤:
读图 → 画ROI区域 → area_center面积信息 → 裁剪ROI区域
创建ncc模板 → 找到ncc模板 → 仿射变换 → 显示
ps:基于Normalized cross correlation(NCC)用来比较两幅图像的相似程度已经是一个常见的图像处理手段。NCC算法可以有效降低光照对图像比较结果的影响。
ps:学会灵活运用复制粘贴

read_image (Image, 'C:/Users/yuan/Desktop/7.tif')
gen_rectangle2 (ROI_0, 415.916, 176.48, rad(-40.041), 19.9162, 16.9716)
area_center (ROI_0, Area, RowRef, ColumnRef)
reduce_domain (Image, ROI_0, ImageReduced)

dev_display (Image)
dev_set_draw ('margin')

create_ncc_model (ImageReduced, 'auto', rad(0), rad(360), 'auto', 'use_polarity', ModelID)
find_ncc_model (Image, ModelID, rad(0), rad(360), 0.5, 1, 0.5, 'true', 0, Row, Column, Angle, Score)
vector_angle_to_rigid (RowRef, ColumnRef, 0, Row, Column, Angle, HomMat2D)
affine_trans_region (ROI_0, RegionAffineTrans, HomMat2D, 'nearest_neighbor')
dev_display (Image)
dev_display (RegionAffineTrans)

ps:仿射变换函数刚开始打出来是这样的
vector_angle_to_rigid (RowRef, ColumnRef, rad(-40.041), Row, Column, angle, HomMat2D)
affine_trans_region (ROI_0, RegionAffineTrans, HomMat2D, ‘nearest_neighbor’)
此时显示模板匹配找到的区是没有角度的是水平的
在这里插入图片描述
这是因为在创建ncc模板的时候,自动将ROI_0的角度转到0°了,所以仿射变换的起始角度应该变为0,以后记住这种情况得到仿射矩阵时,起始角度直接填0°就好,变换后的角度就写angle。
vector_angle_to_rigid (RowRef, ColumnRef, 0, Row, Column, angle, HomMat2D)

ps:还有一点注意的就是创建和找到ncc模板的函数,刚打出来的时候
create_ncc_model (ImageReduced, ‘auto’, 0, 0, ‘auto’, ‘use_polarity’, ModelID)
find_ncc_model (Image, ModelID, 0, 0, 0.5, 1, 0.5, ‘true’, 0, Row, Column, Angle, Score)
第三、四个位置都是搜索的起始角度和终止角度,这里都改为 rad(0 和 rad(360),像这样。
find_ncc_model (Image, ModelID, rad(0), rad(360), 0.5, 1, 0.5, ‘true’, 0, Row, Column, Angle, Score)
vector_angle_to_rigid (RowRef, ColumnRef, 0, Row, Column, Angle, HomMat2D)

ps:这里因为要进行仿射变换,所以找ncc目标的函数的第6个位置只能填1(匹配一个),不然会因为格式报错。

10、 代码-一次性匹配多个飞机

read_image (Image, 'C:/Users/yuan/Desktop/7.tif')
gen_rectangle2 (ROI_0, 415.916, 176.48, rad(-40.041), 19.9162, 16.9716)
area_center (ROI_0, Area, RowRef, ColumnRef)
reduce_domain (Image, ROI_0, ImageReduced)

dev_display (Image)
dev_set_draw ('margin')

create_ncc_model (ImageReduced, 'auto', rad(0), rad(360), 'auto', 'use_polarity', ModelID)
find_ncc_model (Image, ModelID, rad(0), rad(360), 0.5, 3, 0.5, 'true', 0, Row, Column, Angle, Score)

if(|Score|>0)
    for Index := 1 to 3 by 1	 
    vector_angle_to_rigid (RowRef, ColumnRef, 0, Row[Index-1], Column[Index-1], Angle[Index-1], HomMat2D)
    affine_trans_region (ROI_0, RegionAffineTrans, HomMat2D, 'nearest_neighbor')
    dev_display (Image)
    dev_display (RegionAffineTrans)
    endfor
endif

ps:匹配到了3架飞机,所以row,column等这些值有三个数。
ps:|score|的值是该向量的维数!不是绝对值!
halcon学习_模板匹配_第4张图片halcon学习_模板匹配_第5张图片


基于灰度值的模板匹配

1、 基于灰度值的目标匹配采用的是平均绝对差算法(Mean Absolute Differences,简称MAD)
2、 rad()函数是将角度转换为弧度,deg()函数是将弧度转换为角度。
3、 disp_arrow()函数用来显示箭头。注意,disp显示只是显示,在变量窗口是看不到值的。
4、 rot表示旋转搜索,mg表示金字塔搜索。
best_match()、best_match_rot()、best_match_mg()、best_match_rot_mg()
fast_match()、fast_match_rot()、fast_match_mg()、fast_match_rot_mg()


基于形状的模板匹配

教程中前几课都是在讲demo,先来看看demo。
1、 对光照要求高,不适合室外自然光
2、基于形状的模板匹配在创建模板时,自动将ROI的位置移到像素点(0,0)位置,且讲角度旋转为0°。
3、 创建:
create_shape_model()、create_shape_model_xld()、create_scale_shape_model() /最后这个函数带缩放功能
ps:创建模板如果带get_shape_model(),得到xld轮廓,在仿射变换函数中用到,显示的图形就是轮廓。affine_trans_contour_xld()用这个仿射变换显示轮廓。也可以不显示轮廓想显示画的矩形框,那么affine_trans_region()函数,仿射变换之前画的roi区域,注意这时候求的仿射矩形前面应该填roi的行列角度,不是(0,0,0)。
ps:创建函数第二个参数金字塔层数不要写1,不然识别起起来困难(而且应该离焦状态就找不到了)
4、 寻找:
find_shape_model()、find_scale_shape_model()、find_shape_models() /最后这个函数找多个模板
5、 仿射变换:
平移旋转: vector_angle_to_rigid()
缩放:hom_mat2d_scale()
6、 显示:
dev_disp(Image)
dev_disp(RegionAffineTrans)
7、 多了解demo,学会应用到实战项目
ps:contour n.外形、轮廓

8、 demo - 模板匹配(形状) - align_measurements()
9、 demo - 模板匹配(形状) - create_average_shape_model():
① channels_to_image(Templates,MultichannelImage)
将多张图变成一张多通道的图
②mean_n(MultichannelImage,ImageMean)
求均值变为一个通道(然后将均值图片作为创建的模板)
10、 demo - 模板匹配(形状) - align_measurements()
write_shape_model(ModelID,‘green-dot.shm’)
将模板存入.shm文件中,方便以后直接使用
inspect_shape_model()
检查模型轮廓
11、 demo - 模板匹配(形状) - create_roi_via_vision()
dev_set_part(左上x,左上y,右下x,右下y)
在这之后显示的图片都是显示划定的区域
12、 demo - 模板匹配(形状) - create_shape_model_xld()
binary_threshold() //快速二值化
13、 demo - 模板匹配(形状) - inspect_shampoo_label()
add_channels()
添加灰度化值到区域
14、 demo - 模板匹配(形状) - matching_coins()
前面的循环是创建模板,后面的循环是寻找和显示
15、 demo - 模板匹配(形状) - reuse_model()
write_shape_model()
存储成.sbm的文件(上面是.shm文件,帮助中看的也是shm文件,不懂,但是这个例子中用.sbm文件,且我尝试了可以用),可以保存创建了的模型。
16、 demo - 模板匹配(形状) - synthetic_circle
set_shape_model_para()函数中第2个参数GenParamName如果是’timeout’,这个函数的作用是超过时间就不继续寻找了。
paint_xld()、paint_region()
由轮廓到图像、由区域到图像
17、 demo - 模板匹配(形状) - pm_measure_board
讲了(电路板芯片)的定位+测量。定位电路板芯片中心位置和角度,就可以定位到两排引脚,并用两个长方形框选。
ps:对于膨胀和腐蚀,二值图像是区域增加或减少,灰度图像是灰度值(亮度)增加或减少。
18、 demo - 模板匹配(形状) - pm_multiple_models
以后做多模板可以完全复制粘贴这个例子
inspect_shape_model()是用来检查模型轮廓,不满意的话可以在创建后修改,用特征直方图筛选,注意特征要选前面带xld的。

create_shape_model (Image, 5, rad(0), rad(360), 'auto', 'pregeneration', 'use_polarity', 30, 10, ModelID)
get_shape_model_contours (ModelCont, ModelID, 1)
select_shape_xld (ModelCont, ModelContours, 'contlength', 'and', 20, 1000)

下面这段代码是为了方便直接模型,不用修改后再进行仿射变换再显示。

inspect_shape_model (Image, ModelImages, ModelRegions, 1, 30
connection (ModelRegions, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 20, 100000
union1 (SelectedRegions, ModelRegions)
gen_contours_skeleton_xld (ModelRegions, ModelContours, 1, 'filter') //将一个骨架转换为xld的轮廓
dev_display (ModelContours)

halcon学习_模板匹配_第6张图片

count_obj (ModelContours, NumModel)
count_obj (Models, NumModels)
concat_obj (Models, ModelContours, Models)
IndexS := [IndexS,NumModels + 1]
IndexE := [IndexE,NumModels + NumModel]
ModelIDs := [ModelIDs,ModelID]

对于这个代码有这个图会好理解些。(自用)halcon学习_模板匹配_第7张图片
19、 demo - 模板匹配(形状) - multiple_dxf_model
和上个例子的识别部分都一样,区别在上半段。
read_contours_xld_dxf() //这个demo的重点
这个demo读dxf文件将轮廓转为图像,再进行创建轮廓
20、 实战(实时找瓶盖上的字):
(基本都差不多 简单点写重要的)
①:助手方式:
检测选项卡 - 要按一下执行,结果才会显示到检测选项卡
②:代码方式:
抠图(手画或blob方法) → 创建模板 → 寻找识别 → 仿射变换 → 显示
在寻找函数的下一行加一个if( |Score| > 1)防止某一帧没有找到报错
ps:取消勾选运行模式,连续运行时,创建模板时左上角显示的轮廓可以在消失。
ps:学会灵活运用halcon自带例子,把它当字典用。

你可能感兴趣的:(计算机视觉)