如何快速在1000×1000×3的NumPy数组中查找10×10×3子数组?
高效检测小NumPy数组在大数组中的位置
方法1:NumPy滑动窗口向量化实现
利用numpy.lib.stride_tricks.sliding_window_view生成所有可能的窗口,批量完成比较,完全避免循环,充分利用NumPy的向量化运算优势。
import numpy as np from numpy.lib.stride_tricks import sliding_window_view # 假设big(1000×1000×3)和small(10×10×3)已定义 H, W, _ = big.shape h, w, _ = small.shape # 生成所有与small尺寸匹配的滑动窗口,形状为 (H-h+1, W-w+1, h, w, 3) windows = sliding_window_view(big, window_shape=(h, w, 3)) # 对每个窗口与small做全元素匹配,压缩最后三维的比较结果 matches = np.all(windows == small, axis=(2, 3, 4)) # 获取所有匹配位置的坐标 y_coords, x_coords = np.where(matches) # 输出匹配位置 for y, x in zip(y_coords, x_coords): print(y, x)
方法2:OpenCV模板匹配(最快方案)
OpenCV的matchTemplate底层经过高度优化,处理大尺寸3通道数组的速度远超纯NumPy实现,适合大规模数据场景。
import cv2 import numpy as np # 注意:若你的数组是RGB格式,而OpenCV默认处理BGR,需先转换:big = cv2.cvtColor(big, cv2.COLOR_RGB2BGR) result = cv2.matchTemplate(big, small, cv2.TM_CCOEFF_NORMED) # 完全匹配时,归一化相关系数接近1,设置高阈值过滤 threshold = 0.9999 locations = np.where(result >= threshold) # OpenCV返回的坐标是(x, y),对应原数组的(j, i),需转换顺序输出 for x, y in zip(*locations): print(y, x)
方法3:展平数组后批量比较
将窗口和小数组都展平为一维,通过计算平方差和来判断匹配,本质是方法1的变体,适合需要自定义匹配逻辑的场景。
import numpy as np from numpy.lib.stride_tricks import sliding_window_view H, W, _ = big.shape h, w, _ = small.shape # 将small展平为一维数组 small_flat = small.flatten() # 生成所有窗口并展平,形状为 ((H-h+1)*(W-w+1), h*w*3) windows_flat = sliding_window_view(big, (h, w, 3)).reshape(-1, h*w*3) # 计算每个窗口与small的平方差之和,值为0表示完全匹配 diff_sum = np.sum((windows_flat - small_flat)**2, axis=1) match_indices = np.where(diff_sum == 0)[0] # 将一维索引转换为二维坐标 y_coords = match_indices // (W - w + 1) x_coords = match_indices % (W - w + 1) for y, x in zip(y_coords, x_coords): print(y, x)
内容的提问来源于stack exchange,提问作者dljve
相关产品推荐
相关产品推荐

