基于特征的图像对齐(SIFT或ORB)

一. 效果图

什么是图像对齐或者图像配准?
图像对齐(或者图像配准)可以扭曲旋转(其实是仿射变换)一张图使它和另一个图可以很完美的对齐。
下图为SIFT特征匹配的图。
在这里插入图片描述
下图为上面左边图矫正的结果。
在这里插入图片描述

二. 基于特征的图像对齐步骤

下面以ORB特征为例说明,SIFT特征的步骤与ORB几乎相同。

1. 读取图片到内存

2. 检测特征点

为两张图检测ORB特征点。为了计算单应性矩阵4个就够了,但是一般会检测到成百上千的特征点。可以使用参数MAX_FEATURES 来控制检测的特征点的数量。检测特征点并计算描述子的函数是detectAndCompute。

3. 特征匹配

找到两图中匹配的特征点,并按照匹配度排列,保留最匹配的一小部分。然后把匹配的特征点画出来并保存图片到磁盘。我们使用汉明距离来度量两个特征点描述子的相似度。下图中把匹配的特征点用线连起来了。注意,有很多错误匹配的特征点,所以下一步要用一个健壮的算法来计算单应性矩阵。

4. 计算单应性矩阵

上一步产生的匹配的特征点不是100%正确的,就算只有20~30%的匹配是正确的也不罕见。findHomography 函数使用一种被称为随机抽样一致算法(Random Sample Consensus )的技术在大量匹配错误的情况下计算单应性矩阵。

5. 扭转图片(Warping image)

有了精确的单应性矩阵,就可以把一张图片的所有像素映射到另一个图片。warpPerspective 函数用来完成这个功能。

三. 代码实现

from __future__ import print_function
import cv2
import numpy as np


MAX_FEATURES = 500
GOOD_MATCH_PERCENT = 0.15


def alignImages(im1, im2):

  # Convert images to grayscale
  im1Gray = cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)
  im2Gray = cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)

  # Detect ORB features and compute descriptors.
  orb = cv2.ORB_create(MAX_FEATURES)
  keypoints1, descriptors1 = orb.detectAndCompute(im1Gray, None)
  keypoints2, descriptors2 = orb.detectAndCompute(im2Gray, None)

  # Match features.
  matcher = cv2.DescriptorMatcher_create(cv2.DESCRIPTOR_MATCHER_BRUTEFORCE_HAMMING)
  matches = matcher.match(descriptors1, descriptors2, None)

  # Sort matches by score
  matches.sort(key=lambda x: x.distance, reverse=False)

  # Remove not so good matches
  numGoodMatches = int(len(matches) * GOOD_MATCH_PERCENT)
  matches = matches[:numGoodMatches]

  # Draw top matches
  imMatches = cv2.drawMatches(im1, keypoints1, im2, keypoints2, matches, None)
  cv2.imwrite("matches.jpg", imMatches)

  # Extract location of good matches
  points1 = np.zeros((len(matches), 2), dtype=np.float32)
  points2 = np.zeros((len(matches), 2), dtype=np.float32)

  for i, match in enumerate(matches):
    points1[i, :] = keypoints1[match.queryIdx].pt
    points2[i, :] = keypoints2[match.trainIdx].pt

  # Find homography
  h, mask = cv2.findHomography(points1, points2, cv2.RANSAC)

  # Use homography
  height, width, channels = im2.shape
  im1Reg = cv2.warpPerspective(im1, h, (width, height))

  return im1Reg, h



if __name__ == '__main__':

  # Read reference image
  refFilename = "img1.png"
  print("Reading reference image : ", refFilename)
  imReference = cv2.imread(refFilename, cv2.IMREAD_COLOR)

  # Read image to be aligned
  imFilename = "img2.png"
  print("Reading image to align : ", imFilename);  
  im = cv2.imread(imFilename, cv2.IMREAD_COLOR)

  print("Aligning images ...")
  # Registered image will be resotred in imReg. 
  # The estimated homography will be stored in h. 
  imReg, h = alignImages(im, imReference)

  # Write aligned image to disk. 
  outFilename = "aligned.jpg"
  print("Saving aligned image : ", outFilename); 
  cv2.imwrite(outFilename, imReg)

  # Print estimated homography
  print("Estimated homography : \n",  h)

每天进步一点,加油!!!
欢迎技术交流,如果想用SIFT特征实现,请联系作者。
在这里插入图片描述

  • 8
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
很抱歉,由于篇幅和版权等问题,我无法在此提供完整的源代码。但是,我可以给您提供一个基本的代码框架和思路,供您参考。 首先,您需要安装OpenCV库,以便进行图像处理和特征提取等操作。接下来,您可以按照以下步骤进行编码: 1. 加载图像并进行预处理,包括图像校正、去畸变、去噪等。 ```python import cv2 # 加载图像 img1 = cv2.imread("image1.jpg") img2 = cv2.imread("image2.jpg") # 进行预处理 # TODO: 图像校正、去畸变、去噪等操作 ``` 2. 利用SIFTORB等局部特征提取算法,提取图像的关键点和描述子。 ```python # 创建SIFTORB对象 sift = cv2.xfeatures2d.SIFT_create() orb = cv2.ORB_create() # 提取关键点和描述子 kp1, des1 = sift.detectAndCompute(img1, None) kp2, des2 = sift.detectAndCompute(img2, None) ``` 3. 采用FLANN或者K-D Tree等算法进行特征匹配。 ```python # 创建FLANN对象 FLANN_INDEX_KDTREE = 1 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) ``` 4. 利用RANSAC算法筛选出匹配点对,并计算出图像间的仿射变换矩阵。 ```python # 筛选好的匹配点对 good_matches = [] # RANSAC算法阈值 ransac_thresh = 5.0 for m, n in matches: if m.distance < 0.7 * n.distance: good_matches.append(m) if len(good_matches) > 4: # 获取匹配点的坐标 src_pts = np.float32([ kp1[m.queryIdx].pt for m in good_matches ]).reshape(-1, 1, 2) dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good_matches ]).reshape(-1, 1, 2) # 进行RANSAC筛选和仿射变换 M, mask = cv2.estimateAffinePartial2D(src_pts, dst_pts, method=cv2.RANSAC, ransacReprojThreshold=ransac_thresh) ``` 5. 利用仿射变换矩阵对图像进行坐标对齐和融合,得到全景图像。 ```python # 进行仿射变换 result = cv2.warpAffine(img1, M, (img1.shape[1], img1.shape[0])) # 将两张图像拼接在一起 result[0:img2.shape[0], 0:img2.shape[1]] = img2 # 显示全景图像 cv2.imshow("result", result) cv2.waitKey(0) ``` 6. 最后进行全景图像的后处理,包括色彩校正、去瑕疵、去噪等。 ```python # TODO: 进行全景图像的后处理,包括色彩校正、去瑕疵、去噪等操作 ``` 以上就是一个基本的全景拼接系统的代码框架和思路,具体实现需要根据具体情况进行调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值