基于图像金字塔的图像合成代码异常求助:结果右侧不符
图像金字塔图像合成错误排查
基于图像金字塔(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
相关产品推荐
相关产品推荐

