目标:
将数张有重叠部分的图像通过特征点检测,匹配,图像变换拼成一幅无缝的全景图。
待拼接的上方图片
待拼接的下方图片
#拼接成功后的图片
在图像拼接中首先利用SIFT算法提取图像特征进而进行特征匹配,继而使用RANSAC算法对特征匹配的结果进行优化,接着利用图像变换结构进行图像映射,最终进行图像融合。
在图像拼接过程中,运用SIFT局部描述算子检测图像中的关键点和特征,SIFT特征是基于物体上的一些局部外观的兴趣点而与影像的大小和旋转无关。对于光线、噪声、些微视角改变的容忍度也相当高,所以用来检测要拼接图像的特征及关键点就很有优势。而接下来即步骤三是找到重叠的图片部分,连接所有图片之后就可以形成一个基本的全景图了。匹配图片最常用的方式是采用RANSAC(RANdom SAmple Consensus, 随机抽样一致),用此排除掉不符合大部分几何变换的匹配。之后利用这些匹配的点来估算单应矩阵”(Homography Estimation),也就是将其中一张图像通过关联性和另一张匹配。
在计算特征点会出现左图多个相同目标和右图的目标匹配成功所以我的处理
是将左图右边的1/5,右图左边的1/5进行提取图像特征,并进行特征匹配。
代码实现如下:
H是3x3视角变换矩阵
,img_origcorners_orig = np.array([[0, 0, imageA.shape[0], imageA.shape[0]],
[0, imageA.shape[1], 0, imageA.shape[1]],
[1, 1, 1, 1]])
transform_corners = np.matmul(H, corners_orig)
transform_corners(34) 结果的每一列的前2维分别是img_orig在warpPerspective images图像中的四个corners坐标
x’=(h11x+h12y+h13)/(h31x+h32y+1),y’=(h21x+h22y+h23)/(h31x+h32*y+1)变换得到该点在另一幅图像的位置。
变换结果
(imageB, imageA) = images
imagea=copy.copy(imageA)
imageb = copy.copy(imageB)
imagea=self.Convert(imagea,int(imageA.shape[1] / 5),imageA.shape[1])
imageb=self.Convert(imageb, 0,imageB.shape[1]-int(imageB.shape[1] / 5))
(kpsA, featuresA) = self.detectAndDescribe(imagea)
(kpsB, featuresB) = self.detectAndDescribe(imageb)
# 匹配两张图片的所有特征点,返回匹配结果
M = self.matchKeypoints(kpsA, kpsB, featuresA, featuresB, ratio, reprojThresh)
拼接过程会用到加权融合去除图像拼接缝,先通过在warpPerspective image的图像坐标,
def get_transform_corners(imageA,H):
corners_orig = np.array([[0, 0, imageA.shape[0], imageA.shape[0]],
[0, imageA.shape[1], 0, imageA.shape[1]],
[1, 1, 1, 1]])
transform_corners = np.matmul(H, corners_orig)
return transform_corners
#加权融合去接缝
def removal_seam_updown(img_trans, img_targ, transform_corners, threshold=20):
# img_trans warpPerspective image
# img_targ target image
# transform_corners the 4 corners of warpPerspective image
# corners_orig = np.array([[0, 0, 1],
# [0, img.shape[0], 1],
# [img.shape[1], 0, 1],
# [img.shape[1], img.shape[0], 1]])
# obtain 4 corners from T transform
pano = copy.deepcopy(img_trans)
pano[0:img_targ.shape[0], 0:img_targ.shape[1]] = img_targ
y_down = img_targ.shape[1]
y_top = int(min(transform_corners[1, 0], transform_corners[1, 1]))
cols=pano.shape[1]
# calculate weight matrix
alphas = np.array([y_down - np.arange(y_top, y_down)]*cols) / (y_down - y_top)
alphas=alphas.T
alpha_matrix = np.ones((alphas.shape[0], alphas.shape[1], 3))
alpha_matrix[:, :, 0] = alphas
alpha_matrix[:, :, 1] = alphas
alpha_matrix[:, :, 2] = alphas
# common area one image no pixels
alpha_matrix[img_trans[y_top:y_down, 0:cols, :] <= threshold] = 1
img_targ = pano[:, 0:img_targ.shape[1]