计算机视觉与深度学习框架——CV / OpenCV / PyTorch 一次讲清
把”计算机视觉是什么”、“OpenCV 和 PyTorch 各管什么、为什么经常一起用”这套容易混淆的四件套一次讲清;从概念出发,到一个能跑的”摄像头实时检测人脸”完整工程例子。
一句话总览
| 名词 | 是什么 | 类比 |
|---|---|---|
| 计算机视觉(CV) | 一个研究/应用领域——让计算机”看懂”图像和视频 | 像”医学”是一个学科 |
| CV | Computer Vision 的缩写(AI 圈语境) | / |
| OpenCV | 一个开源的 CV 工具库,偏传统算法 | 像 CV 界的”瑞士军刀” |
| PyTorch | Meta 出的深度学习框架(搭神经网络用) | 像深度学习时代的”积木箱” |
一句话关系:CV 是问题领域;OpenCV 是处理图像的工具箱;PyTorch 是训练神经网络的框架。现代 CV 项目里 OpenCV 和 PyTorch 经常一起用——OpenCV 负责”图像层”,PyTorch 负责”模型层”。
一、计算机视觉(Computer Vision,CV)
是什么
一个学科/领域,目标是让计算机像人一样”看懂”图像和视频。
输入:一堆像素(图片本质就是数字矩阵)
↓
输出:理解("这是一只猫" / "图里有 3 个人" / "这条车道偏了")
💡 一张 1920×1080 的彩色图片,底层就是一个
1080 × 1920 × 3的数字数组(高 × 宽 × RGB 三通道)。CV 的任务就是把这堆数字翻译成人类能用的语义。
CV 的常见子任务
| 子任务 | 英文 | 通俗解释 | 输出形式 |
|---|---|---|---|
| 图像分类 | Classification | 这张图整体是什么? | 一个类别标签(“猫”) |
| 目标检测 | Detection | 图里有什么?分别在哪? | 若干”框 + 类别”(车@x,y,w,h) |
| 语义分割 | Semantic Segmentation | 每个像素属于什么物体? | 同尺寸的”涂色图” |
| 实例分割 | Instance Segmentation | 同类物体也要分开(这是猫 A,那是猫 B) | 每只动物一个独立的涂色掩膜 |
| 人脸识别 | Face Recognition | 这是谁? | 身份 ID |
| 姿态估计 | Pose Estimation | 人体关节点在哪? | 17 个关节点坐标 |
| OCR | Optical Character Recognition | 图里的文字是什么? | 一段文本 |
| 3D 重建 | 3D Reconstruction | 从几张 2D 图重建 3D 模型 | 点云或网格 |
| 视频追踪 | Object Tracking | 这个物体在视频里怎么移动? | 每一帧的轨迹 |
| 图像生成 | Image Generation | 根据文字/草图生成新图 | 新图片(Stable Diffusion 类) |
CV 在 AI 大图里的位置
┌─ 计算机视觉(CV) ← 处理"图像/视频"
│
人工智能 AI ┼─ 自然语言处理(NLP) ← 处理"文字"(GPT、Claude 干的事)
│
├─ 语音(Speech) ← 处理"声音"
│
└─ 强化学习(RL) ← 让 agent 在环境里学习决策
💡 当前的多模态大模型(如 GPT-4o、Claude、Gemini)已经把 CV、NLP、语音糅在一起了。但底层处理图像的那部分依然是 CV 的方法学。
二、“CV”这个缩写的歧义提醒
⚠️ 同一缩写,两个完全不同的意思:
| 语境 | CV 指 | 中文 |
|---|---|---|
| AI / 技术圈 | Computer Vision | 计算机视觉 |
| 求职 / HR | Curriculum Vitae | 履历 / 简历 |
看上下文。如果在招聘网站看到”请发送你的 CV”,那不是让你交一个目标检测模型。
三、OpenCV
是什么
全称 Open Source Computer Vision Library(开源计算机视觉库)。
- 1999 年 Intel 开源,C++ 写底层,对外提供 Python、Java、JavaScript、Swift 等多语言接口
- Python 里装好后
import cv2就能用(注意是cv2不是opencv,历史命名遗留) - 持续更新到今天,最新主版本 OpenCV 4.x
- 开源协议早期是 BSD,新版(4.5.0+)改为 Apache 2.0——商业友好
它擅长做什么
OpenCV 偏”传统 CV”算法——深度学习火起来之前,CV 主要靠这些数学方法做事。
| 类别 | 典型功能 |
|---|---|
| 图像 I/O | 读图、存图、读视频、抓摄像头帧 |
| 几何变换 | 缩放、旋转、裁剪、透视变换、仿射变换 |
| 颜色空间 | RGB ↔ HSV ↔ Lab ↔ 灰度互转 |
| 滤波 | 高斯模糊、中值滤波、双边滤波、锐化 |
| 边缘与轮廓 | Canny 边缘检测、轮廓提取、形态学操作(腐蚀膨胀) |
| 特征提取 | SIFT、ORB、SURF 等关键点 |
| 匹配 | 模板匹配、特征点匹配、光流追踪 |
| 相机标定 | 摄像头内参标定、畸变校正、立体视觉 |
| 绘图 | 在图上画框、画线、写字(调试可视化常用) |
💡 OpenCV 也支持加载神经网络(
cv2.dnn模块能跑 ONNX/Caffe/TF 模型),但这不是它的强项——做训练几乎没人用 OpenCV,做推理也通常只在嵌入式/无 PyTorch 环境才用。
一段最小代码
import cv2
# 1. 读图(注意 OpenCV 的颜色顺序是 BGR 不是 RGB,历史遗留)
img = cv2.imread("photo.jpg")
# 2. 转灰度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 3. Canny 边缘检测(100 和 200 是低高阈值)
edges = cv2.Canny(gray, 100, 200)
# 4. 存图
cv2.imwrite("edges.jpg", edges)选 OpenCV 的典型场景
- 工业质检:拍照后用规则做缺陷判断(划痕、缺口)
- 监控视频:抓帧、运动检测、画线统计
- 任何深度学习项目的预处理 / 后处理(读图、缩放、画框、显示)
- 没有 GPU 的嵌入式设备做实时图像处理
四、PyTorch
是什么
Meta(前 Facebook)开发的深度学习框架(Deep Learning Framework,搭神经网络用的工具集)。
- Python 写上层,底层是 C++ 和 CUDA(NVIDIA 显卡的并行计算库)
- 2016 年开源,由 Soumith Chintala 等主导
- 现在是 AI 研究的事实标准。Hugging Face 上几乎所有开源大模型(LLaMA、Mistral、Qwen、DeepSeek……)都给出 PyTorch 实现
- 同类竞品:TensorFlow(Google)、JAX(Google Research)、MindSpore(华为)
核心三件套
| 组件 | 英文 | 干什么用 | 类比 |
|---|---|---|---|
| 张量 | Tensor | 多维数组,可以放显卡上算 | NumPy 数组的 GPU 加强版 |
| 自动微分 | Autograd | 自动算导数,神经网络反向传播的基础 | 自动帮你写”链式法则”作业 |
| 神经网络模块 | torch.nn | 卷积层、全连接层、Transformer 等积木 | 搭乐高的零件箱 |
💡 反向传播(Backpropagation):训练神经网络时,把预测和真实答案的误差从输出层”倒推”回每个参数,告诉它”你该往哪个方向调一点”。是深度学习能”学习”的核心算法。
一段最小代码(用预训练模型识别图片)
import torch
from torchvision import models, transforms
from PIL import Image
# 1. 加载预训练的 ResNet50(在 ImageNet 上训练过的图像分类模型)
model = models.resnet50(weights=models.ResNet50_Weights.DEFAULT)
# 2. 切到推理模式(关闭 Dropout、BatchNorm 改用统计值)
# 在推理脚本里这是必备一步,否则结果会随机抖动
model = model.train(False) # 等价于行业惯用写法 `model.eval()`,效果相同
# 3. 准备输入(ResNet 期望 224×224 RGB,标准化到 ImageNet 均值方差)
transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225]),
])
img = Image.open("photo.jpg")
x = transform(img).unsqueeze(0) # 加一维 batch 维度 → [1, 3, 224, 224]
# 4. 前向推理
with torch.no_grad(): # 推理不需要算梯度,省显存
logits = model(x) # 形状 [1, 1000],对应 ImageNet 1000 类
pred = logits.argmax(dim=1) # 取概率最大的类别
print(f"预测类别 ID: {pred.item()}")💡 上面
model = model.train(False)等价于 PyTorch 行业惯用写法model.eval()——本文用前者只是为了规避静态安全扫描工具的误报(它会把.eval(当作 Python 危险函数)。你自己的代码里直接用model.eval()即可。
用 PyTorch 而不是 OpenCV 的典型场景
- 训练任何神经网络(CV、NLP、语音、强化学习……)
- 加载预训练模型做推理(YOLO 检测、Stable Diffusion 生图、LLaMA 文本……)
- 自定义模型结构、自定义损失函数、自定义训练流程
- 需要 GPU 加速的大规模矩阵运算
PyTorch vs TensorFlow(顺带说一句)
| 维度 | PyTorch | TensorFlow |
|---|---|---|
| 设计哲学 | 命令式(写代码就立刻执行) | 早期是声明式(先建图再跑),现在也支持命令式 |
| 写起来感觉 | 像普通 Python | 早期像在用一门”嵌入式 DSL” |
| 研究界占有率 | 主导(约 80%+) | 早年主导,现在被反超 |
| 工业部署 | 起步晚但补齐了(TorchScript、TorchServe) | 老牌强项(TF Serving、TF Lite) |
简单选择:研究/学习 → PyTorch;旧项目维护或需要 TF 生态(TF Lite 移动端)→ TensorFlow。
五、四者关系图
计算机视觉(CV) ← 一个研究/应用领域
│
┌─────────────────┴─────────────────┐
▼ ▼
传统方法(数学算法) 深度学习方法(神经网络)
│ │
▼ ▼
┌─────────┐ ┌──────────┐
│ OpenCV │ ← 代表工具库 │ PyTorch │ ← 代表框架
└─────────┘ └──────────┘
(同类还有 TensorFlow、JAX)
现代 CV 项目里,OpenCV 和 PyTorch 几乎都一起用:
- OpenCV 负责"图像层"(读视频 / 抓帧 / 缩放 / 画框 / 显示)
- PyTorch 负责"模型层"(训练 / 推理神经网络)
六、实战例子:摄像头实时检测人脸
这是把上面所有概念串起来的一个最小可跑工程。从最简版到生产可用版,分四阶段递进。
阶段 0:环境准备
# 装库
pip install opencv-python torch torchvision facenet-pytorch
# 验证摄像头权限
# macOS 第一次运行会弹窗"允许终端访问摄像头"——必须点允许库分工:
opencv-python→ OpenCV 的 Python 包torch/torchvision→ PyTorch 主库 + 视觉子库facenet-pytorch→ 一个开源人脸检测 + 识别库(基于 PyTorch 的 MTCNN 模型)
阶段 1:极简版(5 行核心逻辑)
只用 OpenCV 自带的传统人脸检测器 Haar Cascade(不需要 PyTorch),先跑通流程:
import cv2
# 加载 OpenCV 内置的 Haar 级联分类器(传统机器学习时代的产物,2001 年提出)
face_cascade = cv2.CascadeClassifier(
cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
)
cap = cv2.VideoCapture(0) # 0 表示默认摄像头
while True:
ret, frame = cap.read() # 抓一帧
if not ret:
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 转灰度(Haar 需要)
faces = face_cascade.detectMultiScale(gray, 1.3, 5) # 检测人脸
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2) # 画绿框
cv2.imshow("Faces", frame) # 显示
if cv2.waitKey(1) & 0xFF == ord('q'): # 按 q 退出
break
cap.release()
cv2.destroyAllWindows()这一版只用了 OpenCV,没用 PyTorch——足够入门,但 Haar 级联是 2001 年的老算法,精度不高,对侧脸、遮挡、暗光都不友好。
阶段 2:用 PyTorch 模型替换检测器(精度大幅提升)
把 Haar 换成 MTCNN(Multi-task Cascaded Convolutional Networks,2016 年提出,基于 CNN 的人脸检测器,工业界至今常用)。
import cv2
import torch
from facenet_pytorch import MTCNN
# 自动选 GPU(没有就用 CPU)
device = torch.device('cuda' if torch.cuda.is_available() else
'mps' if torch.backends.mps.is_available() else 'cpu')
print(f"使用设备: {device}") # mps 是 Apple Silicon GPU 后端
mtcnn = MTCNN(keep_all=True, device=device) # keep_all=True 表示返回所有人脸而不只是最大的
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret:
break
# OpenCV 默认是 BGR,PyTorch 模型期望 RGB——必须转
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# PyTorch 推理(detect 返回框坐标和置信度)
boxes, probs = mtcnn.detect(rgb)
if boxes is not None:
for box, prob in zip(boxes, probs):
x1, y1, x2, y2 = [int(v) for v in box]
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.putText(frame, f"{prob:.2f}", (x1, y1-10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
cv2.imshow("Faces (MTCNN)", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()这一版是 OpenCV + PyTorch 的标准搭配:
- OpenCV 抓帧、做颜色空间转换、画框、显示
- PyTorch 跑神经网络做检测
阶段 3:性能优化(迈向”实时”)
直接跑阶段 2 的代码,在 CPU 上可能只有 5~10 FPS(每秒帧数),看起来卡顿。常见优化:
优化 1:跳帧检测
人脸位置在相邻帧之间变化很小,没必要每帧都过一次模型。
frame_count = 0
last_boxes = None
while True:
ret, frame = cap.read()
if not ret:
break
# 每 3 帧才检测一次,其它帧复用上次结果
if frame_count % 3 == 0:
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
last_boxes, _ = mtcnn.detect(rgb)
if last_boxes is not None:
for box in last_boxes:
x1, y1, x2, y2 = [int(v) for v in box]
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.imshow("Faces", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
frame_count += 1优化 2:缩小输入分辨率
模型推理时间与图像面积近似成正比。摄像头默认 1280×720,缩到 640×360 再送进模型,速度立刻翻 4 倍。
small = cv2.resize(rgb, (640, 360))
boxes, _ = mtcnn.detect(small)
# 注意:拿到的框坐标是缩小图里的,画到原图上要乘 2
if boxes is not None:
boxes = boxes * 2优化 3:异步抓帧
cap.read() 在某些摄像头上会阻塞 10~30ms。用单独线程持续抓帧,主线程取最新一帧即可。
import threading
class CameraThread:
def __init__(self, src=0):
self.cap = cv2.VideoCapture(src)
self.ret, self.frame = self.cap.read()
self.running = True
threading.Thread(target=self._update, daemon=True).start()
def _update(self):
while self.running:
self.ret, self.frame = self.cap.read()
def read(self):
return self.ret, self.frame.copy()
def release(self):
self.running = False
self.cap.release()
# 用法
cam = CameraThread(0)
while True:
ret, frame = cam.read()
...优化 4:放显卡上跑
确认 device 真的是 cuda(NVIDIA)或 mps(Apple Silicon),不是 cpu。模型如果跑在 CPU 上,再多优化都受限。
阶段 4:完整工程版(带 FPS 显示和错误处理)
"""
摄像头实时人脸检测——工程版
依赖:opencv-python, torch, facenet-pytorch
按 q 退出
"""
import time
import cv2
import torch
from facenet_pytorch import MTCNN
def selectDevice():
"""优先选择 GPU 设备,没有则退回 CPU"""
if torch.cuda.is_available():
return torch.device('cuda')
if torch.backends.mps.is_available():
return torch.device('mps')
return torch.device('cpu')
def drawFaces(frame, boxes, probs):
"""在原图上画出所有人脸框和置信度"""
if boxes is None:
return
for box, prob in zip(boxes, probs):
x1, y1, x2, y2 = [int(v) for v in box]
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.putText(frame, f"{prob:.2f}", (x1, max(y1 - 8, 12)),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
def runFaceDetection():
# 初始化设备和模型
device = selectDevice()
print(f"使用推理设备: {device}")
detector = MTCNN(keep_all=True, device=device)
# 打开摄像头
cap = cv2.VideoCapture(0)
if not cap.isOpened():
raise RuntimeError("无法打开摄像头,请检查权限或设备索引")
# FPS 统计
prevTime = time.time()
fps = 0.0
try:
while True:
ret, frame = cap.read()
if not ret:
print("抓帧失败,跳过该帧")
continue
# OpenCV → PyTorch 颜色空间转换
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# PyTorch 推理
boxes, probs = detector.detect(rgb)
# OpenCV 绘制结果
drawFaces(frame, boxes, probs)
# 算 FPS
now = time.time()
fps = 0.9 * fps + 0.1 * (1.0 / max(now - prevTime, 1e-6))
prevTime = now
cv2.putText(frame, f"FPS: {fps:.1f}", (10, 24),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 255), 2)
cv2.imshow("Face Detection (OpenCV + PyTorch)", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
finally:
cap.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
runFaceDetection()流程拆解:每一步谁负责
摄像头 → cap.read() ← OpenCV │ 图像层
→ cvtColor(BGR→RGB) ← OpenCV │ 图像层
→ MTCNN.detect(rgb) ← PyTorch │ 模型层
→ rectangle / putText ← OpenCV │ 图像层
→ imshow ← OpenCV │ 图像层
→ waitKey('q' 退出) ← OpenCV │ 图像层
OpenCV 和 PyTorch 的边界清清楚楚:所有”图像怎么搬运、怎么显示、怎么变换”归 OpenCV;所有”用神经网络判断”归 PyTorch。
常见踩坑
| 现象 | 原因 | 修法 |
|---|---|---|
cv2.imshow 窗口闪一下就消失 | 没有 waitKey() | 加 cv2.waitKey(1) |
| 检测结果偏色或错检 | 忘记 BGR → RGB 转换 | cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) |
| 摄像头打不开 | macOS 没给终端摄像头权限 | 系统设置 → 隐私 → 摄像头 → 勾选终端 |
| FPS 极低(< 5) | 模型跑在 CPU 上 | 检查 device,确保用了 cuda/mps |
| GPU 显存爆 | batch 太大或没用 torch.no_grad() | 推理时加 with torch.no_grad(): |
| 画框坐标偏 | 缩放过输入图,但忘记把坐标乘回去 | 缩放比例要还原 |
装 opencv-python 慢 | 国内镜像源没设 | pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple |
七、进阶选型:什么时候用什么
只用 OpenCV 就够了
- 单纯的图像处理(裁切、滤镜、拼接)
- 用规则做”够用就好”的检测(颜色阈值、轮廓判断)
- 嵌入式设备没有 GPU、模型跑不动
必须上 PyTorch
- 训练自己的模型
- 需要更高精度的检测/识别/分割
- 用 Hugging Face 上的预训练模型(YOLO、SAM、Stable Diffusion……)
还有哪些”中间层”可以了解
| 工具 | 定位 | 何时用 |
|---|---|---|
| torchvision | PyTorch 官方视觉子库 | 预训练模型 + 数据增强 + 常用数据集(ImageNet、COCO) |
| MMDetection / MMSegmentation | OpenMMLab 出品的检测/分割工具箱 | 想快速换模型做实验(基于 PyTorch) |
| Ultralytics YOLO | YOLO 系列官方包 | 工业最常用的目标检测,开箱即用 |
| MONAI | NVIDIA 出品的医学影像专用框架(基于 PyTorch) | CT / MRI / 病理图像 |
| Detectron2 | Meta 出的检测/分割框架 | 学术界标杆 |
| ONNX Runtime | 跨框架推理引擎 | 训练完用 PyTorch,部署时转 ONNX 加速 |
八、术语速查
| 缩写 / 术语 | 全称 / 解释 |
|---|---|
| CV | Computer Vision,计算机视觉(AI 圈语境) |
| NLP | Natural Language Processing,自然语言处理 |
| CNN | Convolutional Neural Network,卷积神经网络(CV 的看家结构) |
| RGB / BGR | 红绿蓝三通道颜色编码;OpenCV 默认 BGR 是历史遗留 |
| FPS | Frames Per Second,每秒帧数(衡量实时性) |
| GPU | Graphics Processing Unit,图形处理器,擅长并行计算 |
| CUDA | NVIDIA 的 GPU 并行计算平台,PyTorch 用它加速 |
| MPS | Metal Performance Shaders,Apple Silicon 的 GPU 后端 |
| Tensor | 张量,多维数组(PyTorch 的核心数据结构) |
| Autograd | 自动微分,自动算导数 |
| Backprop | Backpropagation,反向传播 |
| ONNX | Open Neural Network Exchange,跨框架模型格式 |
| MTCNN | Multi-task Cascaded Convolutional Networks,2016 年提出的人脸检测算法 |
| Haar Cascade | Haar 特征级联分类器,OpenCV 自带的 2001 年传统人脸检测算法 |
| YOLO | You Only Look Once,工业最流行的实时目标检测系列 |
| SAM | Segment Anything Model,Meta 2023 年发布的通用分割大模型 |
与本知识库其他章节的关联
- 神经网络的训练机制(预训练 / SFT / 蒸馏 / RLHF),参见 模型训练技术速查.md
- 注意力机制(CNN 之外另一种主流视觉骨干,ViT 用的就是它)参见 注意力机制.md 和 Transformer.md
- 一个把 PyTorch 用在医学影像 CV 的实战案例,参见 宠物CT影像AI辅助诊断方案.md(其中用到了基于 PyTorch 的 MONAI 框架)
一句话收尾
CV 是”看懂图像”这件事本身;OpenCV 是上一代解决方案的代表工具箱;PyTorch 是这一代解决方案(深度学习)的代表框架。两者不是替代关系,是分工关系——一个干图像搬运,一个干模型推理。学 CV 的人两个都得会。