图像配准:基于 OpenCV 的高效实现

简介: 图像配准:基于 OpenCV 的高效实现

在这篇文章中,我将对图像配准进行一个简单概述,展示一个最小的 OpenCV 实现,并展示一个可以使配准过程更加高效的简单技巧。


什么是图像配准


图像配准被定义为将不同成像设备或传感器在不同时间和角度拍摄的两幅或多幅图像,或来自同一场景的两幅或多幅图像叠加起来,以几何方式对齐图像以进行分析的过程(Zitová 和 Flusser,2003 年)。


百度百科给出的解释


图像配准:图像配准(Image registration)就是将不同时间、不同传感器(成像设备)或不同条件下(天候、照度、摄像位置和角度等)获取的两幅或多幅图像进行匹配、叠加的过程,它已经被广泛地应用于遥感数据分析、计算机视觉、图像处理等领域。


医学科学、遥感和计算机视觉都使用图像配准。


有两种主要方法:

  • 经典计算机视觉方法(使用 OpenCV)——我们将在本文中关注的内容
  • 基于深度学习的方法

虽然后者可以更好地工作,但它可能需要一些“域”适应(在你的数据上微调神经网络)并且可能计算量太大。


使用 OpenCV 进行图像配准


基于特征的方法:由单应变换关联的图像对


此操作试图发现两张照片之间的匹配区域并在空间上对齐它们以最大限度地减少错误。


我们的目标是找到一个单应性矩阵 H,它告诉我们需要如何修改其中一张图像,使其与另一张图像完美对齐。


第 1 步:关键点检测


关键点定义了图像中一个独特的小区域(角、边缘、图案)。关键点检测器的一个重要方面是找到的区域应该对图像变换(例如定位、比例和亮度)具有鲁棒性,因为这些区域很可能出现在我们试图对齐的两个图像中。有许多执行关键点检测的算法,例如 SIFT、ORB、AKAZE、SURF 等。


第 2 步:特征匹配


现在我们必须匹配来自两个图像的关键点,这些关键点实际上对应于同一点。


第 3 步:单应性


单应性通常由一个 3x3 矩阵表示,它描述了应该应用于一个图像以与另一个图像对齐的几何变换。


第 4 步:图像变形


找到单应性矩阵后,我们可以用它来对齐图像。下面是该过程的代码:

    import numpy as np
    import cv2 as cv
    import matplotlib.pyplot as plt
    img1 = cv.imread('image1.jpg', cv.IMREAD_GRAYSCALE)  # referenceImage
    img2 = cv.imread('image2.jpg', cv.IMREAD_GRAYSCALE)  # sensedImage
    # Initiate SIFT detector
    sift_detector = cv.SIFT_create()
    # Find the keypoints and descriptors with SIFT
    kp1, des1 = sift_detector.detectAndCompute(img1, None)
    kp2, des2 = sift_detector.detectAndCompute(img2, None)
    # BFMatcher with default params
    bf = cv.BFMatcher()
    matches = bf.knnMatch(des1, des2, k=2)
    # Filter out poor matches
    good_matches = []
    for m,n in matches:
        if m.distance < 0.75*n.distance:
            good_matches.append(m)
    matches = 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, :] = kp1[match.queryIdx].pt
        points2[i, :] = kp2[match.trainIdx].pt
    # Find homography
    H, mask = cv2.findHomography(points1, points2, cv2.RANSAC)
    # Warp image 1 to align with image 2
    img1Reg = cv2.warpPerspective(img1, H, (img2.shape[1], img2.shape[0]))
    cv.imwrite('aligned_img1.jpg', img1Reg)The problem is that this matrix H is found via a compute-intensive optimization process.


    高效的图像配准

    无论您为每个步骤选择的参数如何,对执行时间影响最大的是图像的分辨率。您可以大幅调整它们的大小,但如果您需要对齐的图像具有原始分辨率,会发生什么情况?


    幸运的是,有办法解决这个问题。事实证明,您可以计算低分辨率图像的变换,然后调整此变换以适用于全分辨率图像。


    详细步骤:

    1. 调整图像大小
    2. 在低分辨率图像上计算矩阵 H
    3. 变换矩阵 H 使其适用于全分辨率图像
    4. 将新矩阵应用于原始图像。


    第 3 步可能是这里最不明显的部分,所以让我们看看它是如何工作的:


    我们想要调整在低分辨率图像上计算的变换以适用于高分辨率图像。因此,我们希望高分辨率图像中的每个像素执行以下操作:


    缩小到低分辨率 -> 应用变换 H -> 放大到高分辨率


    幸运的是,所有这些步骤都只是矩阵乘法,我们可以将所有这些步骤组合在一个单一的转换中。


    设 H 为您计算出的变换。您可以将 H 乘以另一个单应性 A,得到 AH = H',其中 H' 是进行两种变换的单应性,相当于先应用 H,然后应用 A。


    下面是详细代码:

      import numpy as np
      import cv2 as cv
      import matplotlib.pyplot as plt
      img1 = cv.imread('image1.jpg', cv.IMREAD_GRAYSCALE)  # referenceImage
      img2 = cv.imread('image2.jpg', cv.IMREAD_GRAYSCALE)  # sensedImage
      #  Resize the image by a factor of 8 on each side. If your images are 
      # very high-resolution, you can try to resize even more, but if they are 
      # already small you should set this to something less agressive.
      resize_factor = 1.0/8.0
      img1_rs = cv.resize(img1, (0,0), fx=resize_factor, fy=resize_factor)
      img2_rs = cv.resize(img2, (0,0), fx=resize_factor, fy=resize_factor)
      # Initiate SIFT detector 
      sift_detector = cv.SIFT_create()
      # Find the keypoints and descriptors with SIFT on the lower resolution images
      kp1, des1 = sift_detector.detectAndCompute(img1_rs, None)
      kp2, des2 = sift_detector.detectAndCompute(img2_rs, None)
      # BFMatcher with default params
      bf = cv.BFMatcher()
      matches = bf.knnMatch(des1, des2, k=2)
      # Filter out poor matches
      good_matches = []
      for m,n in matches:
          if m.distance < 0.75*n.distance:
              good_matches.append(m)
      matches = 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, :] = kp1[match.queryIdx].pt
          points2[i, :] = kp2[match.trainIdx].pt
      # Find homography
      H, mask = cv2.findHomography(points1, points2, cv2.RANSAC)
      # Get low-res and high-res sizes
      low_height, low_width = img1_rs.shape
      height, width = img1.shape
      low_size = np.float32([[0, 0], [0, low_height], [low_width, low_height], [low_width, 0]])
      high_size = np.float32([[0, 0], [0, height], [width, height], [width, 0]])
      # Compute scaling transformations
      scale_up = cv.getPerspectiveTransform(low_size, high_size)
      scale_down = cv.getPerspectiveTransform(high_size, low_size)
      #  Combine the transformations. Remember that the order of the transformation 
      # is reversed when doing matrix multiplication
      # so this is actualy scale_down -> H -> scale_up
      h_and_scale_up = np.matmul(scale_up, H)
      scale_down_h_scale_up = np.matmul(h_and_scale_up, scale_down)
      # Warp image 1 to align with image 2
      img1Reg = cv2.warpPerspective(
                  img1, 
                  scale_down_h_scale_up, 
                  (img2.shape[1], img2.shape[0])
                )
      cv.imwrite('aligned_img1.jpg', img1Reg)
      相关文章
      |
      2月前
      |
      计算机视觉
      Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
      这篇文章详细介绍了OpenCV库中的图像二值化函数`cv2.threshold`,包括二值化的概念、常见的阈值类型、函数的参数说明以及通过代码实例展示了如何应用该函数进行图像二值化处理,并展示了运行结果。
      505 0
      Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
      |
      3月前
      |
      算法 计算机视觉
      opencv图像形态学
      图像形态学是一种基于数学形态学的图像处理技术,它主要用于分析和修改图像的形状和结构。
      54 4
      |
      3月前
      |
      存储 计算机视觉
      Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
      本文介绍了使用OpenCV进行图像读取、显示和存储的基本操作,以及如何绘制直线、圆形、矩形和文本等几何图形的方法。
      Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
      |
      4月前
      |
      算法 计算机视觉 Python
      python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)
      该文章详细介绍了使用Python和OpenCV进行相机标定以获取畸变参数,并提供了修正图像畸变的全部代码,包括生成棋盘图、拍摄标定图像、标定过程和畸变矫正等步骤。
      python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)
      WK
      |
      4月前
      |
      编解码 计算机视觉 Python
      如何在OpenCV中进行图像转换
      在OpenCV中,图像转换涉及颜色空间变换、大小调整及类型转换等操作。常用函数如`cvtColor`可实现BGR到RGB、灰度图或HSV的转换;`resize`则用于调整图像分辨率。此外,通过`astype`或`convertScaleAbs`可改变图像数据类型。对于复杂的几何变换,如仿射或透视变换,则可利用`warpAffine`和`warpPerspective`函数实现。这些技术为图像处理提供了强大的工具。
      WK
      123 1
      |
      6月前
      |
      算法 计算机视觉
      【Qt&OpenCV 图像的感兴趣区域ROI】
      【Qt&OpenCV 图像的感兴趣区域ROI】
      211 1
      |
      6月前
      |
      运维 算法 计算机视觉
      【Qt&OpenCV 图像的模板匹配 matchTemplate/minMaxLoc】
      【Qt&OpenCV 图像的模板匹配 matchTemplate/minMaxLoc】
      84 1
      |
      6月前
      |
      存储 编解码 算法
      【Qt&OpenCV 检测图像中的线/圆/轮廓 HoughLinesP/HoughCircles/findContours&drawContours】
      【Qt&OpenCV 检测图像中的线/圆/轮廓 HoughLinesP/HoughCircles/findContours&drawContours】
      103 0
      |
      5月前
      |
      机器学习/深度学习 XML 计算机视觉
      OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习库,它提供了大量的函数和工具,用于处理图像和视频数据。
      OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习库,它提供了大量的函数和工具,用于处理图像和视频数据。
      |
      6月前
      |
      计算机视觉
      OpenCV中图像算术操作与逻辑操作
      OpenCV中图像算术操作与逻辑操作
      74 1