Halcon拼接图像

一、Halcon拼接图像方式分为两大块,一是已知两图像间需要拼接的位置和坐标,通过算子tile_images或者tile_images_offset进行硬拼接。二是通过两图之间互相重叠部分的图像特征点,通过特征点匹配和投影变换来拼接。第一种拼接较为简单,本文讲的是第二种。
二、本文通过互相之间有重叠区域的四张图像,进行拼接。图像拼接不能损失原始图像信息
为达到以上目标,图像拼接要求具备以下条件:
1.图像应具有一定的纹理特征,拼接正是通过这些特征来进行的。
2.图像需要具有重叠部分,一般情况下,这些重叠部分点图像的1/4以上较为合理。
3.图像的背景亮度差异不能太大,应该低于10个灰度值,否则难以拼接成功。
4.图像的方位差异不能太大,图像应该来源同一方位。
5.拼合边界过渡应平滑,以消除接拼痕迹
图像拼接前,根据图像情况,可以进行图像预处理,主要是对图像进行校正和噪声滤波。下面是实例代码

*此示例程序显示了如何组合PCB的多个图像
*转换成PCB的大马赛克图像。该程序展示了如何使用
*proj_match_points_ransca和gen_projective_msaic来实现这一点。
*请注意,PCB的表面有一些退化,看起来
*像褶皱一样,很容易被误认为是图像之间的接缝
*在马赛克图像中。为了表明情况并非如此,程序
*还显示了马赛克图像的真实接缝
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 4 by 1
    read_image (Image, J+'.png')
    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')
stop ()
*显示用于计算投影的点匹配
*图像之间的转换,我们将在一个大的
*平铺图像,图像之间有一些空间,以便
*其中的图像很容易被看到
dev_set_window_extents (-1, -1, 640 / 4, 2980 / 4)
tile_images_offset (Images, TiledImage, [0,362,724,1086], [0,0,0,0], [-1,-1,-1,-1], [-1,-1,-1,-1], [-1,-1,-1,-1], [-1,-1,-1,-1], 650, 1448)
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 ()
*现在我们计算一共4个图像,其实是3对图像之间的点匹配
*图像对之间的投影变换。请注意,代码
*下面调用每个图像对的点运算符。
*通过保存上一次迭代的点(对J中的ImageT将
*与对J+1中的ImageF相同)。
dev_clear_window ()
dev_display (TiledImage)
disp_message (WindowHandle, 'Point matches', 'window', 12, 3, 'black', 'true')
*我们定义图像对,即哪个图像应该映射到哪个图像。
From := [1,2,3]
To := [2,3,4]
Num := |From|
*我们需要一个变量来累积投影变换矩阵。
ProjMatrices := []
*此外,由于我们想在下面创建一个刚性马赛克,我们需要
*累积所有点对应关系和每个点的匹配次数
*图像对。
Rows1 := []
Cols1 := []
Rows2 := []
Cols2 := []
NumMatches := []
*现在我们可以确定3个图像对之间的变换
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, 362, 650, 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) * 362, ColJunctionsF, 6, rad(45))
    gen_cross_contour_xld (PointsT, RowJunctionsT + (T - 1) * 362, ColJunctionsT, 6, rad(45))
    *将匹配的点对表示为直线。我们创造
    *XLD轮廓线,以便我们可以放大到图形窗口
    *仔细看一下匹配。
    RowF := subset(RowJunctionsF,Points1) + (F - 1) * 362
    ColF := subset(ColJunctionsF,Points1)
    RowT := subset(RowJunctionsT,Points2) + (T - 1) * 362
    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
   *现在显示提取的数据。
    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)
*保存拼接好的图像
write_image (MosaicImage, 'png', 0, '10.png')
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 ()
*为了更清楚地显示图像中可见的折叠不是由
*镶嵌,我们在镶嵌图像中显示图像之间的接缝。
*这可以通过创建包含边框的图像来最容易地完成
*的图像,从中生成马赛克,并对结果进行分割
*马赛克图像。
get_image_size (Image, Width, Height)
gen_image_const (ImageBlank, 'byte', Width, Height)
gen_rectangle1 (Rectangle, 0, 0, Height - 1, Width - 1)
paint_region (Rectangle, ImageBlank, ImageBorder, 255, 'margin')
gen_empty_obj (ImagesBorder)
for J := 1 to 4 by 1
    concat_obj (ImagesBorder, ImageBorder, ImagesBorder)
endfor
gen_projective_mosaic (ImagesBorder, MosaicImageBorder, 2, From, To, ProjMatrices, 'default', 'false', MosaicMatrices2D)
threshold (MosaicImageBorder, Seams, 128, 255)
dev_clear_window ()
dev_display (MosaicImage)
disp_message (WindowHandle, 'Seams between the\nimages', 'window', 12, 12, 'black', 'true')
dev_set_color ('yellow')
dev_display (Seams)
disp_message (WindowHandle, 'Click \'Run\'\nto continue', 'window', 550, 12, 'black', 'true')
stop ()
*如果你仔细观察上面的投影镶嵌图,你可能会注意到
*拼接图中有一个非常轻微的投影失真。这种情况会发生
*因为变换不能完全准确地确定
*因为噪声导致的点坐标中的非常小的误差。
*因为图像之间的重叠区域
*成对可以起到铰链的作用,图像可以围绕铰链旋转到图像之外
*的部分。在这个例子中,我们知道图像之间的映射必须
*是一个僵化的转变。如果我们想强制转换为刚性的
*我们可以简单地使用bundle_ajust_msaic。
bundle_adjust_mosaic (4, 1, From, To, ProjMatrices, Rows1, Cols1, Rows2, Cols2, NumMatches, 'rigid', MosaicMatrices2D, Rows, Cols, Error)
*现在,我们可以从刚性变换中生成马赛克图像。
gen_bundle_adjusted_mosaic (Images, MosaicImageRigid, MosaicMatrices2D, 'default', 'false', TransMatrix2D)
get_image_size (MosaicImageRigid, Width, Height)
dev_set_window_extents (-1, -1, Width / 3, Height / 3)
dev_clear_window ()
dev_display (MosaicImageRigid)
disp_message (WindowHandle, 'Rigid mosaic', 'window', 12, 12, 'black', 'true')

下面是4张待拼接图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
下面是拼接完成图
在这里插入图片描述

  • 8
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值