OpenCV入门及应用案例:手把手教你做DNN图像分类
导读:本文将介绍OpenCV的源码结构、OpenCV深度学习应用的典型流程,以及深度学习和OpenCV DNN(Deep Neural Networks,深度神经网络)模块的背景知识,让读者可以快速认识OpenCV,消除神秘感,同时对计算机视觉从传统算法到深度学习算法的演进历史有所了解。
OpenCV是一个计算机视觉开源库,提供了处理图像和视频的能力。OpenCV的影响力非常大,有超过47 000的社区用户,以及超过1400万次的下载量。其应用领域横跨图像处理、交互式艺术、视频监督、地图拼接和高级机器人等。作为一个有十几年历史的开源项目,OpenCV拥有广大的用户群体和开发者群体。
在数字的世界中,一幅图像由多个点(像素)组成。图像处理就是对其中一个像素或者一个区域内的像素(块)进行处理。无论是初学者还是富有经验的研发人员,他们都需要借助软件工具来分析这些像素和图像块,OpenCV则是其中最常用、最重要的一个软件工具。
OpenCV成为最主要的图像处理工具包,是因为它功能齐全,支持目前主流的图像、视频处理算法,而且对外提供C++、Python和Java的接口,用户调用方便。本书的代码分析、示例程序及环境搭建基于OpenCV 4.1版本,源代码位于GitHub的OpenCV仓库。
01 OpenCV库
OpenCV由各种不同组件组成。OpenCV源代码主要由OpenCV core(核心库)、opencv_contrib和opencv_extra等子仓库组成。近些年,OpenCV的主仓库增加了深度学习相关的子仓库:OpenVINO(即DLDT, Deep Learning Deployment Toolkit)、open_model_zoo,以及标注工具CVAT等。
下面分别介绍3个主要的代码库:OpenCV core、opencv_contrib、opencv_extra。
1. 核心库OpenCV core
核心库是OpenCV的主要算法来源。OpenCV采用模块化结构设计,包含了多个共享或者静态库。目前OpenCV核心库提供了很多组件,如下所示。
核心功能模块:这是一个小巧而高效的模块,定义了基础的数据结构,包含紧密多尺度向量矩阵和一些供其他模块使用的基础函数 图像处理模块:它包括了线性和非线性的图像滤波、几何图像变换(图像缩放、仿射变换、透视矫正、通用的基于表格的像素映射)、色域变换及直方图生成与分析等 视频:这是一个视频分析模块,包含运动检测、背景减除和对象追踪等算法 calib3d:包含基础的多视角几何算法、单个和立体相机标定算法、对象姿势预测算法、立体一致性算法,以及3D元素重建 Features2d:图像显著特征检测、特征点描述和匹配 Objdetect:对象检测和预先定义的类别检测(如脸、眼、杯子、人、车等) Highgui:提供了比较容易使用的UI接口 Video I/O:提供了基本的视频存取访问和编解码功能 GPU:为不同的OpenCV算法模块提供GPU加速算法 其他:如FLANN和Google测试封装层、Python绑定等
// 引入OpenCV DNN模块的命名空间
using namespace cv::dnn;
// 创建人脸检测器
CascadeClassifier cascade;
// 导入性别和年龄深度神经网络模型
Net gender_net=dnn::readNetFromCaffe(gender_modelTxt, gender_modelBin);
Net age_net=dnn::readNetFromCaffe(age_modelTxt, age_modelBin);
// 人脸检测
cascade.load(cascadeName);
cascade.detectMultiScale(input_gray_file, output_faces_data);
// 准备深度神经网络的输入数据
Mat inputBlob=blobFromImage(input.getMat(ACCESS_READ));
gender_net.setInput(inputBlob, "data");
age_net.setInput(inputBlob, "data");
// 执行模型的前向运算,即模型推理
Mat gender_prob=gender_net.forward("prob");
Mat age_prob=age_net.forward("prob");
轻量:OpenCV的深度学习模块只实现了模型推理功能,这使得相关代码非常精简,加速了安装和编译过程。 最少的外部依赖:重新实现一遍深度学习框架使得对外部依赖减到最小,大大方便了深度学习应用的部署。 方便集成:①如果原来的应用是基于OpenCV开发的,通过深度学习模块可以非常方便地加入对神经网络推理的支持;②如果网络模型来自多个框架,如一个来自TensorFlow,一个来自Caffe,则深度学习模块可以方便整合网络运算结果。 通用性:①提供统一的接口来操作网络模型;②内部所做的优化和加速对所有网络模型格式都适用;③支持多种设备和操作系统。
图像分类网络
Caffe:AlexNet、GoogLeNet、VGG、ResNet、SqueezeNet、DenseNet、ShuffleNet TensorFlow:Inception、MobileNet Darknet:darknet-imagenet ONNX:AlexNet、GoogleNet、CaffeNet、RCNN_ILSVRC13、ZFNet512、VGG16、VGG16_bn、ResNet-18v1、ResNet-50v1、CNN Mnist、MobileNetv2、LResNet100E-IR、Emotion FERPlus、Squeezenet、DenseNet121、Inception-v1/v2、ShuffleNet
对象检测网络
Caffe:SSD、VGG、MobileNet-SSD、Faster-RCNN、R-FCN、OpenCV face detector TensorFlow:SSD、Faster-RCNN、Mask-RCNN、EAST Darknet:YOLOv2、Tiny YOLO、YOLOv3 ONNX:TinyYOLOv2
语义分割网络:FCN(Caffe)、ENet(Torch)、ResNet101_DUC_HDC(ONNX) 姿势估计网络:openpose(Caffe) 图像处理网络:Colorization(Caffe)、Fast-Neural-Style(Torch) 人脸识别网络:openface(Torch)
import numpy as np # 引入numpy库
import cv2 as cv # 引入OpenCV库,深度学习模块包含在其中
with open('synset_words.txt') as f:
classes=[x[x.find(' ') + 1:] for x in f]
image=cv.imread('space_shuttle.jpg')
input=cv.dnn.blobFromImage(image, 1, (224, 224), (104, 117, 123))
net=cv.dnn.readNetFromCaffe('bvlc_googlenet.prototxt',
'bvlc_googlenet.caffemodel')
net.setInput(input)
out=net.forward()
indexes=np.argsort(out[0])[-5:]
for i in reversed(indexes):
print ('class:', classes[i], ' probability:', out[0][i])
本文摘编自《OpenCV深度学习应用与性能优化实践》,经出版方授权发布。