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

- 堆叠后图像:

所用代码
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) # 保存最终图像
问题根源
问题出在无符号整数溢出与截断:
- OpenCV读取JPG图像默认返回
uint8类型数组,该类型数值范围为0-255。当亮区像素值(比如250)相加时,250+250=500,超出uint8的存储上限,会发生溢出截断(500 mod 256 = 244),再除以2得到122,与原像素值偏差极大,导致亮区变色。 - 暗区像素值小(比如50),相加后100未超出255范围,计算结果正常,因此暗区无异常。
- 你设置了
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
相关产品推荐
相关产品推荐

