详见《OpenCV3编程入门(毛星云、冷雪飞)》
OpenCV官方主页:
OpenCV Github主页:/Itseez/opencv
OpenCV开发版Wiki主页:
1.1 OpenCV的下载、安装与配置
本文配置环境为OpenCV 3.4.16 + Visual Studio
1、OpenCV下载
在OpenCV官方主页下载需要的版本,启动.exe解压到D:\Program Files\下
2、配置OpenCV环境变量
在【计算机】 > 【属性】 > 【高级系统设置】 > 【高级】 > 【环境变量】 > 【系统变量】PATH中添加:
D:\Program Files\opencv\build\x64\vc14\bin和…opencv\build\x64\vc14\bin
D:\Program Files\opencv\build\x64\vc14\bin和…opencv\build\x64\vc15\bin
3、工程包含include目录的配置
Visual Studio中:【视图】 > 【属性管理器】 > 【Debug | x64】 右键属性
【通用属性】 > 【VC++目录】 > 【包含目录】中添加以下三个目录
D:\Program Files\opencv\build\include
D:\Program Files\opencv\build\include\opencv
D:\Program Files\opencv\build\include\opencv2
选择x64或是x86取决于编译程序时用哪个编译器,和计算机系统是32位还是64位无关。
4、工程库lib目录的配置
Visual Studio中:【视图】 > 【属性管理器】 > 【Debug | x64】右键属性
【通用属性】 > 【VC++目录】 > 【库目录】中添加以下目录
D:\Program Files\opencv\build\x64\vc14\lib
5、链接库的配置
Visual Studio中:【视图】 > 【属性管理器】 > 【Debug | x64】 右键属性
【通用属性】 > 【链接器】 > 【输入】 > 【附加的依赖项】
粘贴D:\opencv\build\x64\vc14\lib下所有lib库文件的名字
opencv_world3416.lib
opencv_world3416d.lib
Debug文件库名有d结尾,Release没有
6、在Windows文件夹下加入OpenCV动态链接库
对于64位系统,将D:\Program Files\opencv\build\x64\vc14\bin目录下的所有文件复制到C:\Windows\SysWOW64下。
配置完成后,载入一张图片进行测试:
# include <opencv2/opencv.cpp>using namespace cv;int main(){Mat img = imread("1.jpg");imshow("【载入的图片】",img);waitKey(6000);}
1.2 OpenCV基本架构
OpenCV就是多模块作为代码容器组合起来的一个SDK(Software Development Kit,软件开发工具包)
…\opencv\build\include\opencv:OpenCV 1.0保留下来的最核心内容的头文件
…\opencv\build\include\opencv2:新版OpenCV2系列的头文件
opencv_modules.hpp:OpenCV2中与新模块构造相关的说明代码,定义了OpenCV2所有组件的宏。
calib3d:calibration + 3D,主要是和相机校准和三维重建相关的内容,包括基本的多视角几何算法、单个立体摄像头标定、物体姿态估计、立体相似性算法、3D信息的重建
core:核心功能模块,包括OpenCV基本数据结构、动态数据结构、绘图函数、数组操作相关函数、辅助功能与系统函数和宏、与OpenGL的互操作
dnn:对图像和视频完成基于深度学习的计算机视觉推理,包括图像分类、目标检测、图像分割、文字检测和识别、姿态估计、深度估计等
features2d:2D功能框架,包括特征检测和描述、特征检测器Feature Detectors通用接口、描述符提取器Descriptor Extractors通用接口、描述符匹配器Descriptor Matchers通用接口、通用描述符Generic Descriptor匹配器通用接口、关键点绘制函数和匹配功能绘制函数
flann:Fast Library for Approximate Nearest Neighbors,高维的近似近邻快速搜索算法库,包含快速近似最近邻搜索、聚类
highgui:高层GUI图形用户界面,包含媒体的输入输出、视频捕捉、图像和视频的编解码、图形交互界面的接口。
imgcodecs:图像的输入和输出
imgproc:图像处理模块,包括线性和非线性的图像滤波、图像的几何变换、图像转换、直方图、结构分析和形状描述、运动分析和对象跟踪、特征检测、目标检测
ml:机器学习模块,基本是统计模型和分类算法,包括统计模型、一般贝叶斯分类器、K近邻、支持向量机、决策树、提升、梯度提高树、随机树、超随机树、期望最大化、神经网络、MLData
objdetect:目标检测模块,包括Cascade Classification(级联分类)和Latent SVM两部分
photo:Computational Photography,包括图像修复和图像去噪两部分
stiching:图像拼接模块,包含拼接流水线、特点寻找和匹配图像、估计旋转、自动校准、图片歪斜、接缝估测、曝光补偿
superres:超分辨技术相关功能模块
video:视频分析组件,包括运动估计、背景分离、对象跟踪等视频处理内容
videoio:视频输入和输出
videostab:video stabilization,视频稳定相关的组件
#define HAVE_OPENCV_SHAPE
#define HAVE_OPENCV_WORLD
OpenCV3的项目架构改变
抛弃整体架构,使用内核+插件的架构形式。
Github中除了正式版OpenCV的主仓库和新增加的opencv_extra仓库外,还增加了opencv_contrib,包括脸部识别和文本检测、文本识别、新的边缘检测器、充满艺术感的图像修复、深度图处理、新的光流和追踪算法。
opencv_contrib是大多数实验性代码放置的地方,一些API可能会改变,这些额外模块可以在CMake中用OPENCV_EXTRA_MODULES_PATH=/modules传递给CMake文件,和OpenCV3主体中的代码一起编译和运行。opencv_contrib的文档是自动生成的,可以在/master/中找到。
1.3 快速上手OpenCV图像处理
OpenCV图像处理之腐蚀、图像模糊、canny边缘检测
//头文件和命名空间的包含#include <iostream>#include <opencv2/opencv.hpp> //OpenCV头文件的包含#include <opencv2/highgui/highgui.hpp> //OpenCV highgui模块头文件#include <opencv2/imgproc/imgproc.hpp> //OpenCV 图像处理头文件using namespace cv; //包含cv命名空间int main(){//载入图像Mat srcImage = imread("1.jpg"); //显示原图imshow("【原始图】",srcImage);//进行腐蚀操作(用图像的暗色部分腐蚀掉图像的高亮部分)Mat element = getStructuringElement(MORPH_RECT, Size(15,15)); //返回指定形状和尺寸的结构元素(内核矩阵)Mat dstImage1,dstImage2, dstImage3, edge, grayImage;erode(srcImage, dstImage1, element); //腐蚀操作imshow("【效果图】腐蚀操作",dstImage1);//图像模糊blur(srcImage,dstImage2,Size(7,7)); //模糊操作imshow("【效果图】均值滤波",dstImage2);//canny边缘检测dstImage3.create(srcImage.size(),srcImage.type());cvtColor(srcImage,grayImage,COLOR_BGR2GRAY); //转为灰度图blur(grayImage,edge,Size(3,3)); //使用3×3内核来降噪Canny(edge,edge,3,9,3); //运行Canny算子imshow("【效果图】Canny边缘检测",edge);waitKey(6000); //等待任意按键按下return 0;}
1.4 OpenCV视频操作基础
OpenCV中的VideoCapture类:对视频进行读取显示,调用摄像头。
读入工程目录下的“1.avi”:
//方式1:先实例再初始化VideoCapture capture;capture.open("1.avi");//capture.open(0); 调用摄像头采集图像//方式2:实例化的同时进行初始化VideoCapture capture("1.avi");//VideoCapture capture(0); 调用摄像头采集图像
摄像头调用配合canny边缘检测:
# include "opencv2/opencv.hpp"using namespace cv;int main(){//读入图像while(1){Mat frame;capture >> frame; cvtColor(frame,edges, CV_BGR2GRAY);blur(edges, edges, Size(7,7)); //进行模糊Canny(edges,edges,0,30,3); //进行Canny边缘检测imshow("被Canny后的视频",edges); //显示经过处理后的当前帧if(waitKey(30)>=0) break; //延时30s}return 0;}
1.5 编译OpenCV源代码
1、下载安装CMake
CMake下载官网:/
在Binary distributions中找到需要平台的Installer文件
CMake:
1、跨平台的编译工具,可以用简单的语言描述所有平台的安装(编译)过程,能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。
2、CMake的组态档取名为CmakeLists.txt,并不是直接建构出最终的软件,而是产生标准的建构档(如UNIX的Makefile或Windows Visual C++的project/workspaces),然后再依一般的建构方式使用。这使熟悉某个集成开发环境(IDE)的开发者可以用标准方式建构他的软件。
3、CMake可以根据CMakeLists.txt这个配置文件,通过选择不同的编译器来生成不同的解决方案,VisualStudio的编译器对应生成Visual Studio版的sln解决方案。
4、这种可以使用各平台原生建构系统的能力是CMake和SCons等其他类似系统的区别。
2、使用CMake生成OpenCV源代码工程的解决方案
运行cmake-gui(通过桌面快捷方式或Program Files\CMake\bin\cmake-gui.exe)
3、编译OpenCV源代码
编译OpenCV,其实就是得到了一些二进制的生成文件,如dll、lib和exe。因为是在debug下编译的,所以在工程目录的bin\debug下会生成OpenCV对应版本的依赖库,可以供以后调用此次编译的OpenCV时使用。
打开生成的OpenCV.sln解决方案,F5启动调试,编译耗时几分钟。
由于OpenCV的源代码工程默认将ALL_BUILD设置为启动项,编译成功后,会默认运行它。ALL_BUILD是一个项目生成周边的杂项,不是exe执行文件,本身不可以运行,因此可能会弹出错误提示,不必理会。
可以指定一个另外的启动项:所选项目 > 【设为启动项】
1.6 Samples官方实例
OpenCV提供了Android、CPP、GPU、Java、Mac OS X、OCL、Python、Python2、WinRT等版本的示例程序。
在…\opencv\sources\samples下面,有各种语言的示例和CMakeLists.txt,可以使用CMake来生成Visual Studio解决方案:
注意:如果链接的库是x64,那么CMake生成解决方案时也应该选择x64,两边需要保持一致,否则编译通过后无法运行。
将…\opencv\sources\samples\data文件夹拷贝到samples.sln根目录下,使用图片素材配合运行示例。
运行某一示例:所选项目右键 > 【调试】 > 【启动新实例】
彩色目标跟踪:Camshift
路径:…\opencv\sources\samples\cpp下的camshiftdemo.cpp文件
功能:根据鼠标框选区域的色度光谱来进行摄像头读入的视频目标的跟踪,主要采用Camshift(Continuously Adaptive Mean-SHIFT)算法,是对MeanShift算法的改进。
光流:optical flow
光流用来指定时变图像中模式的运动速度,当物体在运动时,在图像上对应点的亮度模式也在运动。光流包含了目标运动的信息,因此可被观察者用来确定目标的运动情况。
点追踪:lkdemo
路径:…\opencv\sources\samples\cpp下的lkdemo.cpp文件
程序运行后会启动启动摄像头,按键盘上的r键启动自动点追踪,可以看到物体上的点随着物体一同移动。
人脸识别:objectDetection
路径:…\opencv\sources\samples\cpp\tutorial_code\objectDetection
注意:将…\opencv\sources\data\haarcascades下的haarcascade_eye_tree_eyeglasses.xml和haarcascade_frontalface_alt.xml文件复制到和源文件同一目录中。
程序运行后,将脸对准摄像头,可以发现程序准确识别出人脸,并用彩色的圆将脸圈出。
支持向量机引导
在OpenCV的机器学习模块有两个示例程序,第一个是使用CvSVM::train训练一个SVM分类器。
第二个是用于讲解在训练数据线性不可分时,如何定义支持向量机的最优化问题。
1.7 “opencv.hpp”头文件认知
在编写core、objdetect、imgproc、photo、video、feature2d、objdetect、calib3d、ml、highgui、contrib模块的应用程序时,原则上仅写一句
#include <opencv2/opencv.hpp>
可以精简优化代码。
opencv.hpp中已经包含了OpenCV各模块的头文件,如高层GUI图形用户界面模块头文件“highgui.hpp”、图像处理模块头文件“imgproc.hpp”、2D特征模块头文件“features2d.hpp”等。
1.8 命名规范约定
编写代码时,一旦确定某一套命名规范,最好不要中途更改。
《代码大全》规定
类名:混合使用大小写,首字母大写。ClassName
类型定义:包括枚举和typedef,混合使用大小写,首字母大写。TypeName
枚举类型:除了混合使用大小写外,总以复数形式表示。EnumeratedTypes
局部变量:混合使用大小写,且首字母小写,名字与底层数据类型无关,应该反映该变量代表的事物。localVariable
子程序参数:混合使用大小写,每个单词首字母大写,名字与底层数据类型无关,应该反映该变量代表的事物。RoutineParameter
对类的多个子程序可见的成员变量名:用m_前缀。m_ClassVariable
局部变量名:用g_前缀。g_GlobalVariable
具名常量:全部大写。CONSTANT
宏:全部大写,单词间用分隔符"_"隔开。SCREEN_WIDTH
枚举类型成员名:用能反映其基础类型的、单数形式的前缀。Color_Red
Base_EnumeratedType
匈牙利命名法
基本原则:变量名=属性+类型+对象描述
1.9 argc与argv
argc, argv两个参数一般在用命令行编译程序时有用。在opencv官方示例程序中,main函数会带上两个形参:
int main(int argc, char* argv[]){const char* imagename = argc > 1 ? argv[1] : "lena.jpg"}
UNIX和Linux中的标准写法为:
main(int argc, char *argv[], char**env)
arg:参数,例如arguments, argument_counter, argument vector
argc:int类型,用来统计运行程序时送给main函数的命令行参数的个数,在Visual Studio中默认为1
argv[]:char*类型,为字符串数组,用来存放指向字符串参数的指针数组,每一个元素指向一个参数。
argv[0]:指向程序运行的全路径名
argv[1]:指向在DOS命令行中执行程序名后的第一个字符串
argv[2]:指向执行程序名后的第二个字符串
argv[3]:指向执行程序名后的第三个字符串
argv[argc]为NULL
argv[1]对应 【项目属性】 > 【配置属性】 > 【调试】 > 【命令参数】,记住带双引号,如果有多个字符串,用空格隔开。比如要读取两张名称为1.jpg,2.jpg的图片,在命令参数中填"1.jpg" “2.jpg”。
如果在Visual Studio中使用了argc或argv,必须在 【项目属性】 > 【配置属性】 > 【调试】 > 【命令参数】中指定参数的值。
也可以将argc, argv有关的代码进行替换来通过编译,比如将Mat srcImage=imread(argv[1],1);
替换为Mat srcImage=imread("1.jpg",1);
env:char**类型,为字符串数组,很少使用。env[]每一个元素都包含ENVVAR=value形式的字符串,其中ENVVAR为环境变量,value为ENVVAR的对应值。
argc, argv和env是在main()函数之前被赋值的,因此main()并非真正的程序入口点函数,往往入口点与操作系统有关。在Windows的控制台应用程序中,将main()函数作为程序入口点,很少使用argc, argv等命令行参数。
main()函数的几种写法:
1、返回值为整型带参的main函数
int main(int argc, char** argv){//函数体内使用或不使用argc和argv都可行return 1;}
2、返回值为整型不带参的main函数
int main(int argc, char** argv){//函数体内使用argc或argvreturn 1;}
3、返回值为void且不带参的main函数
int main(){return 1;}
1.10 格式输出函数printf()简析
printf函数是标准C语言函数,包含在studio.h中,OpenCV也对其有包含,只需包含头文件如opencv.hpp,就可以使用。
int printf(const char *format, )//int printf("格式控制字符串",输出表列);
1.11 智能显示当前使用的OpenCV版本
OpenCV提供了一个名为“CV_VERSION”的用于标识当前OpenCV版本的宏。可使用如下代码进行智能检测,并将版本号输出到控制台窗口中:
printf("\t 当前使用的OpenCV版本为OpenCV" CV_VERSION);