You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

网格状拼接地毯图像时的轻微错位问题及优化咨询

地毯高分辨率图像拼接优化方案求助

背景与当前方案

我需要制作全清晰的高分辨率地毯合成图像,方法是拍摄地毯不同部位的6张照片后拼接。原本使用Photoshop API,由于Adobe将其整合至仅企业可用的Firefly,转而基于OpenCV开发手动拼接方案。

原始图像按2列3行排列:左列从上到下为图像5、3、1,右列从上到下为图像6、4、2。

曾尝试OpenCV内置的Stitcher类,调整参数后仅部分图像能成功拼接,因此采用手动拼接流程:

  • 第一步:两两拼接同行图像(1与2、3与4、5与6),得到3张行拼接结果,效果尚可
  • 第二步:将行1与行2拼接,再将结果与行3拼接,最终图像的地毯边缘出现无法消除的轻微错位

现有代码实现

main.py

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()

stitcher.py

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

warp.py

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

loader.py

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

homography.py

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

features.py

import cv2

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

已尝试的无效方案

  • 手动旋转行拼接结果并重新拼接,效果无改善
  • 去除背景后拼接,效果不佳
  • 试用多个GitHub开源拼接工具,均出现类似错位问题

优化建议需求

针对地毯图像拼接的错位问题,寻求具体的技术优化方向或代码调整方案。


内容的提问来源于stack exchange,提问作者Karan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 01:22:05