寻找错误的单应性

2024-10-01 00:32:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图用Python中的OpenCV做一个图像拼接项目,在这个项目中,我使用Lucas-Kanade算法跟踪视频帧之间的点匹配来找到单应矩阵。在编写了程序之后,到了拼接视频帧的时候,我决定运行一个测试,我只需在黑色画布上显示每个图像的透视扭曲版本,看看单应矩阵是如何扭曲它们的。当我这样做的时候,不是在帧之间一点一点地移动,而是将帧转换得越来越远,远离帧之间的轻微移动

[-------------------------------------------------------------------------------空白---------------------------------]

[框架0------------------------------------------------------------------------------------------------------------]

[------------框架1---------------------------------------------------------------------------------------------------]

[---------------------------------------------------框架2----------------------------------------------------------]

[--------------------------------------------------------------------------------------------------------框架3------------]

后续帧将超出可视范围。我不清楚为什么会发生这种事。我实施了反投影误差检查,以确保只有精确光流计算的点被传递。我还将findHomography的反投影阈值设置为10、1,然后设置为0.5,所有这些都无效。我正在拼接多个图像,所以我在帧之间乘以我的单应矩阵。这似乎加剧了错误。为什么会发生这种情况?我如何修复我的单应矩阵?这是我的代码(忽略注释掉的测试。另外,一些缩进格式可能在复制到论坛时被弄乱):

import numpy as np
import sys
import cv2
import math

lastFeatures = None
currentFeatures = None
opticFlow = None
panRow = None
Rows = None
finalPanorama = None

def loadRow(dirPath, fType, numImages,  column):
    imageRow = []
    for i in range(0, numImages):
            imageRow.append(cv2.imread("%s/%i_%i.%s" % (dirPath, column, i, fType), cv2.IMREAD_COLOR))
    return imageRow

def findNthFeatures(prevImg, prevPnts, nxtImg):

    back_threshold = 0.5

    nxtDescriptors = []
    prevGrey = None
    nxtGrey = None
    nxtPnts = prevPnts[:]

    prevGrey = cv2.cvtColor(prevImg, cv2.COLOR_BGR2GRAY)
    nxtGrey = cv2.cvtColor(nxtImg, cv2.COLOR_BGR2GRAY)

    lucasKanadeParams = dict(winSize = (19,19), maxLevel = 100, criteria = (cv2.TERM_CRITERIA_EPS |     cv2.TERM_CRITERIA_COUNT, 10, 0.03))

    nxtPnts, status, err = cv2.calcOpticalFlowPyrLK(prevGrey, nxtGrey, prevPnts, None, **lucasKanadeParams)
    backProjections, status, err = cv2.calcOpticalFlowPyrLK(nxtGrey, prevGrey, nxtPnts, None, **lucasKanadeParams)
    d = abs(prevPnts - backProjections).reshape(-1, 2).max(-1)
    status = d < back_threshold
    goodNew = nxtPnts[status].copy()
    goodLast = prevPnts[status].copy()

    return goodLast, goodNew

def getHomographies(videoName):
    color = np.random.randint(0,255,(100,3))    
    lastFrame = None
    currentFrame = None
    lastKeypoints = None
    currentKeypoints = None
    firstImage = True
    featureRefreshRate = 5

    feature_params = dict( maxCorners = 100,
                        qualityLevel = 0.1,
                        minDistance = 8,
                        blockSize = 15)

    frameCount = 0

    Homographies = []

    cv2.namedWindow('display', cv2.WINDOW_NORMAL) 
    cap = cv2.VideoCapture(videoName)
    flags, frame = cap.read()

    while flags:
    if firstImage:                                                
        firstImage = False
            lastFrame = frame[:,:].copy()
            lastGray = cv2.cvtColor(lastFrame, cv2.COLOR_BGR2GRAY)
        lastKeypoints = cv2.goodFeaturesToTrack(lastGray, mask = None, **feature_params)
            flags, frame = cap.read()
            frameCount += 1
        else:
            mask = np.zeros_like(lastFrame)           
            currentFrame = frame[:,:].copy()
            frameCount += 1

        lastKeypoints, currentKeypoints = findNthFeatures(lastFrame, lastKeypoints, currentFrame)
  #         for i,(new,old) in enumerate(zip(currentKeypoints, lastKeypoints)):
  #             a, b = new.ravel()
  #             c, d = old.ravel()
   #             mask = cv2.line(mask, (a,b), (c,d), color[i].tolist(), 2)
   #             frame = cv2.circle(frame, (a,b), 5, color[i].tolist(), -1)
   #         img = cv2.add(frame,mask)

#            cv2.imshow('display', img)
#            cv2.waitKey(0)
            homographyMatrix, homographyStatus = cv2.findHomography(currentKeypoints, lastKeypoints, cv2.RANSAC, 0.5)

            Homographies.append(homographyMatrix)   
        lastFrame = currentFrame
        lastKeypoints = currentKeypoints

            if frameCount % featureRefreshRate == 0:
                grayBuf = cv2.cvtColor(lastFrame, cv2.COLOR_BGR2GRAY)
                lastKeypoints = cv2.goodFeaturesToTrack(grayBuf, mask = None, **feature_params)

            flags, frame = cap.read()

    return Homographies

def stitchRow(videoName):

    cv2.namedWindow('display', cv2.WINDOW_NORMAL)

    frameCount = 0
    cap = cv2.VideoCapture(videoName)
    ret, initialImage = cap.read()
    homographyMatrices = []
    homographyMatrices = getHomographies(videoName)
    warpHMat = homographyMatrices[frameCount]

    while ret:
        ret, nextImg = cap.read()
        frameCount += 1
        result = cv2.warpPerspective(nextImg, warpHMat, (initialImage.shape[1] + nextImg.shape[1],   nextImg.shape[0]))
        #result[0:initialImage.shape[0], 0:initialImage.shape[1]] = initialImage
        cv2.imshow('display', result)
        cv2.waitKey(0)
#        cv2.imshow('display', initialImage)
#        cv2.waitKey(0)
        warpHMat = homographyMatrices[frameCount]

        for j in range(frameCount, 0, -1):
            warpHMat = warpHMat * homographyMatrices[j-1]

#        initialImage = result[:, :].copy()

stitchRow(sys.argv[1])

Tags: nonestatusmaskcv2framecolorcapcopy