OpenCV-图像拼接

时间:2024-09-30 09:32:17

文章目录

  • 一、基本原理
  • 二、步骤
  • 三、代码实现
    • 1.定义函数
    • 2.读取图像
    • 3.图像配准
      • (1).特征点检测
      • (2).特征匹配
    • 4.透视变换
    • 5.图像拼接
  • 四、图像拼接的注意事项

图像拼接是一种将多张有重叠部分的图像合并成一张无缝的全景图或高分辨率图像的技术。它在许多领域都有广泛的应用,如摄影、虚拟现实、医学成像等。

一、基本原理

图像拼接的基本原理是通过找到不同图像之间的相似性或重叠区域,利用这些区域将图像无缝地融合在一起,形成一幅更大的图像。这个过程通常包括图像预处理、图像配准、建立变换模型、统一坐标变换以及融合重构等步骤。

二、步骤

  • 图像预处理
    • 去噪:去除图像中的噪声,提高图像质量。
    • 边缘提取:提取图像的边缘信息,有助于后续的配准和融合。
    • 直方图处理:调整图像的亮度、对比度等,使不同图像在视觉上更加一致。
  • 图像配准
    • 特征点检测:使用算法(如SIFT、SURF、ORB等)检测图像中的特征点。
    • 特征匹配:根据特征点的描述符进行匹配,找到不同图像之间的对应点。
    • 变换关系计算:根据匹配点计算图像之间的变换关系,如单应性矩阵或仿射变换矩阵。
  • 建立变换模型
    • 根据匹配点之间的对应关系,建立数学模型,描述图像之间的变换关系。
  • 统一坐标变换
    • 将待拼接图像根据变换模型转换到同一坐标系中,使图像在空间位置上对齐。
  • 图像融合
    • 在图像的重叠区域进行融合处理,消除拼接痕迹,使拼接后的图像看起来自然无缝。
    • 融合方法包括多带混合、泊松图像编辑等。

三、代码实现

在OpenCV中,图像拼接通常涉及到特征检测、特征匹配、计算变换矩阵(如单应性矩阵或仿射变换矩阵)以及使用这些矩阵将图像变换到统一坐标系下,最后进行图像拼接的过程。

1.定义函数

import cv2
import numpy as np
import sys
def cv_show(name, img):
    cv2.imshow(name, img)
    cv2.waitKey(0)


def detectAndDescribe(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    descriptor = cv2.SIFT_create()
    (kps, des) = descriptor.detectAndCompute(gray, None)
    kps_float = np.float32([kp.pt for kp in kps])
    return (kps, kps_float, des)
  • 首先我们定义了两个函数,cv_show用来展示图像,detectAndDescribe使用了 OpenCV 的
    SIFT(尺度不变特征变换)算法来检测图像中的关键点和计算这些关键点的描述符。

2.读取图像

"""读取图片"""
imageA = cv2.imread('xiangjiA.jpg')
cv_show('A', imageA)
imageB = cv2.imread('xiangjiB.jpg')
# imageB = cv2.resize(imageB,(662, 604))
cv_show('B', imageB)
  • 使用cv2.imread()读取图片。
  • 使用cv_show()函数显示图片。
    在这里插入图片描述

3.图像配准

(1).特征点检测

"""计算图片特征点及描述符"""
(kpsA, kps_floatA, desA) = detectAndDescribe(imageA)
(kpsB, kps_floatB, desB) = detectAndDescribe(imageB)
  • 调用定义的函数detectAndDescribe
  • 将图片转换为灰度图。
  • 使用SIFT算法(cv2.SIFT_create())检测特征点和计算描述符。

(2).特征匹配

"""建立暴力匹配器BFMatcher,在匹配大型训练集合时使用FlannBaesdMatcher速度快"""
matcher = cv2.BFMatcher()
rawMatches = matcher.knnMatch(desB, desA, 2)
good = []
matches = []
for m in rawMatches:
    if len(m) == 2 and m[0].distance < 0.65 * m[1].distance:
        goodB.append(m)
        matchesB.append((m[0].trainIdx, m[0].queryIdx))
rawMatchesA = matcher.knnMatch(desA, desB, 2)
print(len(good))
print(matches)

vis = cv2.drawMatchesKnn(imageB, kpsB, imageA, kpsA, good, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

cv_show('Keypoint Maxtchs', vis)
  • 使用BFMatcher(暴力匹配器)进行特征点匹配,并应用Lowe’s ratio test来筛选好的匹配点。
  • 分别计算从imageB到imageA的匹配点。

在这里插入图片描述

4.透视变换

"""透视变换"""
if len(matches) > 4:
    ptsA = np.float32([kps_floatA[i] for (i, _) in matches])  # matches是通过阈值筛选之后的特征点对象
    ptsB = np.float32([kps_floatB[i] for (_, i) in matches])  # kps_floatA是图片A中的全部特征点坐标
    (H, mask) = cv2.findHomography(ptsB, ptsA, cv2.RANSAC, 10)

else:
    print('图片未找到4个以上的匹配点')
    sys.exit()
result = cv2.warpPerspective(imageB, H, (imageB.shape[1] + imageA.shape[1], imageB.shape[0]))
  • 如果匹配点数量超过4个,则使用cv2.findHomography()计算单应性矩阵。
  • 使用单应性矩阵和cv2.warpPerspective()进行透视变换。

5.图像拼接

cv_show('result', result)
result[0:imageA.shape[0], 0:imageA.shape[1]] = imageA
cv_show('resultB', result)
  • 将变换后的图片与另一张图片合并,并显示结果。这里我们是从图像左上角位置开始合并。
    在这里插入图片描述
    在这里插入图片描述
    以上是一个基本的图像拼接流程。在实际应用中,可能需要调整特征检测器的参数、匹配阈值以及RANSAC的阈值,以获得最佳结果。此外,对于复杂场景或大规模数据集,可能还需要考虑并行处理和优化内存使用等问题。

四、图像拼接的注意事项

  • 确保图像有重叠部分:图像拼接依赖于图像之间的重叠区域,因此确保待拼接图像有足够的重叠是非常重要的。
  • 选择合适的拼接方法:不同的拼接方法适用于不同的场景和需求,选择合适的拼接方法可以获得更好的效果。
  • 调整参数:在拼接过程中,可能需要调整一些参数(如特征点检测器的阈值、匹配阈值等),以获得最佳的拼接效果。
  • 检查拼接效果:拼接完成后,仔细检查拼接效果,确保没有明显的拼接痕迹或失真现象。

通过以上步骤和注意事项,可以实现高质量的图像拼接,满足各种应用需求。