当前位置:   article > 正文

OpenCV4实战:基于特征对齐的二景图像拼接_opencv 特征匹配 上下融合

opencv 特征匹配 上下融合

前言

昨天总结了基于特征的图像对齐,今天来尝试一下,基于特征对齐的二景图像拼接吧。如下图所示,这是同一地点不同角度拍摄的两幅图像,现在尝试将其进行拼接。
在这里插入图片描述

环境

  • OpenCV:4.1.2
  • Python:3.6.5
  • 平台:Windows 10

实现思路

  1. 基于 ORB 特征检测算法检测两幅图像的特征关键点
  2. 对特征点进行匹配
  3. 从所匹配的全部关键点中筛选出优秀的特征点(基于距离筛选)
  4. 计算单应性变换矩阵
  5. 对右图进行映射变换
  6. 将左图拷贝到特定位置完成拼接

代码演示

import numpy as np
import cv2 as cv
# 导入自己写的一个工具库
import opencv_utils

MAX_FEATURES = 500
GOOD_MATCH_PERCENT = 0.15

def stitchImage(img1, img2):

    # Detect ORB features and compute descriptors.
    orb = cv.ORB_create(MAX_FEATURES)
    kp1, des1 = orb.detectAndCompute(img1, None)
    kp2, des2 = orb.detectAndCompute(img2, None)

    # Match features.
    matcher = cv.DescriptorMatcher_create(cv.DESCRIPTOR_MATCHER_BRUTEFORCE_HAMMING)
    matches = matcher.match(des1, des2, 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 = cv.drawMatches(img1, kp1, img2, kp2, matches, None)
    cv.imwrite("matches.png", 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, :] = kp1[match.queryIdx].pt
        points2[i, :] = kp2[match.trainIdx].pt


    # 通过两个图像的特征点计算变换矩阵,获得变换矩阵和掩模
    (M, mask) = cv.findHomography(points1, points2, cv.RANSAC)

    # 对 img1 透视变换,M 是变换矩阵, 变换后的大小是 (img1.w + img2.w, img1.h)
    result = cv.warpPerspective(img1, M, (img1.shape[1] + img2.shape[1], img1.shape[0]))

    # 将img2的值赋给结果图像
    result[0:img2.shape[0], 0:img2.shape[1]] = img2

    return result


if __name__ == "__main__":
    
    img1 = cv.imread(r"F:\opencvTest\stitch_right.png")
    img2 = cv.imread(r"F:\opencvTest\stitch_left.png")
    
    # 顺时针旋转90度
    img1_90 = opencv_utils.rotateClockWise90(img1)
    img2_90 = opencv_utils.rotateClockWise90(img2)

    # 进行拼接
    stitched = stitchImage(img1_90, img2_90)

    # 结果图逆时针旋转90度
    stitched = opencv_utils.rotateAntiClockWise90(stitched)
    cv.imwrite('stitched.png', stitched)

    # 原图与结果图一起展示,易于对比
    result = opencv_utils.merge3Image(img1, img2, stitched)
    cv.imshow('result', result)
    cv.imwrite('result.png', result)

    cv.waitKey(0)
    cv.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
# opencv_utils.py
import cv2 as cv
import numpy as np

# 合并两张图片为一张图片
def merge2Image(src1, src2):
    if not src1.shape == src2.shape:
        print("图片的尺寸不相等")
        return
    y = src1.shape[0]
    x = src1.shape[1]
    res = np.zeros((y, x * 2, 3), dtype=src1.dtype)
    res[:, :x, :] = src1
    res[:, x:, :] = src2
    return res

# 合并三张图象为一张图像,第一张第二张上下合并,新图像再与第三张左右合并
def merge3Image(src1, src2, src3):
    if (not src1.shape == src2.shape) or (not src1.shape[0] + src2.shape[0] == src3.shape[0]):
        print("图片的尺寸不合适")
        return
    height = src1.shape[0] + src2.shape[0]
    width = src1.shape[1] + src3.shape[1]
    res = np.zeros((height, width, 3), dtype=src1.dtype)
    res[:src1.shape[0], :src1.shape[1], :] = src1
    res[src1.shape[0]:, :src2.shape[1], :] = src2
    res[:, src1.shape[1]:, :] = src3
    return res

# 顺时针旋转90度
def rotateClockWise90(img):
    trans_img = cv.transpose(img)
    new_img = cv.flip(trans_img, 1)
    return new_img

# 逆时针旋转90度
def rotateAntiClockWise90(img):
    trans_img = cv.transpose(img)
    new_img = cv.flip(trans_img, 0)
    return new_img
    
if __name__ == "__main__":
    src1 = cv.imread(r"F:\opencvTest\stitch_left.png")
    src2 = cv.imread(r"F:\opencvTest\stitch_right.png")
    res = merge2Image(src1, src2)
    cv.imshow("res", res)
    cv.imwrite("src_merge.png", res)
    cv.waitKey()
    cv.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

结果展示

在这里插入图片描述
如果您觉得这篇文章对您有帮助,欢迎为我的 github项目 点一个⭐

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/81316
推荐阅读
相关标签
  

闽ICP备14008679号