说明:
模板匹配是halcon的强项,opencv自带的模板匹配算子跟halcon这个比起来差好几层楼那么多。 在视觉引导定位时,模板匹配是少不了的东西。 所有的新手在遇到阈值搞不定的应用时,都会想到模板匹配,可见其概念和易用性已经深入人心。 但实际上halcon的模板匹配的知识点还是很多的,并非仅仅是我们常见的形态模板匹配。 勇哥这个系列贴子用来补全halcon模板匹配的相关系列知识。
使用基于描述符的模板匹配在图片序列中寻找不同姿式的饼干盒子
这个例子展示了如何使用基于描述符的匹配特性找到一个不同方向饼干盒子。
首先,根据参考图像计算模型和参考姿态,然后在显示不同方向的饼干盒子的图像序列中搜索模型。
使用得到的姿势,我们还可以检查盒子是否倒置。
代码说明:
(一)
关于算子vector_to_pose
在贴子《HALCON高级篇:3d相机标定(一)基础理论》中我们讨论过相机外参可以用下面三种方法来确定:
1. 利用从某一个标定图像获取的位姿,其中标定图像中标定板被直接放置在测量平面上。在这种情况下,你就可以用算子get_calib_data来获得其位姿。
2. 通过一个标定板被直接放置在测量平面的额外图像,将相机内参的确定从相机外参的确定分离出来。应用find_calib_object去提取标定标志点和位姿。
3. 自己去确定3D世界点和它们在图像映射的对应关系,然后调用vector_to_pose。
vector_to_pose需要知道至少不再一条直线上3个点的3D世界坐标,然后,你必须确定这些3d点映射后相对应的图像坐标,然后vector_to_pose就能计算出外参。
如下面代码所示:
RowsRoi := [224,224,406,406] ColumnsRoi := [115,540,540,115] WorldX := [-189,189,189,-189] / 1000.0 WorldY := [-80,-80,80,80] / 1000.0 * reference pose of the object to the camera is computed vector_to_pose (WorldX, WorldY, [], RowsRoi, ColumnsRoi, CamParam, 'iterative', 'error', Pose, Quality)
(二)
未完待续……
演示代码:
* This example shows how to find a cookie box aligned in different
* directions with the descriptor based matching feature. First, a
* model and a reference pose are computed from the reference
* image, then the model is searched in a sequence of images
* showing the cookie box in different orientations. Using the
* resulting pose we can also check whether the box is placed
* upside down or not.
*
*
ReCreateDescrModel := false
*
dev_update_off ()
dev_close_window ()
read_image (Image, 'packaging/cookie_box_01')
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
dev_set_draw ('margin')
dev_set_line_width (4)
dev_set_color ('blue')
*
gen_cam_par_area_scan_division (0.0155565, -109.42, 1.28008e-005, 1.28e-005, 322.78, 240.31, 640, 480, CamParam)
*
*
RowsRoi := [224,224,406,406]
ColumnsRoi := [115,540,540,115]
WorldX := [-189,189,189,-189] / 1000.0
WorldY := [-80,-80,80,80] / 1000.0
* reference pose of the object to the camera is computed
vector_to_pose (WorldX, WorldY, [], RowsRoi, ColumnsRoi, CamParam, 'iterative', 'error', Pose, Quality)
image_points_to_world_plane (CamParam, Pose, RowsRoi, ColumnsRoi, 'm', XOuterBox, YOuterBox)
* generate ROI for model training
gen_rectangle1 (Rectangle, 224, 115, 406, 540)
reduce_domain (Image, Rectangle, ImageReduced)
*
* If desired re-create the descriptor-based model. Note that this may take
* several minutes dependent on the hardware.
dev_display (Image)
if (ReCreateDescrModel)
dev_display (Rectangle)
disp_message (WindowHandle, 'Creating the descriptor-based model ... \n(may take a minute)', 'window', 10, 10, 'black', 'true')
count_seconds (SecondsCreation1)
create_calib_descriptor_model (ImageReduced, CamParam, Pose, 'harris_binomial', [], [], ['depth','number_ferns','patch_size','min_scale','max_scale'], [11,30,17,0.4,1.2], 42, ModelID)
count_seconds (SecondsCreation2)
TimeCreation := SecondsCreation2 - SecondsCreation1
write_descriptor_model (ModelID, 'cookie_box_model.dsm')
else
* If desired read the descriptor-based model from disk
disp_message (WindowHandle, 'Reading the descriptor-based model file from disk ...\n ... will take a few seconds!', 'window', 10, 10, 'black', 'true')
dev_set_check ('~give_error')
dev_error_var (ErrorVar, 1)
read_descriptor_model ('cookie_box_model.dsm', ModelID)
Error := ErrorVar
dev_set_check ('give_error')
if (Error != H_MSG_TRUE)
* Create the descriptor-based model if it's not available on disk
dev_display (Image)
dev_display (Rectangle)
disp_message (WindowHandle, 'Reading the descriptor-based model file from disk ... \n... failed!', 'window', 10, 10, 'black', 'true')
disp_message (WindowHandle, 'Creating the descriptor-based model (may take a minute)', 'window', 48, 10, 'black', 'true')
*
count_seconds (SecondsCreation1)
create_calib_descriptor_model (ImageReduced, CamParam, Pose, 'harris_binomial', [], [], ['depth','number_ferns','patch_size','min_scale','max_scale'], [11,30,17,0.4,1.2], 42, ModelID)
count_seconds (SecondsCreation2)
TimeCreation := SecondsCreation2 - SecondsCreation1
* Ignore writing errors as they are not critical for this example
dev_set_check ('~give_error')
write_descriptor_model (ModelID, 'cookie_box_model.dsm')
dev_set_check ('give_error')
ReCreateDescrModel := true
endif
endif
*
*
if (ReCreateDescrModel)
dev_display (Image)
disp_message (WindowHandle, 'One model created in ' + TimeCreation$'.03f' + ' seconds.', 'window', 10, 10, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
endif
*
*
* Main loop:
* search model in image sequence
for Index := 1 to 10 by 1
OutputString := []
read_image (Image, 'packaging/cookie_box_' + Index$'.02')
dev_display (Image)
*
* find model (using default parameters)
count_seconds (Seconds1)
find_calib_descriptor_model (Image, ModelID, [], [], [], [], 0.25, 1, CamParam, 'num_points', Pose, Score)
count_seconds (Seconds2)
Time := Seconds2 - Seconds1
*
* display results
if (|Score| > 0)
get_descriptor_model_points (ModelID, 'search', 0, Row, Col)
dev_set_colored (12)
dev_set_line_width (1)
gen_cross_contour_xld (Cross1, Row, Col, 6, 0.785398)
dev_display (Cross1)
dev_set_color ('lime green')
dev_set_line_width (3)
disp_3d_coord_system (WindowHandle, CamParam, Pose, 0.07)
*
pose_to_hom_mat3d (Pose, HomMat3D)
affine_trans_point_3d (HomMat3D, XOuterBox, YOuterBox, [0,0,0,0], XTrans, YTrans, ZTrans)
project_3d_point (XTrans, YTrans, ZTrans, CamParam, RowTrans, ColTrans)
*
*
gen_contour_polygon_xld (Contour, RowTrans, ColTrans)
close_contours_xld (Contour, Contour)
dev_display (Contour)
*
* determine direction of box
if ((Pose[5] > 45 and Pose[5] < 135) or (Pose[5] > 225 and Pose[5] < 315))
OutputString := 'Box label found in ' + (Time * 1000)$'.4' + ' ms (on the side)'
elseif (Pose[5] > 135 and Pose[5] < 225)
OutputString := 'Box label found in ' + (Time * 1000)$'.4' + ' ms (upside down)'
else
OutputString := 'Box label found in ' + (Time * 1000)$'.4' + ' ms'
endif
endif
if (|Score| == 0)
OutputString := 'No label found'
endif
disp_message (WindowHandle, OutputString, 'window', 10, 10, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
endfor
dev_display (Image)
disp_message (WindowHandle, 'Program finished.\nPress \'Run\' to clear all descriptor models.', 'window', 10, 10, 'black', 'true')
stop ()
dev_update_on ()

---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!


少有人走的路


















