资讯动态

选择性搜索:目标检测候选框生成原理与Python实现

发布时间:2026/10/15 15:07:40 来源:尧图企业网站定制
简介这份资源是选择性搜索Selective Search的Python入门示例面向计算机视觉初学者及目标检测方向的学习者帮助理解如何用超像素分割与区域生长策略生成候选目标区域从而替代传统滑动窗口的低效做法。压缩包共19个文件以12张png与2张jpg图像素材、3个Python脚本为主另含README说明与LICENSE协议整体约53KB体积轻便便于快速运行与调试。其中脚本按步骤拆分覆盖图像预处理、超像素分割、区域合并与候选框提取等环节配合示例图片可直接观察不同参数下的分割效果。目前已有285人学习下载适合作为理解R-CNN系列候选区域生成机制的练手材料也可为后续接入目标检测模型提供参考思路。1. 选择性搜索为什么目标检测的第一公里总在“猜框”如果你跑过目标检测的完整流程会发现一个反直觉的事实真正决定模型上限的往往不是分类网络有多深而是候选框提得够不够全。选择性搜索Selective Search解决的正是这个“第一公里”问题——它不依赖任何训练仅凭图像的颜色、纹理、尺寸和空间交叠度就能把一张图从几百个初始区域合并成两千个左右的候选框且召回率远高于滑动窗口。很多人第一次看到它时觉得不过是区域合并的玄学但当你亲手实现一遍就会明白它为什么能在深度学习之前统治检测领域十几年。这份资源用 Python 把选择性搜索拆成了可运行的简单示例没有黑匣子每一步合并逻辑都摆在代码里适合想搞懂“候选框到底怎么来的”的开发者。2. 从像素到区域选择性搜索的底层合并机制2.1 初始区域为什么不能直接拿像素当候选框一张 500×500 的彩色图像有 25 万个像素点如果每个像素都当作一个初始区域后续合并的计算量会直接爆炸。选择性搜索的第一步是用 Felzenszwalb 超像素分割把图像切成几百个小块这些小块内部颜色和纹理高度一致边缘贴合真实物体边界。这一步的本质是降维把 25 万个决策单元压缩到 500 到 2000 个超像素同时保留物体边界的完整性。常见的实现思路是调用 skimage 的 felzenszwalb 函数参数 scale 控制分割粒度sigma 控制高斯平滑核宽度min_size 过滤掉过小的碎块。scale 越大超像素越少、块越大sigma 越大边界越平滑但可能模糊掉细小结构。我一般会这么理解超像素分割是在“过分割”和“欠分割”之间找平衡过分割会让后续合并次数变多欠分割会让物体被切碎导致漏检。from skimage.segmentation import felzenszwalb from skimage.data import astronaut # scale100 控制分割粒度sigma0.5 控制平滑min_size50 过滤碎块 img astronaut() segments felzenszwalb(img, scale100, sigma0.5, min_size50) print(f超像素数量: {len(np.unique(segments))})这段代码输出的是每个像素所属的超像素标签图。scale 参数直接决定初始区域数量实践中 100 到 300 之间比较常见。min_size 设得太小会保留大量无意义碎块设得太大则可能把独立小物体合并进背景。注意 felzenszwalb 返回的是标签矩阵不是彩色分割图后续所有合并操作都基于这个标签矩阵进行。2.2 相似度计算颜色、纹理、尺寸、交叠的四维博弈选择性搜索的核心在于“合并谁”。它定义了四种相似度每种都从不同角度判断两个区域是否该合并。颜色相似度用 HSV 空间的 25 bin 直方图每个通道独立统计后取交集纹理相似度用 8 个方向的 Gabor 滤波器响应直方图同样 10 bin 量化尺寸相似度鼓励小区域优先合并防止大区域吞并小区域交叠相似度衡量两个区域边界框的重叠程度重叠越高越该合并。这四种相似度不是简单加权平均而是按顺序依次计算先颜色再纹理再尺寸最后交叠。每种相似度都归一化到 0 到 1 之间最终相似度是四者的加权和。常见的实现思路是给颜色和纹理较高权重尺寸和交叠较低权重因为前两者决定“看起来像不像”后两者只是辅助约束。import numpy as np def color_similarity(region1, region2, img_hsv, bins25): 计算两个区域在 HSV 空间的颜色直方图交集 hist1 np.histogram(img_hsv[region1], binsbins, range(0, 256))[0] hist2 np.histogram(img_hsv[region2], binsbins, range(0, 256))[0] # 归一化后取逐 bin 最小值求和 hist1 hist1 / hist1.sum() hist2 hist2 / hist2.sum() return np.sum(np.minimum(hist1, hist2)) def size_similarity(region1, region2, img_area): 小区域优先合并防止大区域吞并小区域 area1 np.sum(region1) area2 np.sum(region2) return 1.0 - (area1 area2) / img_area颜色相似度返回的是直方图交集值越大说明两个区域颜色分布越接近。size_similarity 的设计动机很关键如果没有它大区域会不断吞并小区域导致最终候选框全是整张图。交叠相似度则确保合并发生在空间上相邻的区域之间避免把图像左上角和右下角的区域强行合并。这四种相似度的组合顺序和权重是选择性搜索最需要调参的地方也是不同实现之间差异最大的地方。2.3 合并策略贪心算法如何保证候选框多样性有了相似度下一步是决定合并顺序。选择性搜索用的是贪心策略每次从所有相邻区域对中选出相似度最高的一对合并合并后更新该新区域与所有邻居的相似度重复直到整张图变成一个区域。这个过程会产生一个层次化的区域合并树每一层都对应一组候选框。关键在于选择性搜索不只输出最终合并结果而是把合并过程中每一层的所有区域都保留下来作为候选框。这样做的原因是不同物体在图像中的尺度不同有的物体在早期合并阶段就形成了完整区域有的物体要到后期才成型。如果只取最终结果小物体早就被合并进背景了。def selective_search(img, scale100, sigma0.5, min_size50): segments felzenszwalb(img, scalescale, sigmasigma, min_sizemin_size) regions {i: (segments i) for i in np.unique(segments)} candidates list(regions.values()) while len(regions) 1: # 计算所有相邻区域对的相似度 similarities [] for i in regions: for j in regions: if i j: continue sim compute_similarity(regions[i], regions[j], img) similarities.append((sim, i, j)) # 合并相似度最高的一对 similarities.sort(reverseTrue) _, i, j similarities[0] regions[i] regions[i] | regions[j] del regions[j] candidates.append(regions[i]) return candidates这段伪代码展示了合并的核心循环。每次合并后新区域与邻居的相似度需要重新计算因为颜色和纹理直方图变了。实际实现中会用并查集或邻接表来加速邻居查找否则每次遍历所有区域对的时间复杂度是 O(n²)。候选框数量通常控制在 2000 个左右太多会拖慢后续分类器太少会漏掉小物体。我一般会这么理解选择性搜索是在“召回率”和“计算量”之间做权衡2000 这个数字是大量实验后的经验值。3. 候选框排序与去重为什么两千个框里还有大量冗余3.1 非极大值抑制在候选框阶段的变体合并过程产生的候选框有大量重叠直接送给分类器会浪费算力。标准做法是用非极大值抑制NMS按区域大小或相似度排序后去重。但候选框阶段的 NMS 和检测后处理的 NMS 不同这里没有类别分数只能用区域面积或合并顺序作为排序依据。常见的实现思路是按面积从小到大排序保留小框因为小框更可能是独立物体大框往往是背景或物体组合。def nms_candidates(candidates, iou_threshold0.8): 按面积升序排列去除高度重叠的候选框 candidates sorted(candidates, keylambda r: np.sum(r)) keep [] while candidates: best candidates.pop(0) keep.append(best) candidates [r for r in candidates if iou(best, r) iou_threshold] return keepiou_threshold 设得越低保留的框越少但可能误删真实物体。实践中 0.7 到 0.8 之间比较常见。注意这里排序用的是面积升序不是降序因为小区域更可能是独立物体。如果按面积降序大背景框会先被保留然后删掉所有与它重叠的小物体框导致漏检。3.2 候选框数量与召回率的权衡曲线候选框数量不是越多越好。实验表明当候选框从 1000 增加到 2000 时召回率提升明显从 2000 增加到 5000 时召回率提升不到 2%但计算量翻倍。选择性搜索的论文里给出了这条曲线这也是为什么大多数实现默认输出 2000 个候选框。对于小物体密集的场景可以适当提高到 3000但需要配合更快的分类器。候选框数量召回率VOC 2007单图耗时CPU100092.1%0.8s200096.3%1.5s300097.1%2.3s500097.8%3.9s这张表是选择性搜索论文里的经典数据说明 2000 个候选框是性价比拐点。超过 3000 后召回率提升微乎其微但耗时线性增长。如果你的场景对召回率要求极高且算力充足可以上到 3000但一般不建议超过 5000。3.3 候选框质量评估召回率之外还要看什么召回率只衡量“真实物体是否被某个候选框覆盖”但不衡量候选框的定位精度。一个覆盖了物体但边界框很松的候选框和精确贴合物体边界的候选框召回率是一样的但后者对后续分类器更友好。评估候选框质量时除了召回率还要看平均最佳重叠度ABO和候选框的尺度分布。ABO 越高说明候选框越贴合真实物体边界尺度分布越均匀说明对不同大小物体的覆盖越均衡。常见的实现思路是统计候选框与真实框的最大 IoU 分布如果大量候选框的 IoU 集中在 0.5 到 0.7 之间说明定位精度一般如果集中在 0.7 以上说明候选框质量较高。选择性搜索的 ABO 通常在 0.6 到 0.7 之间不如后来的区域提议网络RPN但胜在无需训练、即插即用。4. 避坑与排查选择性搜索实现中的五个血泪教训4.1 超像素分割参数不当导致物体被切碎现象候选框召回率很低可视化后发现真实物体被切成了多个超像素合并过程始终无法把它们拼回完整物体。原因felzenszwalb 的 scale 参数设得太小导致过分割。scale 越小分割越细物体内部的一致性被破坏颜色和纹理相似度计算时反而认为这些碎块不相似。解决把 scale 从默认的 100 提高到 200 到 300同时适当增大 sigma 到 0.8 到 1.0让分割更粗糙但边界更完整。如果物体本身很小可以先用图像金字塔放大再分割。4.2 相似度权重失衡导致大区域吞并小区域现象候选框里全是整张图或大面积背景小物体完全消失。原因尺寸相似度权重设得太低或者根本没实现尺寸相似度。没有尺寸约束时大区域因为包含更多颜色和纹理与邻居的相似度反而更高导致贪心合并时大区域不断扩张。解决确保 size_similarity 返回的是“小区域优先”的分数即面积越小分数越高。权重上给尺寸相似度 0.2 到 0.3 的占比颜色和纹理各占 0.3 到 0.4交叠占 0.1 到 0.2。4.3 候选框去重时误删小物体现象NMS 之后候选框数量骤减小物体对应的框被删掉了。原因NMS 排序用了面积降序大背景框先被保留然后删掉了所有与它 IoU 超过阈值的小物体框。解决改成面积升序排序先保留小框。同时把 IoU 阈值从 0.5 提高到 0.7 到 0.8减少误删。如果小物体特别重要可以完全跳过 NMS直接把所有候选框送给分类器让分类器去判断。4.4 颜色空间选择错误导致相似度失真现象颜色相似度计算出来的结果与肉眼判断不符两个看起来颜色相近的区域相似度很低。原因直接在 RGB 空间计算直方图。RGB 三个通道高度相关且对光照变化敏感两个颜色相近但亮度不同的区域在 RGB 空间距离很远。解决转换到 HSV 或 Lab 空间再计算直方图。HSV 把色调、饱和度、明度分离对光照变化更鲁棒。Lab 空间则是感知均匀的颜色距离更符合人眼判断。实践中 HSV 用得最多因为计算简单且效果稳定。4.5 合并循环没有提前终止导致耗时过长现象单张图候选框生成耗时超过 5 秒无法满足实时性要求。原因合并循环一直跑到整张图变成一个区域但实际候选框在早期阶段就已经足够好了。后期合并产生的候选框都是大面积背景对检测没有帮助。解决设置最大合并次数或最小区域数量阈值比如当区域数量降到 50 以下时就停止合并。或者当新合并区域的面积超过图像面积的 50% 时停止。这样可以把耗时降低 30% 到 50%召回率损失不到 1%。5. 从选择性搜索到区域提议网络设计取舍与验证方法选择性搜索最值得玩味的地方是它用纯手工设计的相似度函数在没有训练数据的情况下达到了 96% 以上的召回率。这背后的设计取舍很清晰它不追求定位精度只追求“不漏”。颜色、纹理、尺寸、交叠四种相似度的组合本质上是在用多个弱线索投票任何一个线索失效时其他线索还能兜底。这种冗余设计让它在各种图像上都能稳定工作不像单一线索那样容易翻车。但它的代价也很明显贪心合并是串行过程无法并行化单张图耗时在 CPU 上要 1 到 2 秒。后来的区域提议网络RPN用卷积神经网络直接回归候选框把耗时降到了 10 毫秒级别同时 ABO 从 0.65 提升到 0.75 以上。RPN 的本质是用学习到的特征替代手工相似度用并行回归替代串行合并。但 RPN 需要大量标注数据训练而选择性搜索开箱即用。所以在数据稀缺或需要快速原型的场景选择性搜索仍然是合理选择。验证选择性搜索是否工作正常我一般会走三步第一步可视化超像素分割结果确认物体边界没有被切碎第二步统计候选框与真实框的最大 IoU 分布如果 80% 以上的真实框都能找到 IoU 大于 0.5 的候选框说明召回率合格第三步检查候选框的尺度分布如果小物体对应的候选框数量占比低于 10%说明尺寸相似度权重需要调高。这三步走完基本能定位 90% 的问题。从那以后我每次实现选择性搜索都会先把超像素分割结果画出来看一眼确认物体没被切碎再往下走。这个习惯帮我省掉了大量调试合并逻辑的时间。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑