输入图片
Halcon拼接程序
dev_update_off ()
dev_close_window ()
dev_open_window (0, 0, 640, 480, 'white', WindowHandle)
dev_set_color ('green')
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
gen_empty_obj (Images)
for J := 1 to 6 by 1
read_image (Image, 'mosaic/pcb_' + J$'02')
concat_obj (Images, Image, Images)
dev_display (Image)
disp_message (WindowHandle, 'Image ' + J$'d', 'window', 12, 12, 'black', 'true')
wait_seconds (1)
endfor
disp_continue_message (WindowHandle, 'black', 'true')
*为了显示点匹配,用于计算图像之间的射影变换,我们将显示所有的图像在一个大
*平铺图像与一些空间之间的图像,以便图像的范围很容易看到。
dev_set_window_extents (-1, -1, 640 / 4, 2980 / 4)
tile_images_offset (Images, TiledImage, [0, 500, 1000, 1500, 2000, 2500], [0, 0, 0, 0, 0, 0], [-1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1], [-1, -1, -1, -1, -1, -1], 640, 2980)
dev_clear_window ()
dev_display (TiledImage)
disp_message (WindowHandle, 'All 6 images', 'window', 12, 12, 'black', 'true')
disp_message (WindowHandle, 'Click \'Run\'\nto continue', 'window', 2980 / 4 - 50, 12, 'black', 'true')
stop ()
*现在我们计算五对图像之间的点匹配,用这个计算图像对之间的射影变换。
*注意下面的代码为每个图像对调用点运算符。
*因为这些图像形成了一个条形,所以我们可以将这一过程做得更详细一些
*通过保存上次迭代的点来提高效率(image et在pair J中与ImageF在pair J+1中相同)。
*这里没有这样做,因为这样的优化在一般情况下是非常麻烦的,因为图像可能位于一个无法被复制的一般配置中
dev_clear_window ()
dev_display (TiledImage)
disp_message (WindowHandle, 'Point matches', 'window', 12, 3, 'black', 'true')
* 我们定义图像对,即哪个图像应该映射到哪个图像。
From := [1, 2, 3, 4, 5]
To := [2, 3, 4, 5, 6]
Num := |From|
ProjMatrices := []
Rows1 := []
Cols1 := []
Rows2 := []
Cols2 := []
NumMatches := []
* 现在我们可以确定这五个图像对之间的转换。
for J := 0 to Num - 1 by 1
F := From[J]
T := To[J]
select_obj (Images, ImageF, F)
select_obj (Images, ImageT, T)
*提取两个图像中的点。
points_foerstner (ImageF, 1, 2, 3, 200, 0.3, 'gauss', 'false', RowJunctionsF, ColJunctionsF, CoRRJunctionsF, CoRCJunctionsF, CoCCJunctionsF, RowAreaF, ColAreaF, CoRRAreaF, CoRCAreaF, CoCCAreaF)
points_foerstner (ImageT, 1, 2, 3, 200, 0.3, 'gauss', 'false', RowJunctionsT, ColJunctionsT, CoRRJunctionsT, CoRCJunctionsT, CoCCJunctionsT, RowAreaT, ColAreaT, CoRRAreaT, CoRCAreaT, CoCCAreaT)
*确定当前图像对的点匹配和转换。
proj_match_points_ransac (ImageF, ImageT, RowJunctionsF, ColJunctionsF, RowJunctionsT, ColJunctionsT, 'ncc', 21, 0, 0, 480, 640, 0, 0.5, 'gold_standard', 1, 4364537, ProjMatrix, Points1, Points2)
* 累加变换矩阵。
ProjMatrices := [ProjMatrices,ProjMatrix]
*累积点匹配和点匹配的数量。
Rows1 := [Rows1,subset(RowJunctionsF,Points1)]
Cols1 := [Cols1,subset(ColJunctionsF,Points1)]
Rows2 := [Rows2,subset(RowJunctionsT,Points2)]
Cols2 := [Cols2,subset(ColJunctionsT,Points2)]
NumMatches := [NumMatches,|Points1|]
* 生成表示平铺图像中提取的点的叉。
*注意,我们必须考虑平铺图像中的图像行偏移量。
gen_cross_contour_xld (PointsF, RowJunctionsF + (F - 1) * 500, ColJunctionsF, 6, rad(45))
gen_cross_contour_xld (PointsT, RowJunctionsT + (T - 1) * 500, ColJunctionsT, 6, rad(45))
* 生成匹配点对的表示形式为直线。我们创建
* XLD从直线轮廓,以便我们可以放大到图形窗口,以更近距离地查看匹配。
RowF := subset(RowJunctionsF,Points1) + (F - 1) * 500
ColF := subset(ColJunctionsF,Points1)
RowT := subset(RowJunctionsT,Points2) + (T - 1) * 500
ColT := subset(ColJunctionsT,Points2)
gen_empty_obj (Matches)
for K := 0 to |RowF| - 1 by 1
gen_contour_polygon_xld (Match, [RowF[K],RowT[K]], [ColF[K],ColT[K]])
concat_obj (Matches, Match, Matches)
endfor
* Now display the extracted data.
dev_set_color ('blue')
dev_display (Matches)
dev_set_color ('green')
dev_display (PointsF)
dev_display (PointsT)
endfor
disp_message (WindowHandle, 'Click \'Run\'\nto continue', 'window', 2980 / 4 - 50, 12, 'black', 'true')
stop ()
* 最后,利用投影变换生成拼接图像。
gen_projective_mosaic (Images, MosaicImage, 2, From, To, ProjMatrices, 'default', 'false', MosaicMatrices2D)
get_image_size (MosaicImage, Width, Height)
dev_set_window_extents (-1, -1, Width / 3, Height / 3)
dev_clear_window ()
dev_display (MosaicImage)
disp_message (WindowHandle, 'Projective mosaic', 'window', 12, 12, 'black', 'true')
disp_message (WindowHandle, 'Click \'Run\'\nto continue', 'window', Height / 3 - 50, 12, 'black', 'true')
stop ()
拼接效果
最后拼接效果图