以网格方式拼接图像时出现轻微错位问题

问题描述 投票:0回答:1

以网格方式将图像拼接在一起时出现轻微错位问题

我正在尝试创建地毯的高分辨率合成图像,所有部分都清晰可见。为此,我想到的最好方法是对地毯的不同部分拍摄几张照片,然后将它们缝合在一起。

我最初是使用 Photoshop API 来完成此操作,但最近(在过去 30 天内)Adobe 将 Photoshop API 捆绑到了 Firefly 中,目前仅适用于企业版。所以现在我正在尝试为此创建一个 OpenCV 函数。

我的原始图像是:-

从上到下(图5、3、1) 从上到下(图6、4、2)
5
图5
6
图6
3
图3
4
图4
1
图片 1
2
图 2

这些图像的高分辨率版本可在此处

获得

我尝试使用 Open CV 的缝合器类来执行此操作,甚至使用了多个参数,但它们似乎适用于某些图像集,而不是所有图像集。所以目前正在采用这种手动方法。

当前方法

我正在做成对缝合。 所以在第一次迭代中我会将行缝合在一起

1 与 2 缝合

3 与 4 缝合

5 与 6 缝合

结果还不错
1
第 1 行
2
第 2 行
3
第 3 行

我能够进行混合和曝光补偿以获得无缝结果,因此我们可以在这些测试图像中忽略它们。

下一步是将第 1 行与第 2 行缝合,得到结果,然后将这些结果与第 3 行缝合以获得最终的合成结果。结果是:-

最终结果
1 & 2
第 1 行和第 2 行
final
上面与第 3 行缝合

我没有裁剪图像以保持真实性,所以请原谅拼接图像中额外的白色部分。

问题

如果您查看最终图像,会发现地毯边缘有轻微的错位。这是我无法删除的。

我的代码是

import cv2
from loader import load_images
from stitcher import stitch_images_manual

def main():
    corrected_images_dir = "out"
    num_images = 6  # Adjust this to the number of images you have
    rows = 3  # Number of rows in your grid
    columns = 2  # Number of columns in your grid

    # Load images
    images = load_images(corrected_images_dir, num_images)
    if len(images) == 0:
        print("No images loaded.")
        return

    # Stitch images in pairs for each row
    row_images = []
    for i in range(rows):
        start_idx = i * columns
        pair = [images[start_idx], images[start_idx + 1]]
        print(f'Stitching row {i + 1} with images {start_idx + 1} and {start_idx + 2}')
        stitched_row = stitch_images_manual(pair[0], pair[1])
        if stitched_row is not None:
            row_images.append(stitched_row)
            cv2.imwrite(f'out/stitched_row_{i + 1}.png', stitched_row)
            print(f'Saved stitched row {i + 1} as stitched_row_{i + 1}.png')
        else:
            print(f'Stitching failed for row {i + 1}')
            return

if __name__ == "__main__":
    main()


import cv2
import numpy as np
from features import detect_and_compute_features
from homography import compute_homography
from warp import warp_image
from resize import resize_image
from camera_params import estimate_initial_camera_params, refine_camera_params

def stitch_images_manual(image1, image2, scale_percent=50):
    print(f"Stitching images of shapes: {image1.shape} and {image2.shape}")

    # # Resize images to medium resolution
    # image1_resized = resize_image(image1, scale_percent)
    # image2_resized = resize_image(image2, scale_percent)

    # Convert images to grayscale
    gray1 = cv2.cvtColor(image1, cv2.COLOR_BGRA2GRAY)
    gray2 = cv2.cvtColor(image2, cv2.COLOR_BGRA2GRAY)

    # Detect SIFT features and compute descriptors
    keypoints1, descriptors1 = detect_and_compute_features(gray1)
    keypoints2, descriptors2 = detect_and_compute_features(gray2)

    # Match features using FLANN matcher
    FLANN_INDEX_KDTREE = 1
    index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=10)
    search_params = dict(checks=500)
    flann = cv2.FlannBasedMatcher(index_params, search_params)
    matches = flann.knnMatch(descriptors1, descriptors2, k=2)

    # Apply ratio test
    good_matches = []
    for m, n in matches:
        if m.distance < 0.7 * n.distance:
            good_matches.append(m)

    if len(good_matches) < 4:
        print("Not enough good matches to compute homography.")
        return None

    # Extract location of good matches
    points1 = np.zeros((len(good_matches), 2), dtype=np.float32)
    points2 = np.zeros((len(good_matches), 2), dtype=np.float32)

    for i, match in enumerate(good_matches):
        points1[i, :] = keypoints1[match.queryIdx].pt
        points2[i, :] = keypoints2[match.trainIdx].pt

    # Compute homography
    h = compute_homography(points1, points2)

    if h is None:
        return None

    # Get dimensions of input images
    height1, width1 = image1.shape[:2]
    height2, width2 = image2.shape[:2]

    # Determine canvas size based on stitching direction
    if height1 > height2:
        canvas_width = max(width1, width2)
        canvas_height = height1 + height2
    else:
        canvas_width = width1 + width2
        canvas_height = max(height1, height2)

    # Warp the second image to the first image's plane
    warped_image2 = warp_image(image2, h, (canvas_width, canvas_height))

    # Create the stitched image canvas
    result = np.zeros((canvas_height, canvas_width, 4), dtype=np.uint8)
    result[0:height1, 0:width1] = image1

    # Create a mask of where the warped image has valid pixels
    mask = np.any(warped_image2 != 0, axis=2)

    # Paste the warped image pixels into the result image
    result[mask] = warped_image2[mask]

    return result

import cv2
import numpy as np

def warp_image(image, homography, canvas_size):
    warped_image = cv2.warpPerspective(image, homography, canvas_size)
    # cv2.imshow("warped",warped_image)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows
    return warped_image


import os
import cv2

def load_images(image_dir, num_images):
    images = []
    for i in range(1, num_images + 1):
        image_path = os.path.join(image_dir, f'{i}.png')
        if os.path.exists(image_path):
            img = cv2.imread(image_path, cv2.IMREAD_UNCHANGED)
            if img.shape[2] == 3:
                img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
            images.append(img)
            print(f'Loaded image {i} with shape {img.shape}')
        else:
            print(f'Image {image_path} not found.')
    return images


import cv2
import numpy as np

def compute_homography(points1, points2):
    h, mask = cv2.findHomography(points2, points1, cv2.RANSAC)
    if h is None:
        print("Homography computation failed.")

    return h

import cv2

def detect_and_compute_features(image):
    sift = cv2.SIFT_create()
    keypoints, descriptors = sift.detectAndCompute(image, None)
    return keypoints, descriptors

目前,我首先手动缝合行,然后旋转结果并通过更改行参数再次输入它们。这只是我的懒惰工作并且很容易解决,所以也请忽略它。

对于如何改善结果有什么想法吗?我尝试在删除背景后拼接图像,但即使这样也不起作用。

任何可以引导我走向正确方向的提示或指示将不胜感激。

我已经尝试了几个来自 github 的缝合包,但都给出了类似的未对齐结果。

python opencv computer-vision image-manipulation image-stitching
1个回答
0
投票

作为评论中讨论的总结:OpenCVs拼接模块支持至少两种获取图像的方式

全景(球体,无平移,透视)

panorama

平板扫描(平面、平移、无透视)

scans

您的用例不适合两者之一。然而,正如 Christoph Rackwitz 指出的那样:

如果地毯平放在地面上,则要纹理化的表面是 飞机。它不是一个球体。单应性适合组合 将地毯的图片融入到它的一大纹理中。

事实上,OpenCV 能够估计图像的单应性。

OpenCV 提供不同的单应性变形器(请参阅 stitching_detailed.pystitching 包)。使用

plane
整经机

可能会获得更好的结果
© www.soinside.com 2019 - 2024. All rights reserved.