参考例程mosaicking_pyramid.hdev
原理简要说明:在上一篇的基础上,我们知道了在halcon中,图像拼接的大致原理,知道了算法运行的过程,其中一个关键步骤至关重要,那就是找角点。我们知道,在halcon中我们使用的harris算法来检测角点,这里涉及到一个问题,我们是全图遍历的方式来检测角点的,那么当一个图像过大时,相应的检测时间就要增加,再加上匹配,那总时间就是指数级的增长。
对于上述现象的解决办法,在halcon中的例程中也给出了方向,在讲解之前,我们先回忆一下,模板匹配中金字塔的作用,利用金字塔这个特性,可以让我们全图遍历的效率高出很多,即先在高层金字塔处找到匹配的点,因为在高层分辨率低,所以匹配速度不会慢,找到后,逐级递减往下,虽然分辨率越来越高,但是模板大致区域也被确定,那么我们就不用全图遍历了,只去遍历上一层确定的点即可;
对于检测角点这种需要全图遍历的活,我们也可以采用金字塔的特性,而halcon中也有这样的例子,大致原理就是,先在高等级的图像对中查找角点并进行匹配,那么这个时候会得到一个投影矩阵,将这个投影矩阵应用到下一级金字塔的图像对中,来限定查找范围(DistanceTolerance),这样就可以做到优化速度
1读取拍摄图像
跳过,详情见上篇,此处只对两张图像进行拼接
2定义图像对
跳过,详情见上篇,此处只对两张图像进行拼接
3算法流程
该例程中算法全部都在proj_match_points_ransac_guided这个函数中
1取图像的各个等级金字塔图像
ImageF,ImageT分别对应图像对的两张图像
gen_gauss_pyramid (ImageF, ImageFPyramid, 'constant', 0.5)
gen_gauss_pyramid (ImageT, ImageTPyramid, 'constant', 0.5)
2在循环中寻找角点做匹配,并且逐次递减金字塔等级
for Level := NumLevels to 1 by -1
*从高到低选择图像进行角点检测
* Select images from image pyramid
select_obj (ImageFPyramid, ImageFLevel, Level)
select_obj (ImageTPyramid, ImageTLevel, Level)
* Extract interest points in both images
*检测角点
points_harris (ImageFLevel, SigmaGrad, SigmaSmooth, Alpha, Threshold, RowsF, ColsF)
points_harris (ImageTLevel, SigmaGrad, SigmaSmooth, Alpha, Threshold, RowsT, ColsT)
* Calculate projection from point correspondences
*如果是第一次,也就是最上层的图像,那么使用默认的ransac算法来进行角点匹配
if (|HomMat2DGuide| == 0)
* On the highest pyramid level, use proj_mathc_points_ransac
get_image_size (ImageFLevel, Width, Height)
proj_match_points_ransac (ImageFLevel, ImageTLevel, RowsF, ColsF, RowsT, ColsT, 'ncc',\
10, 0, 0, Height, Width, [rad(-40),rad(40)], 0.5, 'gold_standard',\
2.5 * pow(2,4 - Level), 42, ProjMatrix, Points1, Points2)
else
*如果不是第一次,即有了上一等级图像的角点投影关系,利用ransac推导算法来进行角点匹配
*DistanceTolerance=10 * pow(2.0,4.0 - Level)是随着等级不断递减,图像分辨率越来越高的情况下,\
角点在高等级图像和低等级图像之间的容差值,不好理解就理解成角点的搜索窗口,太大就会找错,并且耗时
*DistanceThreshold=2.5 * pow(2.0,4.0 - Level)是投影变换矩阵预测的点与实际找到的角点之间的距离,在此距离内
*才会被认为是匹配的角点,太大就会找错
* On lower levels, use approximation from upper level as
* input for proj_match_points_ransac_guided
proj_match_points_ransac_guided (ImageFLevel, ImageTLevel, RowsF, ColsF, RowsT, \
ColsT, 'ncc', 10, HomMat2DGuide, 10 * pow(2.0,4.0 - Level),\
0.5, 'gold_standard', 2.5 * pow(2.0,4.0 - Level), 42, \
ProjMatrix, Points1, Points2)
endif
*在匹配的角点之间进行刚体变换
if (UseRigidTransformation)
* Use found point correspondences to calculate rigid transformation
* with vector_to_rigid
* Note, that the resulting transformation of proj_match_points_ransac_guided
* is ignored in this case.
RowF := subset(RowsF,Points1)
ColF := subset(ColsF,Points1)
RowT := subset(RowsT,Points2)
ColT := subset(ColsT,Points2)
vector_to_rigid (RowF + 0.5, ColF + 0.5, RowT + 0.5, ColT + 0.5, ProjMatrix)
ProjMatrix := [ProjMatrix,0,0,1]
endif
* To be used on the next lower pyramid level, the projection has
* to be adjusted to the new scale.
* 对于给下一级金字塔的图像的投影矩阵,Tx,Ty需要进行乘2(因为下一级图像放大了一倍),其他项不用
hom_mat2d_scale (ProjMatrix, 2, 2, 0, 0, HomMat2DGuide)
hom_mat2d_scale_local (HomMat2DGuide, 0.5, 0.5, HomMat2DGuide)
endfor
对于最后的两个矩阵缩放,原理如下
hom_mat2d_scale 是缩放矩阵中所有项
hom_mat2d_scale_local 是缩放除Tx©和Ty(f)的其他所有项
最后的这两句代码不一定这样写,只要达到缩放Tx©和Ty(f)的效果而其他不变的结果即可
4图像拼接
gen_projective_mosaic (Images, MosaicImage, 1, From, To, ProjMatrix, [2,1], 'false', MosaicMatrices2D)
5结果演示
可以看到,在以不同等级的金字塔图像开始后,角点匹配的速度被优化了
从原来的原图像(1级金字塔)匹配需要2.42s,到4级金字塔只需要0.0773s,当然,不是金字塔越高越好,根据图像分辨率和角点分布来确定,例程中生成了9层,但是在进行匹配的时候只用到了1~4层,因为后面的图像太过模糊,进行匹配没意义
制作不易,觉得帮到了您,还请点个赞
另外,若觉得本文写的与您理解的有些出入,欢迎交流