共计 3022 个字符,预计需要花费 8 分钟才能阅读完成。
图像分类:从像素到语义的抽象之旅
图像分类是计算机视觉的基石任务,其核心是将输入图像分配到一个预定义的类别标签。卷积神经网络(CNN)通过层次化特征提取实现这一目标:

- 浅层特征提取:前几层卷积核(如 3 ×3 或 5 ×5)捕捉边缘、颜色等低级特征。例如 VGG16 的第一个卷积层可检测 45 度方向的边缘。
- 中层特征组合:随着网络加深,特征图(feature map)逐渐组合出纹理、部件等中级特征。ResNet 的残差连接有效缓解了深层网络梯度消失问题。
- 高级语义理解:全连接层将空间特征转化为类别概率。AlexNet 首次使用 ReLU 激活函数,相比 Sigmoid 显著加速训练过程。
# PyTorch 图像分类示例
import torch
import torchvision
model = torchvision.models.resnet18(pretrained=True)
model.eval()
# 输入预处理
transform = torchvision.transforms.Compose([torchvision.transforms.Resize(256),
torchvision.transforms.CenterCrop(224),
torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
# 推理示例
input_tensor = transform(Image.open('cat.jpg')).unsqueeze(0)
with torch.no_grad():
output = model(input_tensor)
print(torch.nn.functional.softmax(output[0], dim=0))
目标检测:定位与识别的双重挑战
目标检测需要同时完成物体定位(bounding box)和分类任务,主流方法可分为两阶段(如 Faster R-CNN)和单阶段(如 YOLO)检测器:
- Faster R-CNN 工作流:
- 区域提议网络(RPN)生成候选区域
- ROI Pooling 将不同尺寸提案归一化
- 分类头与回归头并行输出
-
典型推理速度:5-10 FPS(V100)
-
YOLO 设计哲学:
- 将图像划分为 SxS 网格
- 每个网格预测 B 个边界框及置信度
- 单次前向传播完成检测
- YOLOv4 可达 60 FPS(RTX 2080Ti)
# 非极大值抑制 (NMS) 实现
def nms(boxes, scores, threshold=0.5):
"""
输入: boxes(N,4), scores(N,)
输出: 保留的索引列表
"""
x1 = boxes[:,0]; y1 = boxes[:,1]
x2 = boxes[:,2]; y2 = boxes[:,3]
areas = (x2 - x1) * (y2 - y1)
_, order = scores.sort(0, descending=True)
keep = []
while order.numel() > 0:
i = order[0]
keep.append(i)
# 计算交集区域
xx1 = x1[order[1:]].clamp(min=x1[i].item())
yy1 = y1[order[1:]].clamp(min=y1[i].item())
xx2 = x2[order[1:]].clamp(max=x2[i].item())
yy2 = y2[order[1:]].clamp(max=y2[i].item())
inter = (xx2 - xx1).clamp(min=0) * (yy2 - yy1).clamp(min=0)
# 计算 IoU
iou = inter / (areas[i] + areas[order[1:]] - inter)
idx = (iou <= threshold).nonzero().squeeze()
order = order[idx + 1] if idx.numel() > 0 else torch.tensor([])
return torch.tensor(keep)
语义分割:像素级的场景理解
语义分割需要为每个像素分配类别标签,全卷积网络(FCN)通过编码器 - 解码器结构实现这一目标:
- 编码器部分:
- 使用 CNN 骨干网络(如 ResNet)提取特征
- 感受野(receptive field)随深度增大
-
通过步幅卷积(stride conv)下采样
-
解码器关键操作:
- 转置卷积(transposed conv)进行上采样
- 跳跃连接(skip connection)融合多级特征
- 输出通道数 = 类别数的特征图
# FCN 模型定义示例
class FCN(nn.Module):
def __init__(self, n_class):
super().__init__()
self.base = torchvision.models.resnet18(pretrained=True)
# 替换 ResNet 最后的全连接层
self.conv1 = nn.Conv2d(512, 512, 3, padding=1)
self.conv2 = nn.Conv2d(512, n_class, 1)
self.upsample = nn.ConvTranspose2d(n_class, n_class, 16, stride=16, padding=0)
def forward(self, x):
x = self.base.conv1(x)
x = self.base.bn1(x)
x = self.base.relu(x)
x = self.base.maxpool(x)
# 获取中间层特征
f1 = self.base.layer1(x) # 1/4
f2 = self.base.layer2(f1) # 1/8
f3 = self.base.layer3(f2) # 1/16
f4 = self.base.layer4(f3) # 1/32
# 解码器部分
x = F.relu(self.conv1(f4))
x = self.conv2(x)
x = self.upsample(x)
return x
生产环境中的关键考量
计算资源与实时性权衡
- 分类任务:轻量级 MobileNetV3 可在手机端实现 10ms 级推理
- 检测任务:YOLOv5s 模型量化后仅 14MB,适合边缘设备
- 分割任务:DeepLabv3+ 通过 ASPP 模块平衡精度与速度
标注成本分析
| 任务类型 | 标注耗时(每图) | 标注工具 |
|---|---|---|
| 分类 | <1 秒 | 打标签 |
| 检测 | 30-300 秒 | LabelImg |
| 分割 | 2-10 分钟 | CVAT |
模型量化部署示例
# TensorRT 优化流程
$ python -m torch2trt \
--input ./model.pth \
--output ./model.trt \
--fp16 \
--input-shape 1 3 224 224
避坑实践指南
- 数据增强同步问题:
- 检测任务中需同时对图像和 bbox 坐标进行相同变换
-
分割任务需确保空间变换后的标签对齐
-
小目标检测技巧:
- 使用 FPN(特征金字塔)融合多尺度特征
-
调整 anchor 尺寸匹配小物体比例
-
类别不平衡处理:
- 分割任务推荐使用 Dice Loss
- 分类任务可采用 Focal Loss
延伸思考方向
- 多任务学习:共享骨干网络实现分类 + 检测 + 分割
- 自监督预训练:通过 MAE 等方法减少标注依赖
- 领域自适应:使用 CycleGAN 进行跨域数据增强
希望这篇笔记能帮助开发者快速理解计算机视觉核心任务的实现原理,在项目选型时做出更合理的技术决策。建议读者尝试在 COCO 或自定义数据集上微调这些模型,实践是掌握细节的最佳途径。
正文完
