多条件过滤图像像素的NumPy代码提速方案咨询
问题解答
示例写法的错误说明
你提供的逐次条件筛选代码无法正常运行,也达不到预期效果,核心问题有两个:
np.where返回的是满足条件的像素坐标元组(行索引数组、列索引数组),red[rule_1]提取到的是满足第一个条件的一维像素值数组,直接和二维的green通道比较会触发维度不匹配的广播错误,得到的结果完全不符合逻辑- 后续的
rule_2、rule_3是基于前一步筛选后的一维数组的索引,不是原图的坐标,直接给mask[rule_3]赋值会出现位置偏移、甚至索引越界的问题
逐次条件筛选思路可以实现提速
这种思路的核心是提前过滤掉不满足前置条件的像素,减少后续比较运算的计算量,如果第一个条件(red>100)能过滤掉大部分像素,提速效果会非常明显,正确的实现方式如下:
import cv2 import numpy as np image = cv2.imread("<some image path>") h, w, _ = image.shape mask = np.zeros((h, w), np.uint8) blue = image[:,:,0] green = image[:,:,1] red = image[:,:,2] # 逐层叠加条件,每次只对已经满足前面条件的像素做后续比较 mask_bool = red > 100 mask_bool[mask_bool] &= red[mask_bool] > green[mask_bool] mask_bool[mask_bool] &= red[mask_bool] > blue[mask_bool] mask[mask_bool] = 255
额外优化建议
- 原代码里
reduce(operator.and_, [条件1, 条件2, 条件3])的写法本身存在性能冗余,numpy布尔数组直接用&做与运算的效率远高于Python层面的reduce迭代,就算不用逐层筛选,直接写mask_bool = (red>100) & (red>green) & (red>blue)也比原写法快 - 不需要把原图转成
int16再做比较,uint8类型的像素值直接比较逻辑完全一致,能省掉一次数组复制和类型转换的开销
内容的提问来源于stack exchange,提问作者nOpe
相关产品推荐
相关产品推荐

