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

为何我的图像堆叠代码会导致结果出现色带与色彩溢出?

图像堆叠程序亮区异常问题排查

我用OpenCV编写了一个简单的图像堆叠程序,功能是对两张图像的相同像素取颜色平均值。代码在图像暗区表现正常,但亮区存在异常。测试时先用同一张图做验证,理论结果应与原图一致,但保存后的图像暗区无变化,亮区却变为其他颜色。此前怀疑是OpenCV的RGB与BGR转换问题,但已排除该可能,现寻求问题根源。

对比图像

  • 原图:original
  • 堆叠后图像:stacked image

所用代码

import cv2
import os
import numpy as np

np.seterr(over ="ignore") # 隐藏numpy错误

# 图像文件夹
folder = "sample/"

# 列出文件夹中所有图像
img_lst = [folder + i for i in os.listdir(folder)] 

# 获取图像的行和列数
img = cv2.imread(img_lst[0] , -1) 
print("processing image 1: " + img_lst[0], ", rows: " + str(img.shape[0]) + ", columns: " + str(img.shape[1]))

rows = img.shape[0]
columns = img.shape[1]

# 输出图像
final_img = np.asarray(img)
final_img.setflags(write=True)

# 堆叠处理
img_num = 1; row = 0; column = 0; color = 0

while img_num < len(img_lst): # 读取列表中所有图像

    img = np.asarray(cv2.imread(img_lst[img_num] , -1))
    print("processing image " + str(img_num + 1))
    
    # 遍历所有像素
    while row < rows:
        while column < columns:
            while color < 3:
                # 对颜色值取平均
                final_img[row][column][color] = int((final_img[row][column][color] + img[row][column][color])/2)
                color += 1
            
            color =0
            column += 1
        
        column = 0
        row += 1

    row = 0
    img_num += 1


print("finished...")              
cv2.imwrite(folder + "final.jpg", final_img) # 保存最终图像

问题根源

问题出在无符号整数溢出与截断:

  1. OpenCV读取JPG图像默认返回uint8类型数组,该类型数值范围为0-255。当亮区像素值(比如250)相加时,250+250=500,超出uint8的存储上限,会发生溢出截断(500 mod 256 = 244),再除以2得到122,与原像素值偏差极大,导致亮区变色。
  2. 暗区像素值小(比如50),相加后100未超出255范围,计算结果正常,因此暗区无异常。
  3. 你设置了np.seterr(over ="ignore"),直接隐藏了溢出错误提示,导致无法直观发现问题。

解决方案

处理前先将图像转换为高精度类型(如float32),计算完成后再转回uint8,同时用numpy向量运算替代低效的嵌套循环:

import cv2
import os
import numpy as np

# 图像文件夹
folder = "sample/"

# 列出文件夹中所有图像
img_lst = [folder + i for i in os.listdir(folder)] 

# 读取第一张图并转换为float32类型
final_img = cv2.imread(img_lst[0] , -1).astype(np.float32)
print(f"processing image 1: {img_lst[0]}, rows: {final_img.shape[0]}, columns: {final_img.shape[1]}")

# 堆叠处理
for img_num in range(1, len(img_lst)):
    img = cv2.imread(img_lst[img_num] , -1).astype(np.float32)
    print(f"processing image {img_num + 1}")
    # 向量运算替代嵌套循环,效率更高
    final_img = (final_img + img) / 2

# 转换回uint8类型并保存
final_img = final_img.astype(np.uint8)
print("finished...")              
cv2.imwrite(folder + "final.jpg", final_img)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 13:01:11