一、从"分类"到"检测":还要知道"在哪"
"分类只回答'这张图是什么'。目标检测(Object Detection)要回答'图里有什么、在哪'——框出每个目标的位置。"老周画:
分类 vs 检测:
分类:[整张图] → "这是猫"
检测:[图] → "这里有一只猫(框A)、那里有一个人(框B)"
检测输出:
每个目标一个框(Bounding Box)+ 类别 + 置信度
框 = 中心点(x,y) + 宽高(w,h) 或 左上角+右下角
云间书店需求:
客流统计:检测"人"(person 类)→ 数框
货架识别:检测"书/商品"→ 统计数量
收银排队:检测人 + 跟踪(第十一章)
检测 vs 分类在流程上的差别:
分类:整图一个标签
检测:把图"切出"很多区域,每个区域判断是什么
→ 核心问题:怎么找"候选区域"?
"检测 = '在哪找' + '是什么'两步——难点在'在哪找':图里人可能出现在任何位置、任何大小。"
二、检测的两大流派:两阶段 vs 单阶段
"目标检测有两大技术路线。"老周说:
两阶段检测器(Two-stage):
第一阶段:先生成"候选区域"(可能是目标的框)
第二阶段:对候选区域分类 + 精修框
代表:R-CNN 系列 → Fast R-CNN → Faster R-CNN
特点:准确率高,但慢(两遍流程)
适合:精度优先(工业质检)
单阶段检测器(One-stage):
一个网络直接输出"框 + 类别"(一步到位)
代表:YOLO(You Only Look Once)、SSD
特点:快(实时),精度略低但已够用
适合:实时视频(客流统计、自动驾驶)
YOLO 为什么叫"只看一次":
传统方法要"滑窗/候选区域"多次看
YOLO 把整张图喂进网络,一次前向就出所有框
→ 速度快到能实时(30-100 FPS)
云间书店选 YOLO:实时客流统计,速度优先
"检测选型:要精度选 Faster R-CNN,要速度选 YOLO。 客流统计要实时 → YOLO 是标准答案。面试常问两者区别,这个要背熟。"
三、YOLO 的原理:一次前向,框都出来
"YOLO 的核心思想:把图像分成网格,每个格子负责预测'中心落在这个格子的目标'。"老周画:
YOLO 原理(简化):
① 把图分成 S×S 网格(如 7×7)
② 每个网格预测:
- 若干候选框(B 个)
- 每个框:中心偏移 + 宽高 + 置信度
- 每个框:各类别概率
③ 过滤:置信度低的丢掉
④ NMS:重叠的框合并(同一个物体只留一个)
┌───┬───┬───┬───┐
│ │ │ │ │ 人的中心在这个格子
├───┼───┼───┼───┤ → 这个格子负责"框出人"
│ │ □ │ │ │
├───┼───┼───┼───┤ □ = 预测的框
│ │ │ │ │
└───┴───┴───┴───┘
网格 + 多尺度(YOLOv3+):
在不同尺寸的特征图上检测(大目标/小目标都行)
→ 小目标检测能力大幅提升
"YOLO = 网格负责制——'每个格子管好自己的辖区'。一次前向,所有格子一起报,所以快。这是 YOLO 的核心直觉。"
四、NMS:重复的框怎么合并
"同一个目标可能被预测出好几个框,怎么只留一个?NMS(非极大值抑制)。"老周说:
NMS(Non-Maximum Suppression)非极大值抑制:
问题:一个人被框了 5 次(重叠的框)
目标:只留"最准"的那一个
流程:
① 按置信度排序,先留置信度最高的框
② 计算它和其余框的 IoU
③ IoU > 阈值(如 0.5)的框 = 重复 → 删掉
④ 对剩下的框重复 ①②③
IoU(Intersection over Union)交并比:
两个框重叠程度 = 交集面积 / 并集面积
0 = 不重叠,1 = 完全重合
IoU > 0.5 通常认为"是同一个目标"
为什么需要 NMS:
没有它,一个目标会输出一堆框(丑 + 重复计数)
客流统计会"一个人数成三个人"
"NMS 是检测的'去重机制'——没有 NMS,检测结果没法用。IoU 概念在后面评估指标(mAP)里也用到,必须吃透。"
五、用 YOLO 做客流统计:实战代码
"现在动手:用现成 YOLO 模型(Ultralytics YOLOv8)做客流统计。"老周写:
# 安装
pip install ultralytics
from ultralytics import YOLO
import cv2
# 1. 加载预训练模型(COCO 数据集,80 类含 person)
model = YOLO("yolov8n.pt") # n = 轻量版(快)
# 2. 图片检测
results = model("store_front.jpg")
# 3. 解析结果:框出"人"
img = cv2.imread("store_front.jpg")
for r in results:
for box in r.boxes:
x1, y1, x2, y2 = box.xyxy[0].tolist() # 框坐标
conf = box.conf[0].item() # 置信度
cls = int(box.cls[0].item()) # 类别
name = model.names[cls] # 类别名
if name == "person" and conf > 0.5: # 只数人
cv2.rectangle(img, (int(x1), int(y1)),
(int(x2), int(y2)), (0, 255, 0), 2)
cv2.putText(img, f"{name} {conf:.2f}",
(int(x1), int(y1)-5),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 1)
# 4. 统计
num_people = sum(
1 for r in results for b in r.boxes
if model.names[int(b.cls[0])] == "person" and b.conf[0] > 0.5)
print(f"识别到 {num_people} 人")
cv2.imshow("result", img)
cv2.waitKey(0)
用现成模型的流程:
下载预训练权重 → 推理 → 解析框 → 后处理
重点:解析 YOLO 输出(xyxy/conf/cls)+ 按业务过滤
完整客流统计(进阶,第十一章细讲):
视频逐帧检测 → 目标跟踪(同一人给同一ID)
→ 画"越线计数"(进门+1)→ 统计时段客流
"2023 年起,用 Ultralytics 一行代码就能跑 YOLO——训练、推理、导出都封装好了。工程上'会用现成模型'比'手写检测器'重要得多。"
六、评估指标:mAP 怎么算
"检测模型好不好,看 mAP(mean Average Precision)。"老周说:
mAP(平均精度均值):
检测评估核心指标
先看"一次预测对不对":
预测框 vs 真实框 IoU > 0.5(阈值)→ 算对(TP)
IoU 不够 → 算错(FP)
没预测到的真实目标 → 漏检(FN)
精确率(Precision):预测的框里,多少是对的?= TP/(TP+FP)
召回率(Recall):真实目标里,多少被找到了?= TP/(TP+FN)
二者权衡:阈值高 → 精确率高召回低;阈值低 → 反过来
AP:精确率-召回率曲线下的面积(一个类别一个 AP)
mAP:所有类别 AP 的平均
mAP@0.5:IoU 阈值 0.5 下的 mAP(常用)
mAP@0.5:0.95:多个 IoU 阈值的平均(COCO 标准)
怎么看:
mAP 越高越好(0-1)
云间书店场景:人检测 mAP@0.5 > 0.9 就很稳
"mAP 是检测的'体检报告'——面试必考、项目必用。记住:精确率管'准不准',召回率管'全不全',mAP 管'整体好不好'。"
七、章末:老周的第八章总结
第七层:目标检测
├── 任务:图里有什么 + 在哪(框+类别+置信度)
├── 两阶段:R-CNN 系(准,慢)/ 单阶段:YOLO(快,实时)
├── YOLO:网格负责制,一次前向出所有框
├── NMS:去重(IoU 交并比 > 0.5 = 同一目标)
├── 实战:Ultralytics YOLOv8 客流统计(数 person)
├── mAP:检测评估指标(精确率/召回率曲线面积)
└── 选型:实时视频用 YOLO(云间书店客流统计)
第九层(预告):图像分割 —— 把书架从背景里抠出来
"小陈,门口摄像头装上了——YOLO 把每个进门的人都框出来,客流数据唰唰地涨!"老周说,"但王姐看了监控又提新要求:'我想知道哪些区域人多,能不能把书架和人都分开显示?'——这就是图像分割:不只是框出人,而是把'每一块像素'分类。下一章,我们玩点更精细的。"