图像均值化仅生成竖线的原因排查与代码问题分析
问题:计算图像像素均值的程序仅生成竖线
我尝试开发一个计算图像像素均值的程序,但运行后仅生成了竖线。以下是当前代码:
from typing import List import cv2 as cv import numpy as np def main(): # Importing two of the same imagae for debugigng purposes a = cv.imread("Datasets/OTIS/OTIS_PNG_Gray/Fixed Patterns/Pattern1/Pattern1_001.png", cv.IMREAD_GRAYSCALE) b = cv.imread("Datasets/OTIS/OTIS_PNG_Gray/Fixed Patterns/Pattern1/Pattern1_001.png", cv.IMREAD_GRAYSCALE) s = [a, b] avg = [[0] * len(a[0])] * len(a) print(f"rows: {len(a)} cols: {len(a[0])}") print(f"rows: {len(avg)} cols: {len(avg[0])}") for i in range(len(a)): for j in range(len(a[0])): # print(f"({i}, {j}): {temp_mean(s, i, j)}") avg[i][j] = temp_mean(s, i, j) / 255 avim = np.array(avg) print(f"rows: {len(avim)} cols: {len(avim[0])}") cv.imshow("title", avim) cv.waitKey(0) def temp_mean(seq: List[List[List[any]]], i: int, j: int): out = 0 for im in seq: out += im[i][j] return out / len(seq) if __name__ == '__main__': main()
原图:
生成图:
问题根源
- 列表初始化错误:
[[0] * len(a[0])] * len(a)会创建多个指向同一行列表的引用,修改任意一行的元素时,所有行的对应位置都会被同步修改,最终导致图像呈现竖线。 - 类型注解不匹配:
temp_mean函数的seq参数标注为List[List[List[any]]],但实际传入的是numpy数组列表,类型定义错误。 - 图像数据类型问题:计算后的
avim为float类型,直接传入cv.imshow可能存在显示异常,需确保数据类型符合要求。
修复后的代码
from typing import List import cv2 as cv import numpy as np def main(): # 导入两张相同图片用于调试 a = cv.imread("Datasets/OTIS/OTIS_PNG_Gray/Fixed Patterns/Pattern1/Pattern1_001.png", cv.IMREAD_GRAYSCALE) b = cv.imread("Datasets/OTIS/OTIS_PNG_Gray/Fixed Patterns/Pattern1/Pattern1_001.png", cv.IMREAD_GRAYSCALE) s = [a, b] # 正确初始化二维列表,避免引用重复 avg = [[0 for _ in range(len(a[0]))] for _ in range(len(a))] print(f"rows: {len(a)} cols: {len(a[0])}") print(f"rows: {len(avg)} cols: {len(avg[0])}") for i in range(len(a)): for j in range(len(a[0])): avg[i][j] = temp_mean(s, i, j) / 255 # 转换为float32类型,适配cv.imshow的显示要求 avim = np.array(avg, dtype=np.float32) print(f"rows: {len(avim)} cols: {len(avim[0])}") cv.imshow("title", avim) cv.waitKey(0) cv.destroyAllWindows() # 释放窗口资源 def temp_mean(seq: List[np.ndarray], i: int, j: int) -> float: out = 0.0 for im in seq: out += im[i][j] return out / len(seq) if __name__ == '__main__': main()
更高效的实现方式
利用numpy的广播特性可以省去手动遍历像素的步骤,大幅提升效率:
import cv2 as cv import numpy as np def main(): a = cv.imread("Datasets/OTIS/OTIS_PNG_Gray/Fixed Patterns/Pattern1/Pattern1_001.png", cv.IMREAD_GRAYSCALE) b = cv.imread("Datasets/OTIS/OTIS_PNG_Gray/Fixed Patterns/Pattern1/Pattern1_001.png", cv.IMREAD_GRAYSCALE) # 直接计算多张图片的均值 avg = np.mean([a, b], axis=0) / 255 # 转换为float32类型确保显示正常 avg = avg.astype(np.float32) cv.imshow("title", avg) cv.waitKey(0) cv.destroyAllWindows() if __name__ == '__main__': main()
内容的提问来源于stack exchange,提问作者A Stick
相关产品推荐
相关产品推荐

