如何快速生成指定行区间为1的0-1 Kernel?
高效生成指定行区间为1的0-1 Kernel
我需要生成一个由0和1组成的Kernel,现有一组高度对列表(例如[[191.0, 243.0], [578.0, 632.0]]),要求将Kernel中处于各高度对区间内的行全部设为1。目前采用双重循环实现,但执行耗时长达数分钟,求更高效的实现方式。
原实现代码
import numpy as np mascara = numpy.zeros((height, width), numpy.uint8) for i in range(height): for j in range(width): # 遍历Kernel的每个元素 indice_parejas = 0 while indice_parejas < numero_de_parejas: # indice_parejas:当前检查的高度对索引 # numero_de_parejas:高度对的总数 if i > vector_mascara[indice_parejas][0] and i < vector_mascara[indice_parejas][1]: # 判断当前行是否在某个高度对区间内 mascara[i][j] = 1 break # 找到匹配区间后退出循环,无需检查其他区间 else: indice_parejas = indice_parejas + 1
高效优化方案
原代码的问题在于嵌套了三层Python循环(行、列、高度对),Python循环本身效率极低,尤其是当height和width较大时,耗时会急剧增加。可以利用NumPy的向量化操作大幅提升效率,核心思路是先确定哪些行需要设为1,再一次性将整行赋值,避免逐元素操作。
方案1:向量化区间判断+广播赋值
import numpy as np # 将高度对列表转为NumPy数组(方便后续向量化操作) vector_mascara = np.array(vector_mascara) # 生成所有行的索引数组 rows = np.arange(height) # 提取所有区间的起始和结束值 starts = vector_mascara[:, 0] ends = vector_mascara[:, 1] # 利用广播判断每行是否属于任意一个区间,得到形状为(height,)的布尔掩码 row_mask = np.any((rows[:, np.newaxis] > starts) & (rows[:, np.newaxis] < ends), axis=1) # 将行掩码广播到width列,转为uint8类型的0-1数组 mascara = row_mask[:, np.newaxis].astype(np.uint8)
方案2:循环区间+逐行赋值(适合区间数量较少的场景)
如果高度对的数量不多,也可以直接循环每个区间,一次性给对应行赋值:
import numpy as np mascara = np.zeros((height, width), dtype=np.uint8) for start, end in vector_mascara: # 计算区间内的行索引范围(匹配原代码的i>start和i<end逻辑) start_row = int(np.floor(start) + 1) end_row = int(np.ceil(end) - 1) if start_row > end_row: continue # 一次性将指定行全部设为1 mascara[start_row:end_row+1, :] = 1
优化效果说明
- 原代码时间复杂度为
O(height * width * N)(N为高度对数量),优化后的方案时间复杂度降至O(height * N)或O(N),且所有核心操作由NumPy的底层C代码实现,执行速度比原代码快几个数量级,即使处理大尺寸Kernel也能在毫秒级完成。
内容的提问来源于stack exchange,提问作者Juan De Dios Herrera
相关产品推荐
相关产品推荐

