最近有一个验证仿射模型精度的需求。起因在于,有一段卫星视频,采用帧间仿射模型进行稳像总是会有局部扭曲,因此怀疑影像是不是有内畸变。为了验证这个猜想,需要对帧间的仿射模型进行精度验证。 验证方法也很简单分别在各自影像上提取特征点,然后匹配,得到同名点对。基于得到的同名点对计算两幅影像间的仿射模型,然后基于这个模型,将影像1上的特征点都计算到影像2上,理论上来说如果精度很好的话,那么计算出来的影像2上的特征点应该是与提取的特征点是完全重合的,否则就是有误差。 这其实有点类似于SLAM中光束法平差里的“重投影”思想,最小化重投影误差。
1.代码实现
# coding=utf-8
import functionsV1 as fun
import cv2
import numpy as np
if __name__ == '__main__':
img1 = cv2.imread("img1.jpg")
img2 = cv2.imread("img2.jpg")
kp1, des1 = fun.getSurfKps(img1, hessianTh=800)
kp2, des2 = fun.getSurfKps(img2, hessianTh=800)
good_kp1, good_kp2 = fun.flannMatch(kp1, des1, kp2, des2)
match_img = fun.drawMatches(img1, good_kp1, img2, good_kp2)
cv2.imwrite("match.jpg", match_img)
affine_mat = fun.findAffine(good_kp1, good_kp2)
print "Affine matrix:"
print affine_mat
T = np.mat(affine_mat[:, 2].reshape(2, 1))
R = np.mat(affine_mat[:2, :2])
print "Translation matrix:"
print T
print "Rotation matrix:"
print R
good_kp2_ = []
for i in range(good_kp1.__len__()):
pt1 = np.mat(good_kp1[i]).reshape(2, 1)
pt2_ = R * pt1 + T
good_kp2_.append(pt2_)
for i in range(good_kp2.__len__()):
pt = (int(good_kp2[i][0]), int(good_kp2[i][1]))
cv2.circle(img2, pt, 3, [0, 0, 255], 1, cv2.LINE_AA)
pt_ = (int(good_kp2_[i][0]), int(good_kp2_[i][1]))
cv2.circle(img2, pt_, 3, [255, 0, 0], 1, cv2.LINE_AA)
cv2.imwrite("check.jpg", img2)
首先,程序输出如下所示,共匹配了1598对点。 匹配的同名点图如下所示,点击查看原图,可以看到是正确的。 但基于这些正确匹配点算出来的仿射模型算出来的特征点坐标误差就很大了,运行效果局部截图如下图所示,点击查看全图。 可以看到确实是存在不均匀的畸变的(靠下部分的误差较大,靠上部分误差较小),这样的影像用单纯的仿射模型是无法解决的。如果变化规律统一,那么在局部的小块中就不应该会出现这种变化不一的情况。 项目的完整代码和测试数据在Github,点击查看。
当然,也可以利用之前这篇博客中的代码,绘制出带有箭头的误差图。
本文作者原创,未经许可不得转载,谢谢配合