先说一个很有意思的起点:计算机视觉(Computer Vision,也称机器视觉),本质上就是让机器学会“看”这个世界。不过这里的“看”,可不是简单地按下快门或打开摄像头,而是要像人眼那样,能够从图像和视频中识别物体、判断位置、理解场景,甚至“讲述”出画面背后的故事。如今,这项技术已经深入各行各业——安防监控、工业质检、自动驾驶……背后都离不开它的支撑。
那么,机器究竟是如何“看见”的?这背后,其实藏着一条漫长的演化路径。
1 计算机视觉
1.1 计算机视觉概述
想要理解计算机视觉,不妨先看看生物视觉的起源。学术界对此有两种主流推测:一种认为最早的视觉器官出现在大约7亿年前的水母身上;另一种则认为它诞生于5亿年前的寒武纪。寒武纪生物大爆发至今仍是未解之谜,但有一点是确定的——在那个时期,动物第一次拥有了“看见”的能力。捕食者能更精准地锁定猎物,猎物也能更早地察觉天敌的靠近。视觉的出现,让猎手与猎物之间的博弈空前激烈,也加速了生命的演化节奏。
经过数亿年的淬炼,今天我们人类的视觉系统已经高度精密。人脑中大约有1000亿个神经元,它们通过复杂的网络彼此连接,才让我们能够如此轻松地感知和理解周围的世界。

图1:人类视觉感知
1.2 计算机视觉应用场景
经过几十年的发展,计算机视觉早已走出实验室,落地到现实生活的方方面面。交通领域的车牌识别和违章抓拍、安防领域的人脸闸机和小区监控、金融领域的刷脸支付和票据识别、医疗领域的影像诊断、工业领域的产品缺陷自动检测……这些看似稀松平常的功能,背后都藏着计算机视觉的影子。而随着技术持续演进,未来还会有更多新场景被打开,给我们的生活带来更大的便利。

图2:计算机视觉技术在各领域的应用
1.3 计算机视觉任务的挑战
说起来你可能不信——人类一眼就能分清猫和狗,但对计算机来说,这却是一个世界级难题。你也许会说:“写个程序,体型大的是狗,小的就是猫?”可问题是,拍摄角度一变,猫在画面里占的像素可能比狗还多,机器照样会认错。这背后折射出一个核心问题:计算机视觉任务面对的挑战实在太多了。目标被遮挡、尺寸变化、物体变形、背景杂乱、光照不均……任何一点干扰,都可能导致识别失败。
此外,数据量有限、类别不均衡、实时性要求高,同样是很多实际项目中绕不开的坎。
2 常见的计算机视觉任务简介和基础概念
所有计算机视觉任务,说到底都依赖图像特征——也就是图像中的信息。传统做法是用设计好的算法(比如SIFT、HOG)来提取这些特征,然后交给SVM这类机器学习算法去处理。以行人检测为例,流程大致是这样的:
- 先通过滑动窗口遍历整张图像,找到候选区域
- 提取候选区域的HOG特征
- 用SVM分类器判断这些区域是不是人
- 由于滑动窗口会产生大量重复区域,再用非极大值抑制(NMS)做一次过滤
不难看出,这种方法非常依赖人工设计的特征,只有经验丰富的研究者才能搞出好的效果。
也正是在这样的背景下,基于神经网络的特征提取方法开始崭露头角。1998年,Yann LeCun第一次把卷积神经网络(CNN)用在了图像识别上,核心思路很简单:让网络自己从数据中学习特征,而不是靠人去设计。他提出的LeNet在手写数字识别上取得了巨大成功。但此后的很长一段时间里,这条路却并没有立刻成为主流——一方面是缺乏足够大的数据集,模型在大尺寸图像上容易过拟合;另一方面是当时的硬件算力有限,网络一复杂,计算速度就跟不上。
直到2012年,Alex Krizhevsky等人提出了AlexNet,并在ImageNet大赛上一举夺魁,才彻底点燃了深度学习在计算机视觉领域的爆发。

图5:早期的卷积神经网络处理图像任务示意
这里简单提几个核心概念:
- 全连接:也叫多层感知机,是最基础的神经网络结构。
- 卷积:卷积层的实现其实是数学中定义的互相关运算,但习惯上大家仍叫它卷积。
- 池化:用某一位置相邻输出的统计特征(比如最大值或平均值)来代替该位置的输出,以此减少计算量。
- Dropout:一种常用的防止过拟合技巧——训练时随机让一部分神经元“失活”,迫使网络学到更鲁棒的特征。
3 常见的计算机视觉任务快速实践
如今的情况已经完全不同了。互联网的爆发带来了海量的数据,硬件的进步让算力不再是瓶颈,新的模型和算法层出不穷。计算机视觉能处理的任务也越来越丰富:分类、检测、分割、场景描述、图像生成、风格迁移……甚至连视频和3D内容也被纳入其视野。
接下来,我们就来看看目前主流的几个视觉任务,再通过PaddleHub工具快速上手实践一番。
首先安装PaddleHub:
!pip install paddlehub --upgrade -i https://mirror.baidu.com/pypi/simple
import paddlehub as hub import cv2 from PIL import Image import matplotlib.pyplot as plt %matplotlib inline
3.1 图像分类
图像分类,本质上就是让机器给图像或图像中的某个区域打上一个类别标签。它是计算机视觉最基础的问题,也是检测、分割、跟踪等更高级任务的前提。安防领域的人脸识别、交通领域的场景识别、互联网领域的图像检索和相册自动归类、医学领域的影像分析……背后都离不开它。
我们用PaddleHub快速上手,下面这个例子加载了resnet50_vd_dishes模型,用来识别美食图片:
classifier = hub.Module(name="resnet50_vd_dishes")
result = classifier.classification(images=[cv2.imread('imgs/test1.jpg')])
print('result:{}'.format(result))
[2022-06-28 17:55:45,454] [ WARNING] - The _initialize method in HubModule will soon be deprecated, you can use the __init__() to handle the initialization of the object
result:[{'白灼虾': 0.4448080360889435}]
从上面的运行结果可以看出,模型成功识别出“白灼虾”,且置信度达到0.44。当然,图像分类的模型远不止ResNet一种。目前大体可分为两大类:CNN骨干网络和Transformer骨干网络。而每一类又包含面向服务器的高精度模型和面向移动端的轻量级模型,后者在推理速度上更有优势。

图:图像分类算法
如果想了解更多分类模型的细节,可以参考图像分类开发套件PaddleClas。
3.2 目标检测
计算机看到的只是一堆数字编码,它并不理解画面中的人和物,更不知道它们在哪里。目标检测要做的,就是让计算机不仅认出画面中的每个目标类别,还要用边界框把它们的位置标出来。这项技术的应用场景相当广泛:安全帽检测、火灾烟雾检测、人员摔倒检测、电瓶车进电梯检测等等。
我们用PaddleHub的yolov3_darknet53_vehicles模型来检测图片中的车辆:
vehicles_detector = hub.Module(name="yolov3_darknet53_vehicles")
result = vehicles_detector.object_detection(images=[cv2.imread('imgs/test2.jpg')], visualization=True)
# 结果保存在'yolov3_vehicles_detect_output/'目录
img = Image.open(result[0]['sa ve_path'])
plt.figure(figsize=(15,8))
plt.imshow(img)
plt.show()
目前目标检测的主流方法,主要分这几条路线:Anchor based(包括两阶段和单阶段)、Anchor free,以及Transformer系列。Anchor可以理解为一组预先设定好比例的候选框,基于Anchor的方法就是用它们来提取候选目标框,然后进行分类和回归。两阶段模型先产出候选框,再做精细调整;单阶段模型省略了候选框这一步,直接输出位置和类别,速度更快,但有时精度会略逊一筹。由于人工设计的Anchor对不同大小的物体不太友好,后来发展出Anchor free方法,不再依赖预设框,而是直接预测目标的中心点或角点。

图:目标检测算法
更多模型细节,可以参考目标检测开发套件PaddleDetection。
3.3 图像分割
如果说目标检测是用矩形框“圈”出目标,那么图像分割就是给画面中的每一个像素都打上标签,把一个图像切分成多个有意义的区域。相同标签的像素往往具有共同的视觉特征。图像分割的应用同样非常广泛:人像分割、车道线分割、无人车环境感知、地块检测、表计识别等等。
我们用deeplabv3p_xception65_humanseg模型来演示人像分割:
human_seg = hub.Module(name="deeplabv3p_xception65_humanseg")
result = human_seg.segmentation(images=[cv2.imread('./imgs/test3.jpg')], visualization=True)
# 结果保存在'humanseg_output/'目录
img_ori = Image.open('./imgs/test3.jpg')
img = Image.open(result[0]['sa ve_path'])
fig = plt.figure(figsize=(8,8))
ax = fig.add_subplot(1,2,1)
ax.imshow(img_ori)
ax = fig.add_subplot(1,2,2)
ax.imshow(img)
plt.show()
图像分割的算法也同样丰富:

图12:图像分割算法
更多模型细节,可以参考图像分割开发套件PaddleSeg。
3.4 OCR
OCR(光学字符识别)是计算机视觉中一个非常活跃的方向。早期OCR主要针对扫描文档,而现在大家常说的OCR更多是指场景文字识别——也就是从复杂的自然环境中提取出文字信息。它的应用场景相当丰富:卡证票据信息录入、工厂自动化、政府医院文档电子化、在线教育等等。

图:文字识别示意图
我们用chinese_ocr_db_crnn_mobile模型来体验一下OCR:
ocr = hub.Module(name="chinese_ocr_db_crnn_mobile")
result = ocr.recognize_text(images=[cv2.imread('./imgs/test4.jpg')], visualization=True)
# 结果保存在'ocr_result/'目录
img = Image.open(result[0]['sa ve_path'])
plt.figure(figsize=(20,20))
plt.imshow(img)
plt.show()

这个例子中,我们用了DBNet做检测、CRNN做识别,属于典型的“两阶段”方法。当然也有端到端的方法,用一个模型同时完成检测和识别。在实际项目中,OCR算法往往还需要搭配文档分析算法一起使用。

图14:OCR算法
文档分析中,版面分析负责识别图像中的文本、标题、表格等区域;表格识别则对表格区域做结构化分析,输出Excel文件;关键信息提取算法能给每个文本区域打上语义标签,比如“订单ID”“发片号码”“金额”;文档视觉问答(DocVQA)则包含了语义实体识别和关系抽取等任务。PP-Structure工具集就整合了版面分析、表格识别、视觉问答等功能。

图15:文档分析算法
更多OCR模型细节,可以参考PaddleOCR。
3.5 视频分析
视频不同于单张图片——它是动态的、按时间排序的图像序列,帧与帧之间存在紧密的上下文联系,同时还可能包含音频和文本信息。视频分析的子任务十分丰富:

图16:视频分析子任务示意图
我们用videotag_tsn_lstm模型来做一次视频分类:
videotag = hub.Module(name="videotag_tsn_lstm") result = videotag.classify(paths=["imgs/dance.mp4"]) print(result)
[{'path': 'imgs/dance.mp4', 'prediction': {'舞蹈': 0.8504236936569214}}]
上面用了TSN模型,分类结果也相当理想。视频分析的算法架构也同样在不断进化:

图18:视频分析算法
想了解更多视频分析模型,可以查阅PaddleVideo。
3.6 图像生成
说到图像生成,就绕不开GAN(生成对抗网络)。这个由Ian J. Goodfellow等人提出的框架,包含一个生成器和一个判别器。生成器负责生成越来越逼真的数据,判别器则努力区分生成的结果和真实数据。两者在不断的“博弈”中达到平衡,最终生成器输出的数据足以以假乱真。GAN的应用范围极广:图像生成、风格迁移、超分辨率、影像上色、人脸属性编辑、人脸融合、动作迁移,等等。
我们试试用UGATIT_100w模型做一次人像动漫化:
import cv2
import paddlehub as hub
model = hub.Module(name='UGATIT_100w')
# 结果保存在'output/'目录
result = model.style_transfer(images=[cv2.imread('imgs/test6.jpg')], visualization=True)
img_ori = Image.open('./imgs/test6.jpg')
img = cv2.cvtColor(result[0], cv2.COLOR_BGR2RGB)
img = Image.fromarray(img)
fig = plt.figure(figsize=(8,8))
ax = fig.add_subplot(1,2,1)
ax.imshow(img_ori)
ax = fig.add_subplot(1,2,2)
ax.imshow(img)
plt.show()
效果非常直观。图像生成的算法栈也很丰富:

图20:图像生成算法
想了解更多细节,可以参考PaddleGAN。
4 总结
这一章我们从计算机视觉的基本概念讲起,梳理了它的应用场景和面临的挑战,随后逐一介绍了图像分类、目标检测、图像分割、OCR、视频分析、图像生成这六大常见任务,并通过PaddleHub工具进行了快速实践。希望能帮你建立起一个从原理到实操的完整视角。
