【问题标题】:Stitching computer images by feature without warping (no camera images)按特征拼接计算机图像而不变形(无相机图像)
【发布时间】:2022-08-11 04:18:12
【问题描述】:

我已经对 python 上的图像拼接进行了相当多的搜索,大多数都是针对全景图像,扭曲和旋转图像以将它们组合成一个。

我正在尝试做的是使用计算机图像,因此它们是数字的并且可以毫无问题地进行模板匹配,它始终是 2D 而无需变形。

基本上在这里我有一张放大的地图,我想为这些小图片制作一张大图,这里我们使用了所有图片:https://imgur.com/a/HZIeT3z

import os
import numpy as np
import cv2

def stitchImagesWithoutWarp(img1, img2):
    orb = cv2.ORB_create()
    kp1, des1 = orb.detectAndCompute(img1,None)
    kp2, des2 = orb.detectAndCompute(img2,None)
    bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
    matches = bf.match(des1,des2)
    matches = sorted(matches, key = lambda x:x.distance)
    good_matches = matches[:10]
    src_pts = np.float32([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1,1,2)
    dst_pts = np.float32([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1,1,2)

    start = (abs(int(dst_pts[0][0][0]-src_pts[0][0][0])), abs(int(dst_pts[0][0][1]-src_pts[0][0][1])))
    h1, w1 = img1.shape[:2]
    h2, w2 = img2.shape[:2]
    vis = np.zeros((start[1]+h1,start[0]+w1,3), np.uint8)
    vis[start[1]:start[1]+h1, start[0]:start[0]+w1, :3] = img1
    vis[:h2, :w2, :3] = img2
    return vis

imgList = []
for it in os.scandir(\"images\"):
    imgList.append(cv2.imread(it.path))

vis = stitchImagesWithoutWarp(imgList[0],imgList[1])
for index in range(2,len(imgList)):
    cv2.imshow(\"result\", vis)
    cv2.waitKey()
    vis = stitchImagesWithoutWarp(vis,imgList[index])

通过运行此代码,我可以成功地将前四个图像拼接在一起,例如:

但是一旦我缝合第五张图像,它似乎有错误的匹配并且不正确,但我总是在 NORM_HAMMING 上得到最佳的距离匹配,结果如下:

问题是,这是第一张图像,按此顺序,最佳匹配点(var开始) 在 x 轴上为负数,这里是 imgur 顺序中的匹配点:

  1. (7, 422)
  2. (786, 54)
  3. (394, 462)
  4. (-350, 383)

    我尝试切换顶部图像,为否定匹配执行特定代码,但我相信我正在偏离性能。

    还从码头注意到第一个图像应该是查询,第二个应该是目标,但我无法通过反转可见函数参数中的变量。

    标签: python opencv feature-detection


    【解决方案1】:

    这里的主要问题是当识别的点不在屏幕上时(负值),它需要调整偏移量,我还增加了一点代码并验证匹配是否合法,好像所有计算的位移都在在蛮力中平均匹配的第一选秀权。

    每个图像的平均大小为 2MB,没有预处理图像/缩小/压缩,在将 9 个图像拼接在一起后,我在我的 PC 中得到了 1050 毫秒的平均值,而对于其他测试的算法(扭曲图像)大约需要 2-3 秒拼接其中的 2 张图像。

    这是最终结果:

    import os
    import numpy as np
    import cv2
    
    def averageTuple(tupleList):
        avgX, avgY = 0,0
        for tuple in tupleList:
            avgX += tuple[0]
            avgY += tuple[1]
        return (int(avgX/len(tupleList)),int(avgY/len(tupleList)))
    
    def tupleInRange(t1, t2, dif=3):
        if t1[0] + dif > t2[0] and t1[0] - dif < t2[0]:
            if t1[1] + dif > t2[1] and t1[1] - dif < t2[1]:
                return True
        return False
    
    def rgbToRGBA(img):
        b_channel, g_channel, r_channel = cv2.split(img)
        alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 255
        return cv2.merge((b_channel, g_channel, r_channel, alpha_channel))
    
    def cropAlpha(img,extraRange=0.05):
        y, x = img[:, :, 3].nonzero()  # get the nonzero alpha coordinates
        minx = int(np.min(x)*(1-extraRange))
        miny = int(np.min(y)*(1-extraRange))
        maxx = int(np.max(x)*(1+extraRange))
        maxy = int(np.max(y)*(1+extraRange))
        return img[miny:maxy, minx:maxx]
    
    def stitchImagesWithoutWarp(img1, img2):
        if len(cv2.split(img1)) != 4:
            img1 = rgbToRGBA(img1)
        if len(cv2.split(img2)) != 4:
            img2 = rgbToRGBA(img2)
    
        orb = cv2.ORB_create()
        kp1, des1 = orb.detectAndCompute(img1,None)
        kp2, des2 = orb.detectAndCompute(img2,None)
        bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
        matches = bf.match(des1,des2)
        matches = sorted(matches, key = lambda x:x.distance)
        good_matches = matches[:10]
        src_pts = np.float32([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1,1,2)
        dst_pts = np.float32([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1,1,2)
    
        pointsList = []
        for index in range(0,len(src_pts)):
            curPoint = (int(dst_pts[index][0][0]-src_pts[index][0][0])), (int(dst_pts[index][0][1]-src_pts[index][0][1]))
            pointsList.append(curPoint)
    
        start = pointsList[0]
        avgTuple = averageTuple(pointsList)
        if not tupleInRange(start, avgTuple): return img1
    
        h1, w1 = img1.shape[:2]
        h2, w2 = img2.shape[:2]
        ax = abs(start[0])
        ay = abs(start[1])
        vis = np.zeros((ay+h1,ax+w1,4), np.uint8)
    
        ofst2 = (ax if start[0]<0 else 0, ay if start[1]<0 else 0)
        ofst1 = (0 if start[0]<0 else ax, 0 if start[1]<0 else ay)
        vis[ofst1[1]:ofst1[1]+h1, ofst1[0]:ofst1[0]+w1, :4] = img1
        vis[ofst2[1]:ofst2[1]+h2, ofst2[0]:ofst2[0]+w2, :4] = img2
        return cropAlpha(vis)
    
    imgList = []
    for it in os.scandir("images"):
        imgList.append(cv2.imread(it.path))
    
    vis = stitchImagesWithoutWarp(imgList[0],imgList[1])
    for index in range(2,len(imgList)):
        vis = stitchImagesWithoutWarp(vis,imgList[index])
    cv2.imwrite("output.png", cropAlpha(vis,0))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-03
      • 2016-04-14
      • 2016-09-11
      • 2012-03-27
      • 2018-10-28
      • 1970-01-01
      • 2012-09-28
      • 1970-01-01
      相关资源
      最近更新 更多