ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

案例-使用python实现基于opencv的图像拼接(合并)

2022-02-04 11:33:02  阅读:265  来源: 互联网

标签:python cv2 transform opencv 拼接 np img2 img1 pts


这是使用python实现的第二个综合性的案例了,希望自己能够坚持下去,也希望能够帮到有需要的朋友们。
图像拼接的的主要原理呢就是使用特征点匹配。简单点说呢,就是两幅图像中会有相同的部分,我们就是根据图像中相同的特征,进行图像的拼接,有些也被称为合并。
具体来说分为四个步骤:

  1. 读取文件并重置尺寸。读取文件大家都理解,之所以要重置尺寸呢就是因为如果两张图像的尺寸不同(img1是360p,img2是720p)会造成后续操作的不便捷。具体代码如下:
import cv2
import numpy as np

#读取两张图片
img1 = cv2.imread("./img/airplane1.jpg")
img2 = cv2.imread("./img/airplane2.jpg")

if (img1 is None) or (img2 is None):
    print("路径问题")
else:
    img1 = cv2.resize(img1,(430,480))
    img2 = cv2.resize(img2,(430,480))
    #把数据压到栈中
    inputs = np.hstack((img1,img2))
    cv2.imshow('input img',inputs)
    cv2.waitKey()

结果如图所示:
在这里插入图片描述

  1. 根据特征点和计算描述子,得到单应矩阵
    这一步骤主要就是平时所学的特征点检测和匹配的基础知识的运用,具体的在代码中有详细的介绍,这里为了后期使用的方便,把获取单应性矩阵封装为一个函数,代码如下:
def get_homo(img1,img2):
    #创建特征转换对象
    sift = cv2.xfeatures2d.SIFT_create()
    #获取特征点和描述子
    k1,d1 = sift.detectAndCompute(img1,None)
    k2,d2 = sift.detectAndCompute(img2,None)
    #创建特征匹配器
    bf = cv2.BFMatcher()
    #使用描述子进行一对多的描述子匹配
    maches = bf.knnMatch(d1,d2,k=2)
    #筛选有效的特征描述子存入数组中
    verify_matches = []
    for m1,m2 in maches:
        if m1.distance <0.8*m2.distance:
            verify_matches.append(m1)
    #单应性矩阵需要最低四个特征描述子坐标点进行计算,判断数组中是否有足够,这里设为6更加充足
    if len(verify_matches) > 6:
        #存放求取单应性矩阵所需的img1和img2的特征描述子坐标点
        img1_pts = []
        img2_pts = []
        for m in verify_matches:
        #通过使用循环获取img1和img2图像优化后描述子所对应的特征点
            img1_pts.append(k1[m.queryIdx].pt)
            img2_pts.append(k2[m.trainIdx].pt)
        #得到的坐标是[(x1,y1),(x2,y2),....]
        #计算需要的坐标格式:[[x1,y1],[x2,y2],....]所以需要转化
        img1_pts = np.float(img1_pts).reshape(-1,1,2)
        img2_pts = np.float(img2_pts).reshape(-1,1,2)
        #计算单应性矩阵用来优化特征点
        H,mask = cv2.findHomography(img1_pts,img2_pts,cv2.RANSAC,5.0)
        return H
    else:
        print("error")

  1. 根据单应性矩阵对图像进行变换,然后平移
    4.图像拼接显示图像
    两个步封装到一个函数中,方便调用调试,重点是在变换过程中存在的平移需要使用齐次变换矩阵。
    代码如下:
def stitch_image(img1,img2,H):
    #1、获得每张图片的四个角点
    #2、对图片进行变换,(单应性矩阵使)
    #3、创建大图,将两张图拼接到一起
    #4、将结果输出
    #获取原始图的高、宽
    h1,w1 = img1.shape[:2]
    h2,w2 = img2.shape[:2]
    #获取四个点的坐标,变换数据类型便于计算
    img1_dims = np.float32([[0,0],[0,h1],[h1,w1],[w1,0]]).reshape(-1,1,2)
    img2_dims = np.float32([[0,0],[0,h2],[h2,w2],[w2,0]]).reshape(-1,1,2)
    #获取根据单应性矩阵透视变换后的图像四点坐标
    img1_transform = cv2.perspectiveTransform(img1_dims,H)
    #img2_transform = cv2.perspectiveTransform(img2_dims,H)

    #合并矩阵  获取最大x和最小x,最大y和最小y  根据最大最小计算合并后图像的大小;
    # #计算方式: 最大-最小
    result_dims = np.concatenate((img2_dims,img1_transform),axis = 0)

    #使用min获取横向最小坐标值,ravel将二维转换为一维,强转为int型,
    # 最小-0.5,最大+0.5防止四舍五入造成影响
    [x_min,y_min] = np.int32(result_dims.min(axis=0).ravel()-0.5)
    [x_max,y_max] = np.int32(result_dims.max(axis=0).ravel()+0.5)
    #平移距离
    transform_dist = [-x_min, -y_min]
    #齐次变换矩阵
    transform_arary = np.array([[1,0,transform_dist[0]],
                                [0,1,transform_dist[1]],
                                [0,0,1]])
    #输出图像的尺寸
    ww = x_max-x_min
    hh = y_max-y_min
    #透视变换实现平移
    result_img = cv2.warpPerspective(img1,transform_arary.dot(H),(ww,hh))
    #将img2添加进平移后的图像
    result_img[transform_dist[1]:transform_dist[1]+h2,
                transform_dist[0]:transform_dist[0]+w2] = img2
    return result_img

在最后分别调用两个函数,测试结果如下图:

    H = get_homo(img1,img2)
    result_img = stitch_image(img1,img2,H)

在这里插入图片描述
如果觉得文章还不错,请点赞支持,创作不易,转载请标注,谢谢

标签:python,cv2,transform,opencv,拼接,np,img2,img1,pts
来源: https://blog.csdn.net/qq_33392383/article/details/122748501

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有