🧠 第二章 能力培养
📄 一句话概括

图像识别拆开只有两步:算一个可比较的数,再定一个阈值。 Demo 用模板相关加阈值,12 条合成样本全判对(TP 6、FP 0、FN 0、TN 6), 但这个 1.000 不能当「模型好」的证据——样本是自己造的。

📝 本节和前面几节的关系

前五节把环境、数学、代码、特征、数据都过了一遍。 这一节把它们串起来,做一件最小但完整的事:看图分类。

一、两步:打分,切一刀

图像识别的全部流程可以压成两步:把图变成一个可比较的分数,再用一个阈值决定它属于哪一类。 Demo 造了两类 8×8 的小图:车辆(横条加两个轮子)和行人(头身腿)。 给每类加高斯噪声造 12 条样本,然后用「相关系数」当分数——它衡量两张图的形状有多像, 取值在 -1 到 1 之间。 结果:车辆样本与车辆模板的相关在 0.79 到 0.98 之间,与行人模板在 0.05 到 0.17 之间。 差距足够大,所以一刀就分开。 准确率 1.000、精度/召回/F1 都是 1.000、混淆矩阵 TP 6、FP 0、FN 0、TN 6。

二、为什么这个 1.000 不算数

因为样本是我造的、噪声是我加的、模板也是我从样本里平均出来的。三件事都由我控制,结果当然好。 换成真实照片,模板匹配很快就不行:光照一变,像素值整体偏移,相关系数立刻掉;角度一变,形状对不上; 有遮挡,相关系数掉一半。 所以这一节的结论不是「模板匹配能用」,而是流程是这样:图 → 分数 → 阈值 → 判定。 深度学习的区别只在第一步:分数不再是人设计的模板,而是模型自己学出来的特征。 后面第八章的卷积网络讲的就是这件事。

三、相关系数为什么能当分数

相关系数先把两张图各自减去自己的均值,再算「同向变化的程度」。 减去均值这一步很关键:它让整体亮度不再影响结果。 所以一张偏亮的车辆图和一张偏暗的车辆图,相关系数依然很高; 而一张车辆图和一张行人图,无论亮度如何,相关系数都低。 这就是「特征」的含义:把跟任务无关的变化(亮度)消掉,把跟任务有关的变化(形状)留下。 上一节的特征工程,本质是同一件事。

四、动手 Demo:模板相关加一刀,12 条全判对

用 numpy 造两类 8×8 图案(车辆、行人),各加高斯噪声造 12 条样本,从前 6 条样本平均出两个模板, 再用相关系数给每条打分、取大者作为判定,最后算准确率与混淆矩阵。

def corr(a, b):
    a = a - a.mean(); b = b - b.mean()
    return float((a * b).sum() / (np.sqrt((a * a).sum() * (b * b).sum()) + 1e-9))

pred = [0 if corr(im, tpl[0]) > corr(im, tpl[1]) else 1 for im, _ in samples]

实跑输出:

--------------------------------------------------------------------
图像识别 = 特征 + 一刀切下去
--------------------------------------------------------------------
  样本   与车辆模板   与行人模板   判成   真值
  -------------------------------------------
  #01         0.945        0.021   车辆   车辆
  #02         0.128        0.867   行人   行人
  #03         0.952        0.041   车辆   车辆
  #04        -0.058        0.891   行人   行人
  #05         0.922        0.158   车辆   车辆
  #06         0.136        0.931   行人   行人
  #07         0.902        0.036   车辆   车辆
  #08         0.064        0.829   行人   行人
  #09         0.925        0.162   车辆   车辆
  #10         0.155        0.798   行人   行人
  #11         0.792        0.156   车辆   车辆
  #12         0.167        0.844   行人   行人

  准确率                   1.000
  精度 / 召回 / F1         1.000 / 1.000 / 1.000
  混淆矩阵                 TP 6、FP 0、FN 0、TN 6

  这里的「特征」就是模板本身,「模型」就是一个相关系数加大于号。
  模板是拿前 6 条样本平均出来的,不是真值;但合成图里两类差别够大,
  12 条一条没判错。这个 1.000 不能当「模型好」的证据——样本是自己造的。
  换成真实照片,模板匹配很快就撑不住:光照、角度、遮挡一变,相关系数就塌了。
  深度学习的区别只在第一步:模板不再是人画的,是学出来的。

12 行打分里,车辆样本与车辆模板都在 0.79 以上,与行人模板都在 0.17 以下, 中间空得很宽——所以这一刀怎么切都对。 准确率 1.000、F1 1.000、混淆矩阵 TP 6 / FP 0 / FN 0 / TN 6。 数字漂亮,但我在正文和输出里都写了:样本是造的,不能当证据。 模板是拿前 6 条样本平均出来的,不是「真值模板」。 这一步很关键——真实系统里你也没有真值模板,只能从样本估。 这两个类别的形状差得很远(横条 对 竖条),所以相关系数能分开。 如果两类形状接近(比如轿车对卡车),这个办法立刻就吃力了。

30 秒实验

  1. 把噪声标准差从 0.30 加到 0.60,看准确率掉到多少。
  2. 把模板换成「只用 1 条样本」,看结果抖不抖。
  3. 想一想:为什么「减去均值」这一步能消掉亮度的影响?

常见误区

  1. 「准确率 1.0 说明方法好」——样本是自己造的,模板也是自己估的。
  2. 「模板匹配过时了」——小样本、形状固定的场景里它又快又稳。
  3. 「图像识别很神秘」——拆开就是打分加阈值。
自测三问(点开对答案) 1. 图像识别的两步是什么? —— 把图变成可比较的分数,再用阈值判定。 2. 为什么这个 Demo 的 1.000 不能当证据? —— 样本、噪声、模板全由自己造,没有真实数据检验。 3. 相关系数为什么要先减均值? —— 让整体亮度不再影响结果,只比较形状。

基础能力六项讲完。下一节换个角度:这个岗位每天到底在干什么活。

相关笔记