简介
OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉库,它提供了很多函数,这些函数非常高效地实现了计算机视觉算法。
OpenCV 使用 C/C++ 开发,同时也提供了 Python、Java、MATLAB 等其他语言的接口
OpenCV 是跨平台的,可以在 Windows、Linux、Mac OS、Android、iOS 等操作系统上运行。
OpenCV 的应用领域非常广泛,包括图像拼接、图像降噪、产品质检、人机交互、人脸识别、动作识别、动作跟踪、无人驾驶等。
OpenCV 还提供了机器学习模块,你可以使用正态贝叶斯、K最近邻、支持向量机、决策树、随机森林、人工神经网络等机器学习算法。
OpenCV 的目标是为计算机视觉需要解决的问题提供工具。在某些情况下,函数库中的高级功能可以有效解决计算机视觉中的问题。
组成模块
OpenCV 是由很多模块组成的,这些模块可以分成很多层:
最底层是基于硬件加速层(HAL)的各种硬件优化。
再上一层是 opencv_contrib 模块所包含的 OpenCV 由其他开发人员所贡献的代码,其包含大多数高层级的函数功能。这就是OpenCV的核心。
接下来是语言绑定和示例应用程序。
处于最上层的是 OpenCV 和操作系统的交互。
image.png
当前 OpenCV 所拥有的模块
模块
说明
Core
该模块包含 OpenCV 库的基础结构以及基本操作。
mproc
图像处理模块包含基本的图像转换,包括滤波以及类似的卷积操作。
Highgui
在 OpenCV 3.0中,分割为 imcodecs、videoio 以及 highgui 三部分。这个模块包含可以用来显示图像或者简单的输入的用户交互函数。这可以看作是一个非常轻量级的 Windows UI 工具包。
Video
该模块包含读取和写视频流的函数。
Calib3d
这个模块包括校准单个、双目以及多个相机的算法实现。
Feature2d
这个模块包含用于检测、描述以及匹配特征点的算法。
Objdectect
这个模块包含检测特定目标,比如人脸或者行人的算法。也可以训练检测器并用来检测其他物体。
Ml
机器学习模块本身是一个非常完备的模块,包含大量的机器学习算法实现并且这些算法都能和 OpenCV 的数据类型自然交互。
Flann
Flann 的意思是“快速最邻近库”。这个库包含一些你也许不会直接使用的方法,但是其他模块中的函数会调用它在数据集中进行最邻近搜索。
GPU
在 OpenCV 中被分割为多个 cuda* 模块。GPU 模块主要是函数在 CUDA GPU 上的优化实现,此外,还有一些仅用于 GPU 的功 能。其中一些函数能够返回很好的结果,但是需要足够好的计算资源,如果硬件没有GPU,则不会有什么提升。
Photo
这是一个相当新的模块,包含计算摄影学的一些函数工具。
Stitching
本模块是一个精巧的图像拼接流程实现。这是库中的新功能,但是,就像 Photo 模块一样,这个领域未来预计有很大的增长。
Nonfree
在 OpenCV 3.0 中,被移到 opencv_contrib/xfeatures2d。OpenCV 包含一些受到专利保护的或者受到使用限制的(比如 SIFT 算法)算法。这些算法被隔离到它们自己的模块中,以表明你需要做一些特殊的工作,才可以在商业产品中使用它们。
Contrib
在 OpenCV 3.0 中,融合进了 opencv_contrib。这个模块包含一些新的、还没有被集成进 OpenCV 库的东西。
Legacy
在 OpenCV 3.0 中,被取消。这个模块包含一些老的尚未被完全取消的东西。
ocl
在OpenCV 3.0 中,被取消,取而代之的是 T-API。这是一个较新的模块,可以认为它和 GPU 模块相似,它实现了开放并行编程的 Khronos OpenCL 标准。虽然现在模块的特性比 GPU 模块少很多,但 ocl 模块的目标是提供可以运行在任何 GPU 或者是其他可以搭载 Khronos 的并行设备。这与 GPU 模 块形成了鲜明的对比,后者使用 Nividia CUDA 工具包进行开发,因此只能在 Nividia GPU 设备上工作。
小例子
图像腐蚀
/**
* 图像腐蚀
**/
void erodeImage() {
Mat srclmage = imread(image);
imshow("[ 原图 ] ",srclmage);
//进行腐蚀操作
//getStructuringElement函数的返回值为指定形状和尺寸的结构元素(内核矩阵〉
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
Mat dstlmage;
erode(srclmage, dstlmage, element);
//显示效果图
imshow ("[ 效果图 ] ", dstlmage);
waitKey(0);
}
image.png
图像模糊
/**
* 图像模糊
**/
void blurImage()
{
Mat srclmage = imread(image);
imshow("[ 原图 ] ", srclmage);
//进行均值滤波操作
Mat dstlmage;
blur(srclmage, dstlmage, Size(7, 7));
imshow("[ 效果图 ] ", dstlmage);
waitKey(0);
}
读取视频
实现视频播放的效果
/**
* 读取视频
* build : g++ sample2.cpp -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_imgcodecs -lopencv_videoio
*/
void readVideo() {
//读入视频
VideoCapture capture("/home/mytestvideo/dog3.mp4");
//循环显示每一帧
while(1)
{
//定义一个Mat变量,用于储存每一帧的图像
Mat frame;
//读取当前帧
capture >> frame;
if (frame.empty()) {
cout << "frame empty!" << endl;
break;
} else {
//显示当前帧
imshow("读取视频",frame);
}
waitKey(30);//延时30ms
}
}
人脸检测
void Pic2Gray(Mat camerFrame,Mat &gray)
{
//普通台式机3通道BGR,移动设备为4通道
if (camerFrame.channels() == 3)
{
cvtColor(camerFrame, gray, CV_BGR2GRAY);
}
else if (camerFrame.channels() == 4)
{
cvtColor(camerFrame, gray, CV_BGRA2GRAY);
}
else
gray = camerFrame;
}
void faceCheck() {
//加载Haar或LBP对象或人脸检测器
CascadeClassifier faceDetector;
std::string faceCascadeFilename = "./haarcascade_frontalface_default.xml";
//友好错误信息提示
try{
faceDetector.load(faceCascadeFilename);
}
catch (cv::Exception e){}
if (faceDetector.empty())
{
std::cerr << "脸部检测器不能加载 (";
std::cerr << faceCascadeFilename << ")!" << std::endl;
exit(1);
}
//读取视频
//绝对路径,相对路径不行
VideoCapture video("/home/mp4/girls.avi");
while (true)
{
Mat frame;
video >> frame;
if (frame.empty())
{
std::cerr << "读取视频失败" << std::endl;
getchar();
exit(1);
}
Mat displayedFrame(frame.size()/2,CV_8UC3);
//人脸检测只试用于灰度图像
Mat gray;
Pic2Gray(frame, gray);
//直方图均匀化(改善图像的对比度和亮度)
Mat equalizedImg;
equalizeHist(gray, equalizedImg);
//人脸检测用Cascade Classifier::detectMultiScale来进行人脸检测
int flags = CASCADE_FIND_BIGGEST_OBJECT|CASCADE_DO_ROUGH_SEARCH; //只检测脸最大的人
//int flags = CASCADE_SCALE_IMAGE; //检测多个人
Size minFeatureSize(30, 30);
float searchScaleFactor = 1.1f;
int minNeighbors = 4;
std::vector faces;
faceDetector.detectMultiScale(equalizedImg, faces, searchScaleFactor, minNeighbors, flags, minFeatureSize);
//画矩形框
cv::Mat face;
cv::Point text_lb;
for (size_t i = 0; i < faces.size(); i++)
{
if (faces[i].height > 0 && faces[i].width > 0)
{
face = gray(faces[i]);
text_lb = cv::Point(faces[i].x, faces[i].y);
cv::rectangle(equalizedImg, faces[i], cv::Scalar(255, 0, 0), 1, 8, 0);
cv::rectangle(gray, faces[i], cv::Scalar(255, 0, 0), 1, 8, 0);
cv::rectangle(frame, faces[i], cv::Scalar(255, 0, 0), 1, 8, 0);
}
}
imshow("直方图均匀化", equalizedImg);
imshow("灰度化", gray);
imshow("原图", frame);
waitKey(20);
}
getchar();
}
image.png