python+opencv图像拼接

#目前在看七月的CV课,今天第二节,作业是实现图像拼接

  1. 使用SIFT特征点检测
  2. 使用FLANN进行特征点单应性匹配
  3. 计算第二张相对于第一张的仿射变换
  4. 使用公式(1-alpha)×原+alpha×仿进行拼接
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
if __name__ == '__main__':
    top, bot, left, right = 100, 100, 0, 500
    img1 = cv.imread('1.png')
    img2 = cv.imread('2.png')
    #扩充图像的边界,CONSTANT表示常量法,填充的边界由value参数给定
    srcImg = cv.copyMakeBorder(img1, top, bot, left, right, cv.BORDER_CONSTANT, value = (0,0,0))
    testImg = cv.copyMakeBorder(img2, top, bot, left, right, cv.BORDER_CONSTANT, value = (0,0,0))
    img1gray = cv.cvtColor(srcImg, cv.COLOR_BGR2GRAY)
    img2gray = cv.cvtColor(testImg, cv.COLOR_BGR2GRAY)
    sift = cv.xfeatures2d_SIFT().create()
    #找到关键点和描述子
    kp1, des1 = sift.detectAndCompute(img1gray, None)
    kp2, des2 = sift.detectAndCompute(img2gray, None)
    #FLANN单应性匹配, 单应性指的是图像在投影发生了畸变后仍然能够有较高的检测和匹配准确率
    #kdtree建立索引方式的常量参数
    FLANN_INDEX_KDTREE = 0
    index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
    search_params = dict(checks = 50)#chesks指定索引树要被遍历的次数
    flann = cv.FlannBasedMatcher(index_params, search_params)
    #进行匹配搜索
    matches = flann.knnMatch(des1, des2, k=2)
    # 寻找距离近的放入good列表
    good = []
    for m, n in matches:
        if m.distance < 0.7 * n.distance:
            good.append(m)
    MIN_MATCH_COUNT = 10
    # 如果足够多就进行匹配
    if len(good) > MIN_MATCH_COUNT:
        # 通过距离近的描述符 找到两幅图片的关键点
        src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
        dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
        # 单应性匹配图关键点匹配线
        M, mask = cv.findHomography(src_pts, dst_pts, cv.RANSAC, 5.0)
        matchesMask = mask.ravel().tolist()
        #仿射变换的图像
        warpImg = cv.warpPerspective(testImg, np.array(M), (testImg.shape[1], testImg.shape[0]), flags = cv.WARP_INVERSE_MAP)
        rows, cols = srcImg.shape[:2]
        for col in range(cols):
            if srcImg[:,col].any() and warpImg[:, col].any():
                left = col
                break
        for col in range(cols-1, 0, -1):
            if srcImg[:,col].any() and warpImg[:,col].any():
                right = col
                break
        res = np.zeros([rows,cols,3], np.uint8)
        for row in range(rows):
            for col in range(cols):
                if not srcImg[row, col].any():
                    res[row, col] = warpImg[row, col]
                elif not warpImg[row, col].any():
                    res[row,col] = srcImg[row, col]
                else:
                    srcImgLen = float(abs(col-left))
                    testImgLen = float(abs(col-right))
                    alpha = srcImgLen / (srcImgLen+testImgLen)
                    res[row, col] = np.clip(srcImg[row,col] * (1-alpha) + warpImg[row, col] * alpha, 0, 255)
        #opencv is bgr, matplotlib is rgb
        res = cv.cvtColor(res, cv.COLOR_BGR2RGB)
        plt.imshow(res)
    #否则不进行拼接
    else:
        matchesMask = None   

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值