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

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<opencv2/imgcodecs.hpp> //图像的读取和写入
#include<opencv2/highgui.hpp>//创建图形用户界面
#include<opencv2/imgproc.hpp>//图像处理的函数
#include<opencv2/opencv.hpp>//包含了关于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算法的相关内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值