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

基于图像金字塔的图像合成代码异常求助:结果右侧不符

图像金字塔图像合成错误排查

基于图像金字塔(Image Pyramid),使用指定掩码将两张输入图像合成为目标图像,但运行代码后生成的合成图像仅正确保留手部区域,右侧部分与预期结果不符,以下是排查出的代码错误及修正方案:

原始代码

import cv2
import numpy as np

# Read the input images and the mask
image1 = cv2.imread("figure2-assignment3.jpg")
image2 = cv2.imread("figure3-assignment3.jpg")
mask = cv2.imread("figure4-assignment3.jpg", cv2.IMREAD_GRAYSCALE)

# Smooth out the mask
mask = cv2.GaussianBlur(mask, (5, 5), 0)

# Convert mask to float32 and normalize to range [0, 1]
mask = mask.astype(np.float32) / 255.0

# Duplicate the mask to match the number of channels in the images
mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)

# Generate Gaussian pyramids for both images and the mask
gaussian_pyramid_image1 = [image1]
gaussian_pyramid_image2 = [image2]
gaussian_pyramid_mask = [mask]

for _ in range(6):  
    image1 = cv2.pyrDown(image1)
    gaussian_pyramid_image1.append(image1)

image2 = cv2.pyrDown(image2)
gaussian_pyramid_image2.append(image2)

mask = cv2.pyrDown(mask)
gaussian_pyramid_mask.append(mask)

# Generate Laplacian pyramids for both images
laplacian_pyramid_image1 = [gaussian_pyramid_image1[-1]]
laplacian_pyramid_image2 = [gaussian_pyramid_image2[-1]]

for i in range(5, 0, -1):  # Start from the second last level
   image1_up = cv2.pyrUp(gaussian_pyramid_image1[i])
   image2_up = cv2.pyrUp(gaussian_pyramid_image2[i])

image1_resized = cv2.resize(gaussian_pyramid_image1[i - 1], (image1_up.shape[1], image1_up.shape[0]))
image2_resized = cv2.resize(gaussian_pyramid_image2[i - 1], (image2_up.shape[1], image2_up.shape[0]))

laplacian_image1 = cv2.subtract(image1_resized, image1_up)
laplacian_image2 = cv2.subtract(image2_resized, image2_up)

laplacian_pyramid_image1.append(laplacian_image1)
laplacian_pyramid_image2.append(laplacian_image2)

# Generate Gaussian pyramid for the mask
gaussian_pyramid_mask = [gaussian_pyramid_mask[-1]]
# Start from the second last level
for i in range(5, 0, -1):  
    mask_up = cv2.pyrUp(gaussian_pyramid_mask[-1])
    mask_resized = cv2.resize(gaussian_pyramid_mask[-1], (mask_up.shape[1], mask_up.shape[0]))
    gaussian_pyramid_mask.append(mask_resized)

# Combine the corresponding levels of Laplacian pyramids using the mask
composite_pyramid = []
for img1, img2, msk in zip(laplacian_pyramid_image1, laplacian_pyramid_image2, gaussian_pyramid_mask):
    img1_resized = cv2.resize(img1, (msk.shape[1], msk.shape[0]))
    img2_resized = cv2.resize(img2, (msk.shape[1], msk.shape[0]))
    composite_level = img1_resized * msk + img2_resized * (1.0 - msk)
    composite_pyramid.append(composite_level)

# Collapse the composite pyramid to obtain the composite image
composite_image = composite_pyramid[-1]
for i in range(len(composite_pyramid) - 2, -1, -1):
   composite_image_up = cv2.pyrUp(composite_image)
   composite_image_resized = cv2.resize(composite_pyramid[i], (composite_image_up.shape[1], 
   composite_image_up.shape[0]))
   composite_image = cv2.add(composite_image_resized, composite_image_up)

# Save the composite image
cv2.imwrite("composite_image_2.jpg", composite_image)

错误分析

  • 高斯金字塔构建缩进错误:原代码中image2和mask的pyrDown操作不在for _ in range(6)循环内,导致仅执行一次,金字塔层数不足,无法完成多尺度合成。
  • 拉普拉斯金字塔生成缩进错误:for i in range(5, 0, -1)循环内的图像上采样、差值计算等语句未缩进,仅执行一次,生成的拉普拉斯金字塔层级数量错误。
  • 掩码金字塔被错误覆盖:原代码重新赋值gaussian_pyramid_mask = [gaussian_pyramid_mask[-1]],直接丢弃了之前正确生成的高斯掩码金字塔,后续生成的掩码层级完全错误。
  • 拉普拉斯计算冗余resize:cv2.pyrUp后的图像尺寸与上一层高斯金字塔的尺寸完全匹配,无需额外resize,resize操作会破坏金字塔的尺度对应关系,导致合成时的层级错位。
  • 合成时层级顺序不匹配:拉普拉斯金字塔和掩码金字塔的层级顺序未对齐,导致不同尺度的掩码与图像层级错误匹配。

修正后的代码

import cv2
import numpy as np

# 读取输入图像和掩码
image1 = cv2.imread("figure2-assignment3.jpg")
image2 = cv2.imread("figure3-assignment3.jpg")
mask = cv2.imread("figure4-assignment3.jpg", cv2.IMREAD_GRAYSCALE)

# 平滑掩码
mask = cv2.GaussianBlur(mask, (5, 5), 0)

# 转换为float32并归一化到[0,1]
mask = mask.astype(np.float32) / 255.0

# 扩展掩码通道数以匹配图像
mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)

# 生成高斯金字塔
num_levels = 6
gaussian_pyramid_image1 = [image1]
gaussian_pyramid_image2 = [image2]
gaussian_pyramid_mask = [mask]

for _ in range(num_levels):
    # 为image1生成下一层高斯金字塔
    img1_down = cv2.pyrDown(gaussian_pyramid_image1[-1])
    gaussian_pyramid_image1.append(img1_down)
    # 为image2生成下一层高斯金字塔
    img2_down = cv2.pyrDown(gaussian_pyramid_image2[-1])
    gaussian_pyramid_image2.append(img2_down)
    # 为mask生成下一层高斯金字塔
    mask_down = cv2.pyrDown(gaussian_pyramid_mask[-1])
    gaussian_pyramid_mask.append(mask_down)

# 生成拉普拉斯金字塔
laplacian_pyramid_image1 = [gaussian_pyramid_image1[-1]]
laplacian_pyramid_image2 = [gaussian_pyramid_image2[-1]]

for i in range(num_levels, 0, -1):
    # 上采样当前层高斯图像
    img1_up = cv2.pyrUp(gaussian_pyramid_image1[i])
    # 计算拉普拉斯层:上一层高斯图像 - 上采样后的当前层
    laplacian1 = cv2.subtract(gaussian_pyramid_image1[i-1], img1_up)
    laplacian_pyramid_image1.append(laplacian1)
    
    img2_up = cv2.pyrUp(gaussian_pyramid_image2[i])
    laplacian2 = cv2.subtract(gaussian_pyramid_image2[i-1], img2_up)
    laplacian_pyramid_image2.append(laplacian2)

# 反转掩码金字塔,使其与拉普拉斯金字塔层级顺序匹配
gaussian_pyramid_mask = gaussian_pyramid_mask[::-1]

# 合成各层级拉普拉斯金字塔
composite_pyramid = []
for img1_lap, img2_lap, msk in zip(laplacian_pyramid_image1, laplacian_pyramid_image2, gaussian_pyramid_mask):
    # 确保尺寸一致(理论上不需要,此处做冗余校验)
    if img1_lap.shape != msk.shape:
        img1_lap = cv2.resize(img1_lap, (msk.shape[1], msk.shape[0]))
        img2_lap = cv2.resize(img2_lap, (msk.shape[1], msk.shape[0]))
    composite_level = img1_lap * msk + img2_lap * (1.0 - msk)
    composite_pyramid.append(composite_level)

# 折叠合成金字塔得到最终图像
composite_image = composite_pyramid[0]
for i in range(1, len(composite_pyramid)):
    composite_image = cv2.pyrUp(composite_image)
    composite_image = cv2.add(composite_image, composite_pyramid[i])

# 保存结果
cv2.imwrite("composite_image_corrected.jpg", composite_image)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 05:43:11