
简介计算机视觉算法实战型PDF资料面向系统学习目标检测与行为识别技术的开发者、研究生及课程备课教师。内容围绕三条核心技术线展开一是选择性搜索用于物体定位介绍层次分组、不同颜色空间与区域相似度函数并给出帕斯卡重叠评分等实验指标二是视觉范围度量通过字袋分类证据反向投影分析刚性对象与非刚性对象在空间范围上的差异三是基于语言模型的动作/事件识别对比LDA-R与TypeDM两种模型在Pascal VOC2007数据集上的识别效果与适用场景。资源为单份PDF压缩包仅482KB轻量便携便于在通勤或碎片时间阅读也适合打印后对照算法公式与实验结论做笔记。已有527人学习浏览内容聚焦经典算法实际落地路径可作为算法选型参考、论文复现导读和计算机视觉课程辅助阅读资料。1. 计算机视觉算法实战候选框、词袋与语言模型三条线的拆解做计算机视觉项目实战的人现在多数是直接调 YOLO、跑现成检测库很少有人再回头啃区域提议和词袋这类经典算法。我拆完这份 PDF 反而想把它翻出来它对应的是计算机视觉算法实战里最容易被跳过的一段——选择性搜索Selective Search、词袋模型、语言模型辅助动作识别。这三个项目不涉及多深的神经网络却把“候选框怎么生成”“分类证据到底落在图像哪里”“视觉样本不够时怎么借语言”讲得很透。拿选择性搜索来说它在 4 秒内生成 2134 个候选框时平均最佳 Pascal 重叠Average Best Pascal OverlapABO就能到 0.804这个数字放到今天做 RPN 依然有参考意义。新手拿它补原理熟手拿它调参数、做评估都不会觉得浪费。2. 选择性搜索把滑窗换成候选框参数与 ABO 评估落地2.1 为什么滑窗不划算早期目标检测最常见做法是滑动窗口固定窗口大小和步长在整幅图上穷举位置然后对每个窗口做分类。问题在于尺度。一个勺子可以出现在沙拉碗里沙拉碗又在餐桌上图像天然是层次性的。穷举窗口要么设多种尺度要么把步长压到很小计算量立刻失控。选择性搜索的思路是“数据驱动”先用图像分割把像素分组再通过层次合并得到一组“有可能包含物体”的区域而不是在像素级穷举。这样既保留了图像本身的结构线索又不至于把每个位置都试一遍。PDF 里那句“图像本质上是层次性的需要所有尺度才能找到物体”其实就是选择性搜索存在的全部理由。2.2 层次分组颜色、纹理、大小、填充四类相似度选择性搜索的完整流程分三步先生成初始区域再计算相邻区域相似度最后按相似度从高到低迭代合并。合并时并不是单一指标而是四类相似度的加权组合。颜色相似度对每个区域做颜色直方图用直方图交集衡量接近程度。为了照顾不同光照和设备差异代码里通常会在多个颜色空间分别计算。纹理相似度用局部二值模式或 SIFT 描述子的直方图衡量纹理一致的区域更容易合并。大小相似度鼓励小区域先合并避免某个大区域吞掉周围所有碎片。优先让小区域合并目的是让分割结果在各个尺度上都有机会出现。填充相似度衡量两个区域合并后能否“填满”它们的包围盒。如果两个区域拼起来几乎成为一个完整矩形说明它们很可能是同一个对象的一部分。实际实现里四个相似度各占 0.25 是常见起点。这个权重不是写死的PDF 中“使用不同的分组策略并且各不相同”就是在说为了覆盖不同图像条件需要让分组策略有足够多样性而不是调一组完美参数走天下。2.3 一个可直接跑的 selectivesearch 样例复现选择性搜索不需要从头写层次合并Python 生态里有现成实现。我一般这样用import cv2 import selectivesearch # 读取图像并转 LAB 颜色空间 img cv2.imread(table.jpg) img_lab cv2.cvtColor(img, cv2.COLOR_BGR2LAB) # 生成候选区域 # scale: 控制分割精细度越大越容易生成大区域 # sigma: 高斯平滑系数越大区域边界越平滑 # min_size: 最小区域像素数过滤碎片 candidate_regions, _ selectivesearch.selective_search( img_lab, scale500, sigma0.9, min_size10 ) # 提取矩形框并去重 boxes [] for region in candidate_regions: rect region[rect] if rect not in boxes: boxes.append(rect) # 过滤过小的框 min_area 50 * 50 boxes [b for b in boxes if b[2] * b[3] min_area] print(候选框数量:, len(boxes))逻辑说明candidate_regions返回的是区域字典列表每个区域里有rect、labels、size等字段。rect的格式是(x, y, w, h)注意不是(x1, y1, x2, y2)。去重是必要的选择性搜索的多样化策略会产生大量重叠框完全相同的框直接丢弃能省不少后续分类时间。参数说明scale500是经验值图像分辨率高时可以上调到 800 甚至 1000。sigma控制分割的平滑程度太小区域边界碎太大容易把小目标并掉。min_size10指初始分割阶段小于 10 像素的区域会被合并这个值建议按数据集最小目标面积调整而不是固定不变。2.4 用 ABO 评估候选框质量候选框生成完下一步是回答“这些框到底好不好”。PDF 里给的关键指标是 ABO平均最佳 Pascal 重叠。它的计算逻辑是对每个真实目标框从所有候选框里找到与它重叠度最高的那个计算 Pascal 重叠分数最后对所有目标求平均。def pascal_overlap(box_a, box_b): # box: (x, y, w, h) x1 max(box_a[0], box_b[0]) y1 max(box_a[1], box_b[1]) x2 min(box_a[0] box_a[2], box_b[0] box_b[2]) y2 min(box_a[1] box_a[3], box_b[1] box_b[3]) inter max(0, x2 - x1) * max(0, y2 - y1) area_a box_a[2] * box_a[3] area_b box_b[2] * box_b[3] union area_a area_b - inter return inter / union if union 0 else 0 def average_best_overlap(proposals, gt_boxes): scores [] for gt in gt_boxes: best max(pascal_overlap(p, gt) for p in proposals) scores.append(best) return sum(scores) / len(scores)逻辑说明这里的proposals就是上一步生成的候选框列表gt_boxes是标注框列表。注意是“每个 GT 框挑一个最高重叠”而不是“每个候选框挑一个最高分数取平均”。两者含义差距很大前者衡量召回上限后者容易被大量重复框灌水。论文里 ABO 0.804 的含义是平均下来每个真实目标至少有一个候选框与它达到约 80% 的重叠。这个数值意味着后续用词袋模型做分类时定位误差不会成为主要瓶颈。提示如果 ABO 达不到预期优先检查min_size是否把目标整体切碎其次检查scale是否太大导致小目标被合并掉。跟分类精度无关先排查候选框。3. 词袋模型不是黑匣子分类证据反投影与视觉范围3.1 从 SIFT 到视觉单词词袋模型Bag of Words在图像领域的经典流程是提取局部特征、聚类成视觉单词、统计直方图、交给分类器。流程不复杂但它长期被当成黑匣子用——大家只知道输入图像输出类别却不知道分类器到底在看图像的哪一块。PDF 里针对猫那张热图说明了一个现象黄色区域代表强阳性证据蓝色代表强阴性证据灰色是中性。如果只用特征直方图做分类你根本说不清这些证据来自物体本身还是背景。正因如此作者才专门做了一个“把分类证据反向投影回图像”的项目。先看词袋模型的训练基础部分import cv2 import numpy as np from sklearn.cluster import KMeans # 提取所有训练图像的 SIFT 描述子 sift cv2.SIFT_create() descriptors [] for img_path in train_images: gray cv2.cvtColor(cv2.imread(img_path), cv2.COLOR_BGR2GRAY) kps, descs sift.detectAndCompute(gray, None) if descs is not None: descriptors.append(descs) all_descs np.vstack(descriptors) # 聚类成视觉单词 K 200 kmeans KMeans(n_clustersK, random_state0).fit(all_descs)逻辑说明SIFT 描述子对亮度、旋转有一定不变性适合做视觉单词的原料。KMeans聚成 200 个簇后每个特征点会被分配一个 0 到 199 的整数 ID这个 ID 就是视觉单词。K 的取值没有标准答案类别少、图像简单时 100 够用类别多、场景杂时往 400 上调。参数说明random_state0是为了可复现。SIFT 描述子是浮点向量直接喂 KMeans 没问题。如果换 ORB 或 BRIEF特征是二进制向量需要换聚类方式或者先转成浮点否则距离计算会出问题。3.2 把 SVM 权重反投影成热图训练好分类器之后关键是反投影。每个视觉单词在 SVM 里都有一个权重正权重表示“这个单词出现会增加目标类别的得分”负权重表示“它出现更倾向于背景”。反投影就是把每个特征点携带的权重放回它原来的像素位置。# 假设 svm_coef 是训练好的线性 SVM 每个视觉单词的权重 # kps 是测试图像的关键点descs 是对应描述子 heat np.zeros_like(gray, dtypenp.float32) for pt, desc in zip(kps, descs): word_id kmeans.predict(desc.reshape(1, -1))[0] x, y int(pt.pt[0]), int(pt.pt[1]) heat[y, x] svm_coef[word_id] # 高斯模糊让热图平滑 heat cv2.GaussianBlur(heat, (0, 0), sigmaX2.0)逻辑说明heat是一个与图像同尺寸的浮点矩阵每个像素累加它所在位置的视觉单词权重。最后用高斯模糊做平滑消除特征点稀疏带来的噪点。把heat用伪彩色叠加到原图上就能看到类似 PDF 里猫那张图的“强阳性证据 / 强阴性证据”分布。这里有个容易误读的地方热图不等于“注意力图”。它反映的是当前分类器对图像各区域的依赖程度而不是“目标应该在哪里”。如果一个分类器大量依赖背景纹理热图照样会指向背景而且分类分数可能还挺高。这就是词袋模型的“黑匣子”所在。3.3 场景上下文和对象边界的作用PDF 在这一节做了两个方向的实验结论都非常工程化。第一个方向是不给目标位置看分类证据来自图像哪些位置。结果发现环境上下文对分类有显著贡献尤其是船这一类物体区域本身的贡献甚至是负的。也就是说分类器很大程度上是靠“周围是水面、天空”来判断“这里有船”而不是靠船体本身。第二个方向是假设存在一个理想包围盒分别评估物体内部、边界、环绕区域的贡献。结论是有了理想定位之后环境的作用基本消失。“良好的目标定位能带来相当大的精度提升”这句话翻译成工程语言就是先保证候选框质量比花大力气优化分类器更划算。基于这些实验PDF 给出一个很实用的判断规则视觉范围由对象的类别决定。刚体对象比如瓶子、汽车的视觉范围就是对象本身非刚性对象比如人、动物的空间范围是无限的也就是远处上下文也能帮上忙按功能分类的对象比如“交通工具”这类抽象类别干脆把整张图作为空间范围。这对项目实战的直接启示是做目标检测数据增强时不要无脑对全图裁剪。刚体类可以放心裁到对象周边非刚性类和功能类保留更多上下文效果往往更好。这一点我在后面裁剪策略里还会提到。4. 动作与事件识别语言模型补足视觉样本的组合方法4.1 为什么动作和事件很难做全监督动作识别和事件识别有一个天然麻烦类别数量近乎无限。一个物体可以搭配大量动词比如“喂马”“骑马”“牵马”“拍马”每个动作又可以有修饰语印度婚礼和欧洲婚礼在视觉上完全不同。传统视觉识别要求每个类别都有大量人工标注样本这种标注成本在动作识别场景下根本撑不住。PDF 里提出的思路是换一个角度不直接识别动作而是先识别动作的组件。组件是物体动作是通过物体和动词的组合表达出来的。视觉模型负责“看到对象并定位”语言模型负责“这个对象通常会被怎样操作”。两部分组合起来就能识别没有标注过的动作组合。4.2 对象定位加语言模型的组合方式组合方案分两层。底层是对象定位PDF 用的是基于选择性搜索的字袋模型也对比了 Felzenszwalb 的基于部分模型结果字袋模型表现更好。上层是语言模型用来给每个对象预测合理动作。作者对比了 LDA-R 和 TypeDM 两种语言模型结论是 TypeDM 更优。这种组合的优势在“不可见事件”上体现得很明显视觉模型只需要知道“画面里有一只碗”语言模型就能给出“盛饭”“清洗”“端起来”这类合理动作。即使没有任何“洗碗”的视觉训练样本系统也能给出一个不算离谱的预测。对项目实战来说这就是在标注预算有限时用文本知识弥补视觉样本短缺的可行路径。4.3 用 VOC2007 做一份对象—动作关联PDF 里为 Pascal VOC2007 创建了人类行为标注对象类别限制在 20 类单个对象的动作频率是无偏的——这一点和大多数动作识别数据集不同后者通常追求每个类别样本量均衡结果反而扭曲了真实场景中的动作分布。下面这段代码是“对象—动词”统计的最小实现能帮你快速理解语言模型那部分在做什么from collections import defaultdict, Counter docs [ ride a horse, feed a horse, walk a dog, wash a car, drive a car, ] # 统计每个对象对应哪些动词 obj_verb defaultdict(Counter) for doc in docs: verb, obj doc.split(maxsplit1) obj_verb[obj][verb] 1 # 转成条件概率对象出现时各动词的概率 for obj, verb_counter in obj_verb.items(): total sum(verb_counter.values()) probs {v: c / total for v, c in verb_counter.items()} print(obj, probs)逻辑说明真实的语言模型比这段代码复杂得多LDA 这类主题模型会把语料中的“对象—动词”关系放到主题维度上做平滑TypeDM 则更进一步对条件分布建模。但核心逻辑就是这段代码做的事从文本知识中统计“某个对象更可能被施加哪些动作”再把统计结果接到视觉对象检测器后面。工程上的注意点对象—动词关联的语料来源决定了模型上限。拿通用语料统计出来的“horse”关联动词可能包含“race”“bet on”这些动作在 VOC 数据集里根本没有对应视觉样本。所以 PDF 特意强调数据是有偏设计限定在 20 个对象类别内但对每个对象发生的动作频率不做人为均衡。这样做的好处是评价结果更接近真实使用场景代价是类别不平衡问题要由模型自己扛。提示如果动作类别里包含大量低频组合先不要上复杂深度模型。用“对象检测器 条件概率表”跑一遍基线通常就能看出问题到底在视觉端还是文本端。5. 高频坑位排查候选框、词袋与语言模型的五个翻车点5.1 候选框与数据准备阶段的排查现象一选择性搜索跑得很慢一张 1080p 图像耗时十几秒完全达不到论文说的“4 秒 2134 个框”。原因scale和sigma配得不合适。scale太小会让初始分割区域非常碎后续合并步骤暴增sigma太大则让区域边界过度平滑合并顺序混乱。另外论文那组数字基于 VOC 数据集的小图不是 4K 大图。解决先把图像短边缩到 400 到 600 像素用scale500, sigma0.9, min_size10跑通流程再逐步提分辨率。如果每张图候选框超过 5000 个先查min_size是不是设得太小而不是直接怀疑库有问题。现象二ABO 分数一直上不去换了几组参数都卡在 0.5 左右。原因min_size太大导致小目标被合并进背景区域或者用多边形标注框直接和矩形候选框算 IoU结果被“空白角”拉低。VOC 这类检测数据集的 GT 本来就是矩形框但其他数据源不一定。解决先对每个 GT 框做面积统计按小目标面积反推min_size。如果标注是多边形先把标注转成外接矩形再算 ABO否则数值会系统性偏低。现象三候选框数量合适但大量框重叠在同一个对象上其他对象一个框都没有。原因层次分组策略不够多样只用了单一颜色空间导致某些对象的区域合并路径完全一致生成的框全挤在纹理最丰富的区域。解决换颜色空间或合并多种颜色空间的结果。RGB、HSV、Lab 各跑一遍把候选框合在一起。选择性搜索的“多样化”不是可选项是保证召回的基本手段。5.2 建模与评估阶段的排查现象四词袋反投影热图集中在背景上物体内部几乎没证据。原因这大概率不是 bug而是分类器真的在靠上下文分类。SIFT 特征在纹理丰富的背景区域更密集背景视觉单词在 SVM 里获得了更高权重。PDF 里“船的对象区域贡献为负”就是这个现象的极端案例。解决先不要急着调分类器用理想包围盒把图像裁出来重新看热图。如果裁掉背景后分数大幅下降说明分类器依赖上下文这在纯目标分类项目里是可以接受的如果业务方要求热图集中在物体上就得给分类器加边框约束或改用区域特征。现象五动作识别模型的效果跟“对象—动词”先验表差不多视觉部分好像没有贡献。原因对象检测器准确率太低传到语言模型的“对象框”大部分是背景语言模型只能退回到先验概率做预测。问题不在语言模型在视觉端。解决单独评估对象定位的 ABO 或检测精度。如果候选框质量差先回来调选择性搜索的scale和min_size不要在一个不可靠的视觉结果上叠加复杂的语言模型。6. 进阶验证先跑 ABO 再谈 mAP把视觉范围结论用到裁剪策略把这份 PDF 的项目拆完最值得带走的是两个习惯第一个是“先验候选框再谈分类”第二个是“类别决定视觉范围”。这两个结论放到现代检测流程里依然能用。我现在接到一个新检测任务第一步不是训练网络而是先跑一轮候选框 ABO 评估。对每个类别单独计算 ABO按类别排序看哪些类目的召回上限特别低。类别间 ABO 差距很大时通常是min_size和scale照顾了大目标、丢了小目标或者颜色空间策略对某些类不敏感。这一步能避免后面整个训练过程都在白费力气。候选框质量决定召回上限分类器再强也救不回没被生成的框。第二个习惯和裁剪策略有关。数据预处理阶段做随机裁剪时我会先给图像分类别刚体类按对象包围盒外扩一点做裁剪非刚性类和按功能定义的类保留更大范围的上下文。PDF 的实验已经说明非刚性对象的视觉范围是无限的所有尺度都能产生同样好的结果按功能分类的对象甚至会把整张图作为空间范围。如果对这些类别也做激进裁剪等于主动砍掉分类器赖以判断的上下文信息。从工程角度看这套旧算法项目最妙的还不是单点效果而是“先证明问题存在再设计对应方法”的推进方式。选择性搜索证明候选框可以用多样化分组快速生成词袋反投影又揭示了分类器对上下文的隐性依赖语言模型则提供了视觉样本不足时的补充通道。三件事连起来正好是一个检测系统从候选框、特征到知识的完整闭环。以后我每次拿新数据集做检测都会强制先走一遍 ABO 评估再看 mAP最后才敢说模型效果好坏。这个顺序帮我过滤了不少玄学也希望帮到你。本文还有配套的精品资源点击获取