图像拼接

2024-09-28 17:16:17 发布

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

我在酒瓶还在的时候录了录像旋转。然后我从视频中获取帧,并从所有图像中剪切中心块。你知道吗

enter image description here

因此,对于所有帧,我都得到了以下图像:
enter image description here

我试着把它们缝起来拍全景,但效果不好。 我使用了以下程序:

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)

我的结果是:
enter image description here

可能有人知道热做得更好?我认为使用小方块从框架应该消除圆度。。。但是。。。你知道吗

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


Tags: inimportnumpyforreturnmatchresultcv2
1条回答
网友
1楼 · 发布于 2024-09-28 17:16:17

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

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坐标变换,它位于结果Affine Transformation matrixtransformation[0, 2]单元中。我将其他变换矩阵元素设置为恒等变换(无缩放、无透视、无旋转或y平移)。然后我把它传递给warpAffine()来转换imgR,就像处理warpPerspective()一样。你知道吗

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

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

enter image description here

匹配图像点的识别也可能稍有不准确,因此仅提取x平移效果更好,因为您可以向算法“提示”您的实际情况。这使得它不太适用于其他条件,但在您的情况下,它会大大改善结果。你知道吗

另外,我用if transformation[0, 2] < 0检查过滤掉一些不正确的结果(它只能旋转一个方向,如果是负数,代码也不会工作)。你知道吗

相关问题 更多 >