首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >图像拼接

图像拼接
EN

Stack Overflow用户
提问于 2019-05-05 22:13:16
回答 1查看 384关注 0票数 3

我录制了视频,而瓶子是rotated.Then,我从视频中获得帧,并从所有图像中切割中央块。

因此,对于所有的帧,我得到了以下图像:

我试过给他们缝制全景图,但结果很糟糕。我使用了以下程序:

代码语言:javascript
复制
import glob

#rom panorama import Panorama
import sys
import numpy
import imutils
import cv2


def readImages(imageString):
    images = []

    # Get images from arguments.
    for i in range(0, len(imageString)):
        img = cv2.imread(imageString[i])
        images.append(img)

    return images


def findAndDescribeFeatures(image):
    # Getting gray image
    grayImage = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # Find and describe the features.
    # Fast: sift = cv2.xfeatures2d.SURF_create()
    sift = cv2.xfeatures2d.SIFT_create()

    # Find interest points.
    keypoints = sift.detect(grayImage, None)

    # Computing features.
    keypoints, features = sift.compute(grayImage, keypoints)

    # Converting keypoints to numbers.
    keypoints = numpy.float32([kp.pt for kp in keypoints])

    return keypoints, features


def matchFeatures(featuresA, featuresB):
    # Slow: featureMatcher = cv2.DescriptorMatcher_create("BruteForce")
    featureMatcher = cv2.DescriptorMatcher_create("FlannBased")
    matches = featureMatcher.knnMatch(featuresA, featuresB, k=2)
    return matches


def generateHomography(allMatches, keypointsA, keypointsB, ratio, ransacRep):
    if not allMatches:
        return None
    matches = []

    for match in allMatches:
        # Lowe's ratio test
        if len(match) == 2 and (match[0].distance / match[1].distance) < ratio:
            matches.append(match[0])

    pointsA = numpy.float32([keypointsA[m.queryIdx] for m in matches])
    pointsB = numpy.float32([keypointsB[m.trainIdx] for m in matches])

    if len(pointsA) > 4:
        H, status = cv2.findHomography(pointsA, pointsB, cv2.RANSAC, ransacRep)
        return matches, H, status
    else:
        return None


paths = glob.glob("C:/Users/andre/Desktop/Panorama-master/frames/*.jpg")
images = readImages(paths[::-1])

while len(images) > 1:
    imgR = images.pop()
    imgL = images.pop()

    interestsR, featuresR = findAndDescribeFeatures(imgR)
    interestsL, featuresL = findAndDescribeFeatures(imgL)
    try:
        try:
            allMatches = matchFeatures(featuresR, featuresL)
            _, H, _ = generateHomography(allMatches, interestsR, interestsL, 0.75, 4.0)

            result = cv2.warpPerspective(imgR, H,
                                     (imgR.shape[1] + imgL.shape[1], imgR.shape[0]))
            result[0:imgL.shape[0], 0:imgL.shape[1]] = imgL
            images.append(result)
        except TypeError:
            pass
    except cv2.error:
        pass
result = imutils.resize(images[0], height=260)
cv2.imshow("Result", result)
cv2.imwrite("Result.jpg", result)

cv2.waitKey(0)

我的结果是:

也许是有人知道热辣才能做得更好?我认为从车架上用小块可以消除圆度.但是..。

数据:https://1drv.ms/f/s!ArcAdXhy6TxPho0FLKxyRCL-808Y9g

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-05-06 20:22:53

我设法取得了很好的成绩。我只是稍微重写了您的代码,下面是修改后的部分:

代码语言:javascript
复制
def generateTransformation(allMatches, keypointsA, keypointsB, ratio):
    if not allMatches:
        return None
    matches = []

    for match in allMatches:
        # Lowe's ratio test
        if len(match) == 2 and (match[0].distance / match[1].distance) < ratio:
            matches.append(match[0])

    pointsA = numpy.float32([keypointsA[m.queryIdx] for m in matches])
    pointsB = numpy.float32([keypointsB[m.trainIdx] for m in matches])

    if len(pointsA) > 2:
        transformation = cv2.estimateRigidTransform(pointsA, pointsB, True)
        if transformation is None or transformation.shape[1] < 1 or transformation.shape[0] < 1:
            return None
        return transformation
    else:
        return None


paths = glob.glob("a*.jpg")
images = readImages(paths[::-1])
result = images[0]

while len(images) > 1:
    imgR = images.pop()
    imgL = images.pop()

    interestsR, featuresR = findAndDescribeFeatures(imgR)
    interestsL, featuresL = findAndDescribeFeatures(imgL)
    allMatches = matchFeatures(featuresR, featuresL)

    transformation = generateTransformation(allMatches, interestsR, interestsL, 0.75)
    if transformation is None or transformation[0, 2] < 0:
        images.append(imgR)
        continue
    transformation[0, 0] = 1
    transformation[1, 1] = 1
    transformation[0, 1] = 0
    transformation[1, 0] = 0
    transformation[1, 2] = 0
    result = cv2.warpAffine(imgR, transformation, (imgR.shape[1] + 
                int(transformation[0, 2] + 1), imgR.shape[0]))
    result[:, :imgL.shape[1]] = imgL
    cv2.imshow("R", result)
    images.append(result)
    cv2.waitKey(1)

cv2.imshow("Result", result)

所以我改变的关键是图像的转换。我使用estimateRigidTransform()而不是findHomography()来计算图像的转换。从该转换矩阵中,我只提取x坐标转换,它位于生成的仿射变换矩阵 transformation[0, 2]单元格中。我将其他转换矩阵元素设置为恒等变换(没有缩放、没有透视图、没有旋转或y平移)。然后,我将它传递给warpAffine(),以像对待warpPerspective()那样转换imgR

你可以这样做,因为你有稳定的相机和旋转的物体位置,你用一个直视的物体捕捉。这意味着您不必进行任何透视图/缩放/旋转图像校正,只需通过x轴将它们“粘合”在一起。

我认为你的方法失败了,因为你实际上观察到瓶子有一个稍微向下倾斜的摄像头视图,或者瓶子不在屏幕的中间。我试着用图像来描述。我在瓶子上写了一些红色的文字。例如,该算法在捕获的圆形对象底部找到匹配点对(绿色)。注意,这个点不仅移动正确,而且对角也向上移动。然后,该程序计算转换,同时考虑到稍微向上移动的点。这种情况继续一帧一帧地恶化。

匹配图像点的识别也可能有点不准确,所以只提取x翻译会更好,因为您为算法提供了实际情况的线索。这使得它不太适用于另一种情况,但在您的情况下,它大大改善了结果。

另外,我还使用if transformation[0, 2] < 0检查筛选出一些不正确的结果(它只能旋转一个方向,如果这是负值的话,代码就不能工作)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55996873

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档