如何将图像numpy数组指定颜色通道值复制到二维列表?代码排错
提取图像单颜色通道像素值的问题排查与解决
问题描述
尝试提取图像中单个颜色通道的所有强度值并转移到二维数组testarray中,但运行代码后出现两个问题:
- 同一列(固定w值)的所有行(h值)数值完全相同
- 部分像素值与原图像不符(如原图像
image[600][450][1]为27,testarray对应位置为18)
原测试代码
#import packages import cv2 import numpy as np import matplotlib.pyplot as plt #reads image image = cv2.imread("nighttime.jpg", cv2.IMREAD_COLOR) #gets height and width vals from image h, w, c = image.shape #creates the array which will act as the copy testarray=[[0]*w]*h #loop to traverse through image and transfer each value of image to testarray for i in range(h): for j in range(w): testarray[i][j]=image[i][j][1] #[1] is used here in order to attain the pixel intensity value for green color channel print(image[600][450][1]) #value returned is 27 print(testarray[600][450]) #value returned is 18 (not equal to previous line's value)
问题原因
核心错误出在testarray的创建方式:
testarray=[[0]*w]*h
这种写法并没有创建h个独立的子列表,而是创建了h个指向同一个列表对象的引用。也就是说,所有行本质上是同一个列表的副本,当你修改testarray[i][j]时,所有行的第j列都会被同步修改。循环结束后,每一列的值都会被最后一行(i=h-1)的对应列值覆盖,这就是同一列数值相同、且像素值与原图像不符的原因。
解决方案
提供两种高效可行的解决方式:
方式1:正确创建独立的二维列表
使用列表推导式生成h个独立的子列表,避免引用复用:
#import packages import cv2 import numpy as np import matplotlib.pyplot as plt #reads image image = cv2.imread("nighttime.jpg", cv2.IMREAD_COLOR) #gets height and width vals from image h, w, c = image.shape # 用列表推导式创建独立的二维列表 testarray = [[0]*w for _ in range(h)] #loop to traverse through image and transfer each value of image to testarray for i in range(h): for j in range(w): testarray[i][j] = image[i][j][1] print(image[600][450][1]) # 输出27 print(testarray[600][450]) # 输出27,与原图像一致
方式2:利用Numpy直接提取通道(更高效)
由于cv2.imread返回的是Numpy数组,直接通过数组切片提取绿色通道,再转成列表即可,无需手动循环:
#import packages import cv2 import numpy as np import matplotlib.pyplot as plt #reads image image = cv2.imread("nighttime.jpg", cv2.IMREAD_COLOR) # 直接提取绿色通道(索引1)并转成二维列表 testarray = image[:, :, 1].tolist() print(image[600][450][1]) # 输出27 print(testarray[600][450]) # 输出27,与原图像一致
这种方法代码更简洁,执行效率远高于手动循环,尤其适合处理大尺寸图像。
内容的提问来源于stack exchange,提问作者BusyFang
相关产品推荐
相关产品推荐

