> 技术文档 > OpenCV的常用用法(C++版)_c++ opencv

OpenCV的常用用法(C++版)_c++ opencv


OpenCV的常用用法(C++版)

一、简介

OpenCV是一个基于Apache2.0许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。 它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。

OpenCV用C++语言编写,它具有C ++,Python,Java和MATLAB接口,并支持Windows,Linux,Android和Mac OS,OpenCV主要倾向于实时视觉应用,并在可用时利用MMX和SSE指令, 如今也提供对于C#、Ch、Ruby,GO的支持。

二、OpenCV的基本操作

(1)OpenCV包含的头文件

#include //图像的读取和写入#include//创建图形用户界面#include//图像处理的函数#include//包含了关于opencv的所有库

(2)OpenCV查看图片

int main() {string path = \"Resources/test.png\";Mat img = imread(path); //在OpenCV中图片格式通常使用Mat保存namedWindow(\"Image\");//新建图形化窗口imshow(\"Image\", img);//图片展示waitKey(6000);//图片展示的时长return 0;}

(3)OpenCV查看视频

int main() {string path = \"Resources/test_video.mp4\";VideoCapture cap(path);//一个通用的类,用于从视频或者摄像头中获取视频帧Mat img; //持续循环,用来接收视频帧并且在窗口显示while (true) {cap.read(img);//使用read方法将视频帧保存到img中imshow(\"Image\", img);//显示每帧图片waitKey(20);//每帧图片显示时长为20ms}return 0;}

(4)OpenCV查看摄像头

int main() {VideoCapture cap(0);//调用摄像头编号为0的摄像头Mat img;while (true) {cap.read(img);imshow(\"Image\", img);waitKey(1);}return 0;}

(5)改变图片颜色

void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );--返回值:无--参数: --InputArray src:传入的图片名称 --OutputArray dst:传出的图片名称 --int code:需要改变的颜色,例如灰色为:COLOR_BGR2GRAY

(6)高斯模糊

void GaussianBlur( InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY );--返回值:无--参数:: --InputArray src:传入的图片名称 --OutputArray dst:传出的图片名称 --Size ksize:高斯核,通常取0-9,越高越模糊 --double sigmaX, double sigmaY:x和y方向上的标准差

(7)边缘检测

void Canny( InputArray image, OutputArray edges, double threshold1, double threshold2)--返回值:无--参数: --InputArray image:传入的图片名称 --OutputArray edges:传出的图片名称 --double threshold1, double threshold2:二者的取值会决定边缘的清晰与否(15,75

(8)膨胀(由于在进行边缘检测时可能在某些边缘会断开,经过膨胀会连在一起)

void dilate( InputArray src, OutputArray dst, InputArray kernel)--返回值:无--参数: --InputArray image:传入的图片名称 --OutputArray edges:传出的图片名称 --InputArray kernel:结构元素,定义如下: Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5))

(9)腐蚀(经过膨胀后的图像经过腐蚀线条会变细,这样断开的边缘会连接在一块)

void erode( InputArray src, OutputArray dst, InputArray kernel)--返回值:无--参数: --InputArray image:传入的图片名称 --OutputArray edges:传出的图片名称 --InputArray kernel:结构元素,定义如下: Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5))

(10)重新定义大小

void resize( InputArray src, OutputArray dst,Size dsize,double fx = 0, double fy = 0--返回值:无--参数: --InputArray image:传入的图片名称 --OutputArray edges:传出的图片名称 --Size dsize:size();如果有具体的数字在括号里输入 --double fx = 0, double fy = 0:如果没有具体的数字,后面两位是按照比例进行缩放

(11)裁剪

Rect roi(200, 100, 300, 300);//定义的要裁剪的形状,前两个元素分别是起始位置的坐标,后两个则是分别向右和向下偏移的距离,这是个矩形的裁剪框imgCrop = img(roi);//裁剪

(12)自行绘制图片的过程

//绘制一个白色的背景(颜色可以根据后面的数值改变Mat img(512, 512, CV_8UC3, Scalar(255, 255, 255));//在这张白纸上绘制一个圆circle(img, Point(256, 256), 155, Scalar(0, 244, 234), -1);//point是圆心,155是半径,scalar是颜色,10是粗细,-1或FILLED是填充//绘制一个矩形rectangle(img, Point(130, 226), Point(382, 286), Scalar(0, 0, 255), -1);//第二个参数为左上顶点,第三个参数为右下顶点//绘制一条线line(img, Point(130, 296), Point(382, 296), Scalar(0, 0, 255), 2);//输出一些文字putText(img, \"hello world\", Point(180, 260), FONT_HERSHEY_DUPLEX, 0.75, Scalar(0, 69, 0), 2);imshow(\"Image\", img);waitKey(0);

(13)图片透视(简单点说就是将一张非平铺的图片输出为平铺)

Point2f src[4] = { {777,107},{1021,82},{840,359},{1117,337} };//这个就是定义在图中的四个点的像素点Point2f dst[4] = { {0.0f,0.0f},{w,0.0f},{0.0f,h},{w,h} };//这是我们希望经过透视之后图的四个像素点matrix = getPerspectiveTransform(src, dst);//透视变换矩阵warpPerspective(img, imgWarp, matrix, Point(w, h));//对原图像进行透视变换//在原图像上标注出四个顶点位置for (int i = 0; i < 4; i++) {circle(img, src[i], 10, Scalar(0, 0, 255), -1);

(14)颜色检测(这段代码是需要手动来确定图片的色调、饱和度和明度)

cvtColor(img, imgHSV, COLOR_BGR2HSV);//创建6个滑动窗口,用来调节HSV(以便找到合适的颜色范围)namedWindow(\"Trackbars\", (640, 200));createTrackbar(\"Hue Min\", \"Trackbars\", &hmin, 179);createTrackbar(\"Hue Max\", \"Trackbars\", &hmax, 179);createTrackbar(\"Sat Min\", \"Trackbars\", &smin, 255);createTrackbar(\"Sat Max\", \"Trackbars\", &smax, 255);createTrackbar(\"Val Min\", \"Trackbars\", &vmin, 255);createTrackbar(\"Val Max\", \"Trackbars\", &vmax, 255);while (true) {Scalar lower(hmin, smin, vmin);//像素的下限Scalar upper(hmax, smax, vmax);//像素的上限inRange(imgHSV, lower, upper, mask);//在这个像素范围内选取imshow(\"Image\", img);imshow(\"Image HSV\", imgHSV);imshow(\"Image mask\", mask);waitKey(1);}waitKey(0);

(14)轮廓检测

void getContours(Mat imgDil, Mat img) {//这个二维数组的目的是存储找到的轮廓,二维数组中第一个参数为第i个轮廓,第二个参数表示该轮廓所对应的点vector<vector<Point>> contours;//轮廓的层次结构,这个类型共有四层结构vector<Vec4i> hierarchy;//使用函数查找轮廓findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); /* void findContours( InputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset = Point()) --返回值:无 --参数: --InputArray image:输入图片的名称 --OutputArrayOfArrays contours:保存轮廓的二维数组 --OutputArray hierarchy:轮廓的层次结构 --int mode:存储的模式,在这里只存储最外层轮廓 --int method:轮廓点的模式,在这里存储关键轮廓点 */ //该数组用来存储逼近后的近似多边形vector<vector<Point>> conPoly(contours.size()); //该数组同来存储图形所对应形状的顶点vector<Rect> boundRect(contours.size()); //遍历每一个轮廓,这样可以有根据不同的需求来选择for (int i = 0; i < contours.size(); i++) { //计算每个轮廓的面积int area = contourArea(contours[i]);//定义轮廓类型,便于添加文字到边界框string objectType; //轮廓面积>1000才绘制if (area > 1000) {//求每个图形的周长float peri = arcLength(contours[i], true);//以指定的精度近似多边形曲线。第二个参数conPloy[i]存储近似的结果,是输出。approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);boundRect[i] = boundingRect(conPoly[i]);//计算边界矩形//找近似多边形的角点,三角形有3个角点,矩形/正方形有4个角点,圆形>4个角点int objCor = (int)conPoly[i].size(); //如果是三个顶点,认为是三角形if (objCor == 3) { objectType = \"Tri\"; } //四个角点进一步判断是正方形还是长方形 else if (objCor == 4) {float aspRatio = (float)boundRect[i].width / (float)boundRect[i].height;//宽高比if (aspRatio > 0.95 && aspRatio < 1.05) { objectType = \"Square\"; }else objectType = \"Rect\";}//如果顶点大于4个判断其为原形else if (objCor > 4) { objectType = \"Circle\"; }//drawContours(img, conPoly, i, Scalar(255, 0, 255), 2);//绘制边界矩形rectangle(img, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 5);//添加标注,boundRect[i].y-5 是为了将文字房子框的上方putText(img, objectType, { boundRect[i].x,boundRect[i].y - 5 }/*文字坐标*/, FONT_HERSHEY_PLAIN, 1, Scalar(0, 69, 255), 1);}}}

(15)人脸检测

/*实现人脸检测的具体步骤:①创建一个用于人脸检测的CascadeClassifier对象②加载存储在XML文件中的Haar特征分类器。该文件包含预训练的分类器用于人脸检测。③检查分类器是否成功加载。如果未成功加载,则输出错误信息。④创建一个向量用于存储检测到的脸部矩形区域⑤使用imread函数读取图像⑥使用分类器的detectMultiScale函数检测图像中的人脸⑦使用rectangle函数在检测到的每个脸部周围绘制矩形框*///创建一个用于人脸检测的CascadeClassifier对象CascadeClassifier faceCascade;//加载存储在XML文件中的Haar特征分类器。该文件包含预训练的分类器用于人脸检测faceCascade.load(\"Resources/haarcascade_frontalface_default.xml\");//检查分类器是否成功加载。如果未成功加载,则输出错误信息。if (faceCascade.empty()) { cout << \"脸部识别加载失败\" << endl;}//创建一个向量用于存储检测到的脸部矩形区域vector<Rect> faces;//使用imread函数读取图像Mat img = imread(\"path_to_image.jpg\"); // 替换为实际的图像路径//使用分类器的detectMultiScale函数检测图像中的人脸faceCascade.detectMultiScale(img, faces, 1.1, 10);/*参数:--img:输入图像。--faces:用于存储检测到的脸部矩形的向量。--1.1:每次图像尺寸减小的比例因子。--10:每个候选矩形应保持的最低近邻数(较高的值意味着只有目标完全位于矩形内才会被检测)。*///使用rectangle函数在检测到的每个脸部周围绘制矩形框for (int i = 0; i < faces.size(); i++) { rectangle(img, faces[i].tl(), faces[i].br(), Scalar(255, 0, 255), 3);}

三、总结

上面的内容为OpenCV的一些基本操作,如果只是需要简单的使用OpenCV来完成一些功能,应该已经足够;如果需要使用OpenCV完成更加复杂的图像操作,需要更加深入的去了解CV算法的相关内容。