*
* online shape-based matching with adaptation to illumination changes
*基于形状的在线匹配,能够适应光照变化
* rotational invariant
* rotation/translation to "normalize" the input image
* 旋转不变,旋转/平移以“规范化”输入图像
* set online to true if you are using an image acquisition device
* if online is set to false, a virtual image acquisition device is opened which reads an image sequence from hard disk
*
online := false
*设置未定义像素为黑色
VisUndefPixelBlack := 1
*关闭所有显示更新以提高性能
dev_update_window ('off')
dev_update_pc ('off')
dev_update_var ('off')
dev_update_time ('off')
if (online)
* open the 'real' image acquisition device
*获取真实图像获取设备的信息
info_framegrabber ('1394IIDC', 'revision', RevisionInfo, RevisionInfoValues)
*打开真实的图像采集设备
open_framegrabber ('1394IIDC', 1, 1, 0, 0, 0, 0, 'default', -1, 'default', -1, 'default', 'default', 'default', -1, -1, AcqHandle)
else
* open the virtual image acquisition device
*获取真实图像获取设备的信息
info_framegrabber ('File', 'general', Information, ValueList)
*打开虚拟图像采集设备,读取存储在硬盘上的图像序列
open_framegrabber ('File', 1, 1, 0, 0, 0, 0, 'default', -1, 'default', -1, 'default', 'pendulum/pendulum', 'default', -1, 1, AcqHandle)
endif
*获取一幅图
grab_image (Image, AcqHandle)
*获取图像的宽度和高度
get_image_size (Image, Width, Height)
dev_close_window ()
*打开新窗口用于显示旋转后的图像
dev_open_window (0, Width + 30, Width, Height, 'black', WindowRot)
*打开新窗口用于显示原始图像
dev_open_window (0, 0, Width, Height, 'black', WindowID)
*设置当前窗口及活动区域
dev_set_window (WindowID)
dev_set_part (0, 0, Height - 1, Width - 1)
*设置旋转窗口及旋转窗口活动区域
dev_set_window (WindowRot)
dev_set_part (0, 0, Height - 1, Width - 1)
*显示原始图像
dev_display (Image)
*设置原窗口文本的显示属性:字体大小16、字体类型momo、启用抗锯齿、不使用下划线
set_display_font (WindowID, 16, 'mono', 'true', 'false')
*输出一个恒等变换矩阵(这个矩阵通常用作其他仿射变换的基础)
hom_mat2d_identity (HomMat2DIdentity)
* disp_continue_message (WindowID, 'black', 'true')
* stop ()
* ------------------------
* select the model object
*选择模型对象
* ------------------------
if (online)
*
* define template by drawing a rectangle
* 定义模板区域
dev_update_pc ('off')
dev_set_window (WindowID)
*设置绘图区域的边界及线宽
dev_set_draw ('margin')
dev_set_line_width (5)
*从AcqHandle中获取图像
grab_image (ImageTempl, AcqHandle)
dev_set_window (WindowID)
dev_display (ImageTempl)
*在原窗口(12,12)位置处显示文本,并设置绘图颜色为green
disp_message (WindowID, 'define the template', 'window', 12, 12, 'black', 'true')
dev_set_color ('green')
*在原窗口绘制一个旋转矩形,矩形的中心位于(RowTempl, ColumnTempl),旋转角度为PhiTempl,长度为Length1和Length2。
draw_rectangle2 (WindowID, RowTempl, ColumnTempl, PhiTempl, Length1, Length2)
*生成一个旋转矩形形状,其属性存储在变量Rectangle中。
gen_rectangle2 (Rectangle, RowTempl, ColumnTempl, PhiTempl, Length1, Length2)
dev_display (Rectangle)
*根据旋转矩形Rectangle减少图像ImageTempl的定义域,生成新的图像ImageReduced。
reduce_domain (ImageTempl, Rectangle, ImageReduced)
*创建一个形状模型ModelID,金字塔层数4,模板旋转起始角度0,转角范围360,旋转步长auto,模板优化方法none,匹配方法
*'use_polarity',对比度30,最小对比度10
create_shape_model (ImageReduced, 4, 0, rad(360), 'auto', 'none', 'use_polarity', 30, 10, ModelID)
*对图像ImageReduced进行强度标准化处理,得到灰度均值TemplMean和灰度偏差Deviation
intensity (ImageReduced, Image, TemplMean, Deviation)
dev_update_pc ('on')
else
*
* load default object for virtual framegrabber
* 加载虚拟图像采集设备的默认对象
*定义了将要创建的形状的尺寸和方向。Length1和Length2是形状的两个长度参数,PhiTempl是形状的旋转角度
*(以弧度为单位,-0.315弧度约等于-18度),RowTempl和ColumnTempl是形状中心的坐标。
Length1 := 32.0
Length2 := 12.5
PhiTempl := -0.315
RowTempl := 112.5
ColumnTempl := 92.0
*从(1,1)开始,将原始图像Image到ImageTempl
copy_obj (Image, ImageTempl, 1, 1)
*生成一个旋转矩形形状,其属性存储在变量Rectangle中。
gen_rectangle2 (Rectangle, RowTempl, ColumnTempl, PhiTempl, Length1, Length2)
*根据旋转矩形Rectangle减少图像ImageTempl的定义域,生成新的图像ImageReduced。
reduce_domain (Image, Rectangle, ImageReduced)
*创建一个形状模型ModelID,金字塔层数4,模板旋转起始角度0,转角范围360,旋转步长auto,模板优化方法none,匹配方法
*'use_polarity',对比度30,最小对比度10
create_shape_model (ImageReduced, 4, 0, rad(360), 'auto', 'none', 'use_polarity', 30, 10, ModelID)
*对图像ImageReduced进行强度标准化处理,得到灰度均值TemplMean和灰度偏差Deviation
intensity (ImageReduced, Image, TemplMean, Deviation)
endif
* RowRot := RowTempl
* ColumnRot := ColumnTempl
*设置旋转中心点
RowRot := Height / 2
ColumnRot := Width / 2
* ------------------------------------------
* visualize normalized input image
*可视化归一化输入图像
* ------------------------------------------
* Compensate for rotation and translation
*补偿旋转和位移
*将一个旋转中心(RowTempl, ColumnTempl)和旋转角度PhiTempl转换为一个仿射变换矩阵HomMat2DRotate。这个矩阵将用于后续的图像变换。
*参数RowRot和ColumnRot指定旋转后的图像的中心点坐标,但在这里它们没有被使用,因为最后一个参数0表示不使用这些值。
vector_angle_to_rigid (RowTempl, ColumnTempl, PhiTempl, RowRot, ColumnRot, 0, HomMat2DRotate)
*使用上一步得到的仿射变换矩阵HomMat2DRotate来变换图像,生成图像ImageAffineTrans,插值方法为'constant',
*false表示输出图像与输入图像大小相同,可能会发生剪切
affine_trans_image (ImageTempl, ImageAffineTrans, HomMat2DRotate, 'constant', 'false')
if (VisUndefPixelBlack == 1)
*输出包含原始图像ImageAffineTrans的完整定义域的图像ImageFull
full_domain (ImageAffineTrans, ImageFull)
dev_set_window (WindowRot)
dev_display (ImageFull)
else
dev_set_window (WindowRot)
dev_display (ImageAffineTrans)
endif
dev_set_window (WindowID)
*显示原始图像
dev_display (ImageTempl)
disp_message (WindowID, 'run the template matching', 'image', 20, 20, 'yellow', 'false')
disp_message (WindowID, 'run the template matching', 'image', 20, 20, 'yellow', 'false')
disp_message (WindowID, '(click left to start,', 'image', 50, 20, 'yellow', 'false')
disp_message (WindowID, 'right to stop)', 'image', 80, 20, 'yellow', 'false')
* disp_continue_message (WindowID, 'black', 'true')
* stop ()
*等待用户左键开始
Button := 0
while (Button != 1)
*获取鼠标状态,左键按下时跳出循环
get_mbutton (WindowID, dummy, dummy, Button)
endwhile
dev_update_pc ('off')
* ------------------------
* shape-based matching
*基于形状的匹配
* ------------------------
Button := 0
Exp := 1
while (Button != 4)
if (online)
grab_image_async (Image, AcqHandle, -1)
else
grab_image (Image, AcqHandle)
endif
*记录开始时间
count_seconds (Seconds1)
*在Image中搜索ModelID,匹配搜索范围为0-360,达到0.7才能被视为模型实例,返回一个最佳匹配,找到的目标
*重叠,且重叠大于0.5时选择一个好的输出,计算精度:'least_squares',搜索时金字塔层数为0,贪婪度设置为0.7
*输出匹配位置的坐标、角度、得分
find_shape_model (Image, ModelID, 0, rad(360), 0.7, 1, 0.5, 'least_squares', 0, 0.7, Row, Column, Angle, Score)
if (Score > 0.5)
*生成一个旋转矩形形状,其属性存储在变量Rectangle中。
gen_rectangle2 (Rectangle, Row, Column, PhiTempl + Angle, Length1, Length2)
reduce_domain (Image, Rectangle, ImageReduced)
intensity (ImageReduced, Image, Mean, Deviation)
* Compensate for rotation and translation
*补偿旋转和位移
*将一个旋转中心(Row, Column)和旋转角度PhiTempl转换为一个仿射变换矩阵HomMat2DRotate。这个矩阵将用于后续的图像变换。
*参数RowRot和ColumnRot指定旋转后的图像的中心点坐标,但在这里它们没有被使用,因为最后一个参数0表示不使用这些值。
vector_angle_to_rigid (Row, Column, Angle, RowRot, ColumnRot, 0, HomMat2DRotate)
*使用上一步得到的仿射变换矩阵HomMat2DRotate来变换图像,生成图像ImageAffineTrans,插值方法为'constant',
*false表示输出图像与输入图像大小相同,可能会发生剪切
affine_trans_image (Image, ImageAffineTrans, HomMat2DRotate, 'constant', 'false')
*记录结束时间
count_seconds (Seconds2)
Time := round(1000 * (Seconds2 - Seconds1))
if (VisUndefPixelBlack == 1)
*将ImageAffineTrans全部显示在ImageFull里
full_domain (ImageAffineTrans, ImageFull)
*显示匹配的结果
dev_set_window (WindowRot)
dev_display (ImageFull)
else
dev_set_window (WindowRot)
dev_display (ImageAffineTrans)
endif
*显示原图
dev_set_window (WindowID)
dev_display (Image)
disp_message (WindowID, Time + ' ms', 'window', 12, 12, 'black', 'true')
dev_set_color ('green')
dev_display (Rectangle)
else
dev_display (Image)
endif
* --------------------------
* Exit with mouse click
*检测鼠标点击以退出循环
* --------------------------
*保存当前的错误变量状态到变量Error中
dev_error_var (Error, 1)
*禁用错误检查。这样可以确保接下来的操作不会因为错误而中断程序
dev_set_check ('~give_error')
*获取鼠标在窗口WindowID中的位置(行R和列C)以及点击状态Button。
get_mposition (WindowID, R, C, Button)
*恢复之前保存的错误变量状态。
dev_error_var (Error, 0)
*恢复错误检查。这样可以确保后续操作中如果发生错误,会正常抛出错误。
dev_set_check ('give_error')
*检查是否发生错误。如果Error不等于H_MSG_TRUE,表示获取鼠标位置时发生了错误鼠标置0
if (Error != H_MSG_TRUE)
Button := 0
endif
endwhile
disp_continue_message (WindowID, 'black', 'true')
stop ()
close_framegrabber (AcqHandle)
dev_set_window (WindowRot)
dev_close_window ()
dev_update_pc ('on')
dev_update_var ('on')
dev_update_time ('on')
dev_update_window ('on')
dev_disp_text (' End of program ', 'window', 'bottom', 'right', 'black', [], [])
使用到的主要相关算子详解:
create_shape_model 中的参数及用法参考文章:Halcon算子—create_shape_model参数解析及优化_create shape model-CSDN博客
vector_angle_to_rigid中的参数及用法参考文章:
halcon模板匹配——算子vector_angle_to_rigid和affine_trans_contour_xld_halcon的vector-CSDN博客
affine_trans_image(Image : ImageAffineTrans : HomMat2D, Interpolation, AdaptImageSize : )
Image:输入的图片
ImageAffineTrans:变换后输出的图片
HomMat2D:仿射变换矩阵
Interpolation:要选择的插值方法。
AdaptImageSize:控制输出图片的大小,设为true则表示将调整图像大小,使右边或下边不发生剪切;设为false则表示目标图像将与输入图像大小相同,超出的位置会被自动剪切。其中
其中插值主要可选的方法有:
nearest_neighbor:最近邻插值: 根据最近像素的灰度值确定灰度值(可能质量较低,但速度很快)。
bilinear:双线性插值。灰度值是通过双线性插值法从四个最近的像素确定的。如果仿射变换包含比例因子小于 1 的缩放,则不会执行平滑处理,这可能会导致严重的混叠效应(中等质量和运行时间)。
bicubic:双三次插值。灰度值通过双三次插值从最近的像素确定。如果仿射变换包含比例因子小于 1 的缩放,则不执行平滑处理,这可能会导致严重的混叠效果(放大质量高,运行速度慢)。
constant:双线性插值。灰度值是通过双线性插值从最近的四个像素中确定的。如果仿射变换包含比例系数小于 1 的缩放,则会使用一种平均值滤波器来防止混叠效应(中等质量,运行时间长)。
weighted:双线性插值。灰度值是通过双线性插值从四个最近的像素确定的。如果仿射变换包含比例系数小于 1 的缩放,则会使用一种高斯滤波器来防止混叠效应(高质 量,慢速)
find_shape_model中的参数及用法参考文章:
[Halcon&算子] find_shape_model()详解和解决匹配函数耗时问题_findshapemodel-CSDN博客