1.什么是图像配准
图像配准是对不同时间、不同传感器等获取的多幅图像进行匹配、信息融合以转换到相同坐标系中的过程。与图像匹配的区别在于要对变形的图像进行旋转、平移之类的校正。图像融合:两幅图像配准后进行叠加,变成一幅大图。常用于视频集成的多幅图像连接成一幅大图像。
2.图像配准
图像配准可以分为粗配准和精配准。
2.1粗配准
粗配准:对任意的两张图片相对位姿完全未知的情况下进行粗略的配准,为精配准提供良好的初始值。其算法主要有两类,一是基于全局搜索的配准算法,二是基于特征匹配的配准算法。
2.1.1基于全局搜索的配准算法
此算法是遍历整个变换空间,通过投票方式(最多点对满足)或选取误差函数最小的方式确定最优变换。这种算法考虽然可以取得较好配准效果,但往往计算负荷较大。当照片要通过灰度/颜色进行信息区分时,用此算法。
2.1.2基于特征匹配的配准算法
当图片强度提供更多的局部结构信息,通过局部形式和结构匹配对应时,用此算法。其核心步骤为:特征提取、特征匹配、模型参数估计、图像变换、灰度插值。
基于特征匹配后进行图像配准。首先要进行单应性变换,它描述的是图像的两个平面投影之间的映射,由于两个平面之间关系是确定的,故此矩阵唯一。单应性矩阵可以看成二维操作到三维操作的一个过渡,是一个3*3的矩阵。函数如下,srcPoints代表源平面中点的坐标矩阵,dstPoints是目标平面中点的坐标矩阵,RANSAC是基于RANSAC的鲁棒算法,ransacReprojThreshold是内点最大允许重投影错误阈值,取值范围1-10;正确估计的好的匹配是内点,其它的是外点。H是计算得到的单应矩阵。
H,mask=cv2.findHomography(srcPoints,dstPoints,cv2.RANSAC,ransacReprojThreshold=5.0)
其次是透视变换,透视变换保持直线性,它是将平面投影到一个新的视平面,也称投影映射。例如从二维到三维,再到另一个二维之间的变换,仿射变换是其中一种特殊情况。src:输入双通道/三通道浮点数组,每个元素是要变换的二维/三维向量、m:3*3/4*4转换矩阵。dst:与src大小、类型相同的输出数组。perspectiveTransform()输入至少需要4个点,且点的坐标矩阵为(-1,1,2)即n个一行两列的坐标矩阵,两列代表横纵坐标,其等价于将坐标齐次化后,与H矩阵的乘法运算
perspectiveTransform(src, m, dst=None)
设置一个至少10个匹配的条件,满足条件就可以得到两张图像标记的关键点位置,然后进行透视转换。得到的3*3转换矩阵用来查询图像,搜索图的四个角点,并绘制出来。
#读取图像
img1 = cv2.imread('p1.png', 0)
img2 = cv2.imread('p2.png', 0)
#使用sift算法,计算特征向量与特征点
sift = cv2.SIFT_create() #创建一个sift算子
kp1, des1 = sift.detectAndCompute(img1, None) #计算特征点与特征向量
kp2, des2 = sift.detectAndCompute(img2, None)
#设置参数
FLANN_INDEX_KDTREE = 1 #建立FLANN匹配器的参数
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks=50) #递归次数
flann = cv2.FlannBasedMatcher(index_params,search_params)
matches = flann.knnMatch(des1, des2, k=2)
good = [] # 这里主要是匹配的更加精确,可以修改ratio值得到不同的效果,即下面的0.7
for m, n in matches:
if m.distance < 0.7 * n.distance:
good.append(m)
#当匹配项大于10时
if len(good)>=10:
#查找单应性矩阵,转换为n行的元素,每一行一个元素,并且这个元素由两个值组成
srcPoints=np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1,1,2)
dstPoints=np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1,1,2)
#获取单应性矩阵
H,mask=cv2.findHomography(srcPoints,dstPoints,cv2.RANSAC,ransacReprojThreshold=5.0)
print(H)
print(srcPoints)
#要搜索的图的四个角点
h,w=np.shape(img1)[0],np.shape(img1)[1]
pts=np.float32([[0,0],[0,h-1],[w-1,h-1],[w-1,0]]).reshape(-1,1,2)
dst=cv2.perspectiveTransform(pts,H)
#绘制多边形
cv2.polylines(img=img2,pts=[np.int32(dst)],isClosed=True,color=(0,255,0))
cv2.imshow("Sift", img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
img=cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches[:10],None,matchColor=(0,255,0))
cv2.imshow("Sift", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
输出的H矩阵:
2.2精配准
以点云精配准为例,经过粗配准,两片点云的重叠部分已经大致对齐,但精度达不到要求。精配准可以提供配准的精度,主要算法是ICP(迭代最近点)算法。
其基本思想是选取两片点云中距离最近的点作为对应点,通过对应点对求解旋转矩阵(R)和平移变换矩阵(T),通过迭代方法使两片点云之间误差越来越小,直到满足设定要求。
其核心是寻找匹配最近点和计算最优变换。