NumPy报错cannot copy sequence with size 2维度不匹配排查
报错原因
触发cannot copy sequence with size 2 to array axis with dimension 3的核心是赋值维度不匹配:
- 你的
fcp()函数最终返回长度为2的元组:(匹配到的调色板颜色列表pal, 颜色距离值ans) - 赋值目标
img_rgb[p]是长度为3的数组,对应图像单个像素的3个颜色通道
NumPy尝试将长度为2的序列写入长度为3的数组切片时,就会抛出该维度错误。
额外注意:OpenCV的cv2.imread()默认读取的图像通道顺序是BGR而非RGB,如果你要在RGB空间计算颜色距离,需要先调用cv2.cvtColor(img, cv2.COLOR_BGR2RGB)做通道转换,否则会出现颜色匹配偏差。
修复方案
最小修改版(保留原有循环逻辑)
只需要修改循环内的赋值逻辑,接收fcp()返回值时丢弃不需要的距离值,仅将颜色数组赋值给像素即可:
import math import cv2 import numpy as np palletes = [[255,85,85],[80,250,123],[255,184,108],[40,42,54],[68,71,90],[248,248,242],[98,114,164]] def fcp(pixel, palletes): ans = math.inf pal = [0,0,0] for pallete in palletes: result = math.sqrt(sum(list(map(lambda x,y: (x-y)**2, pixel, pallete)))) if result < ans: ans = result pal = pallete return pal, ans img = cv2.imread('wallpaper.png') # 若需要在RGB空间计算距离,取消下行注释 # img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img_rgb = img.reshape((img.shape[0]*img.shape[1],3)) for p, pixel in enumerate(img_rgb): # 仅取返回的颜色值,丢弃距离值 match_color, _ = fcp(list(pixel), palletes) img_rgb[p] = match_color img_rgb = img_rgb.reshape(img.shape[0],img.shape[1],3) # 如果之前做了BGR转RGB,保存前需要转回BGR # img_rgb = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2BGR) cv2.imwrite('wallpaper_new.png', img_rgb)
性能优化版(NumPy向量化,处理大图速度提升100倍以上)
原生Python逐像素循环处理高分辨率图像速度极慢,可以用NumPy广播机制批量计算所有像素到调色板的距离,避免显式循环:
import cv2 import numpy as np palletes = np.array([[255,85,85],[80,250,123],[255,184,108],[40,42,54],[68,71,90],[248,248,242],[98,114,164]], dtype=np.float32) img = cv2.imread('wallpaper.png') h, w = img.shape[:2] # 像素转float32避免计算溢出,拉平为(像素总数,3) pixels = img.reshape(-1, 3).astype(np.float32) # 广播计算每个像素到每个调色板颜色的距离:形状为(像素总数, 调色板数量) dist = np.sqrt(((pixels[:, None, :] - palletes[None, :, :])**2).sum(axis=2)) # 取每个像素距离最小的调色板索引 min_idx = dist.argmin(axis=1) # 映射为对应调色板颜色,转回uint8 new_pixels = palletes[min_idx].astype(np.uint8) # 恢复图像形状 new_img = new_pixels.reshape(h, w, 3) cv2.imwrite('wallpaper_new.png', new_img)
内容的提问来源于stack exchange,提问作者Dukk
相关产品推荐
相关产品推荐

