【OpenCV(C++)快速入门】--opencv学习

news2025/1/18 23:36:11

0 配置环境

配置环境网上很多资料,这里就不赘述了。

笔者使用的是VS2022+opencv4.9.0

测试配置环境

// 打开摄像头样例
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/imgproc/imgproc.hpp>  
#include <opencv2/imgcodecs/imgcodecs.hpp>
#include <opencv2/core/core.hpp>  
using namespace cv;

int main()
{
	VideoCapture cap(0);
	Mat frame;
	while (1)
	{
		cap >> frame;
		imshow("调用摄像头", frame);
		waitKey(30);
	}
	return 0;
}

如果配置正确,会调用电脑摄像头

1 读图片和视频

读图片

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
#include <string>


 images ///
int main()
{
	std::string path = "Resources/test.png";		// 图片路径
	cv::Mat img = cv::imread(path);					// 读数据
	cv::imshow("Image", img);						// 显示数据
	cv::waitKey(0);									// 增加延时,0表示无穷
	return 0;
}

读视频

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
#include <string>


 video ///
// 视频是一系列的图像,因此需要遍历所有的图像/帧,捕获并且显示
int main()
{
	std::string path = "Resources/test_video.mp4";	// 视频路径
	cv::VideoCapture capture(path);
	cv::Mat img;
	while (1)
	{
		capture.read(img);							// 读到img中
		cv::imshow("Vedio", img);					// 显示
		cv::waitKey(20);							// 延时20ms,数值越大,视频越慢
	}
	return 0;
}

读相机

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
#include <string>



 Webcam ///
// 视频是一系列的图像,因此需要遍历所有的图像/帧,捕获并且显示
int main()
{
	cv::VideoCapture capture(0);					// 只有一个相机
	cv::Mat img;
	while (1)
	{
		capture.read(img);							// 读到img中
		cv::imshow("Vedio", img);					// 显示
		cv::waitKey(1);								// 延时1ms,数值越大,视频越慢
	}
	return 0;
}

2 基本函数

cvtColor

// cvt是convert的缩写,将图像从一种颜色空间转换为另一种颜色空间
// 把img转换成imgGray
cv::cvtColor(img, imgGray, cv::COLOR_BGR2GRAY);
  • img:输入图像,这是一个BGR格式的彩色图像。

  • imgGray:输出图像,转换后的灰度图像。

  • cv::COLOR_BGR2GRAY:转换代码,表示将BGR格式的图像转换为灰度图像。

GaussianBlur

高斯模糊处理

// 使用高斯滤波器模糊图像。该函数将源图像与指定的高斯核进行卷积,Size(7,7)是核大小,数字越大越模糊
// 把img模糊成imgBlur
cv::GaussianBlur(img, imgBlur, cv::Size(7, 7), 5, 0);
  • cv::GaussianBlur是OpenCV中的一个函数,用于对图像进行高斯模糊处理。高斯模糊是一种图像处理技术,通过使用高斯核对图像进行卷积,可以有效地减少图像的噪声和细节,使图像变得模糊。

  • 参数解释

    • img:输入图像,这是一个cv::Mat类型的对象,表示要进行高斯模糊处理的图像。

    • imgBlur:输出图像,经过高斯模糊处理后的图像,也是一个cv::Mat类型的对象。

    • cv::Size(7, 7):高斯核的大小,表示高斯核的宽度和高度。这里使用7×7的高斯核。高斯核的大小必须是正奇数,以确保核的中心能够对准图像的每个像素。

    • 5:高斯核的标准差(σ)在X方向上的值。标准差越大,模糊效果越明显。如果设置为0,OpenCV会根据高斯核的大小自动计算标准差。

    • 0:高斯核的标准差(σ)在Y方向上的值。如果设置为0,OpenCV会使用与X方向相同的标准差。

Canny

边缘检测

// 边缘检测,阈值1,2可调,目的:显示更多的边缘,使用模糊的图像
cv::Canny(imgBlur, imgCanny, 25, 75);
  • cv::Canny是OpenCV中的一个函数,用于执行Canny边缘检测算法。Canny边缘检测是一种多步骤的算法,包括高斯模糊、梯度计算、非极大值抑制和双阈值检测等步骤。

  • 参数解释

    • imgBlur:输入图像,这是一个经过高斯模糊处理的cv::Mat类型的对象。高斯模糊处理可以减少图像的噪声,使边缘检测更加准确。

    • imgCanny:输出图像,经过Canny边缘检测后的图像,也是一个cv::Mat类型的对象。输出图像是一个二值图像,边缘部分的像素值为255,非边缘部分的像素值为0。

    • 25:低阈值(threshold1),用于Canny边缘检测中的双阈值检测。低阈值用于确定弱边缘。

    • 75:高阈值(threshold2),用于Canny边缘检测中的双阈值检测。高阈值用于确定强边缘。

dilate和erode

膨胀和侵蚀

// 扩大和侵蚀图像
// 创建一个核,增加Size(只能是奇数)会扩张/侵蚀更多
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
cv::dilate(imgCanny, imgDila, kernel);			// 扩张边缘,增加边缘厚度
cv::erode(imgDila, imgErode, kernel);			// 侵蚀边缘,减小边缘厚度
  • cv::getStructuringElement

    • cv::getStructuringElement是OpenCV中的一个函数,用于创建形态学操作的结构元素(也称为核或掩模)。

  • 参数解释

    • cv::MORPH_RECT:指定结构元素的形状为矩形。

    • cv::Size(3, 3):指定结构元素的大小为3×3。这意味着结构元素是一个3×3的矩形,中心像素为(1, 1)。

  • cv::dilate

    • cv::dilate是OpenCV中的一个函数,用于对图像进行膨胀操作。膨胀操作可以扩大图像中的白色区域,通常用于连接断开的部分或填补小孔。

  • 参数解释

    • imgCanny:输入图像,这是一个经过Canny边缘检测的二值图像。

    • imgDila:输出图像,经过膨胀操作后的图像。

    • kernel:结构元素,用于定义膨胀操作的邻域。

  • cv::erode

    • cv::erode是OpenCV中的一个函数,用于对图像进行腐蚀操作。腐蚀操作可以缩小图像中的白色区域,通常用于去除小的噪点或分离粘连的部分。

  • 参数解释

    • imgDila:输入图像,这是一个经过膨胀操作的图像。

    • imgErode:输出图像,经过腐蚀操作后的图像。

    • kernel:结构元素,用于定义腐蚀操作的邻域。

总体代码

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

 basic functions ///
int main()
{
	std::string path = "Resources/test.png";		// 图片路径
	cv::Mat img = cv::imread(path);					// 读数据
	cv::Mat imgGray, imgBlur, imgCanny, imgDila, imgErode;

	// cvt是convert的缩写,将图像从一种颜色空间转换为另一种颜色空间
	// 把img转换成imgGray
	cv::cvtColor(img, imgGray, cv::COLOR_BGR2GRAY);

	// 使用高斯滤波器模糊图像。该函数将源图像与指定的高斯核进行卷积,Size(7,7)是核大小,数字越大越模糊
	// 把img模糊成imgBlur
	cv::GaussianBlur(img, imgBlur, cv::Size(7, 7), 5, 0);

	// 边缘检测,阈值1,2可调,目的:显示更多的边缘,使用模糊的图像
	cv::Canny(imgBlur, imgCanny, 25, 75);

	// 扩大和侵蚀图像
	// 创建一个核,增加Size(只能是奇数)会扩张/侵蚀更多
	cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
	cv::dilate(imgCanny, imgDila, kernel);			// 扩张边缘,增加边缘厚度
	cv::erode(imgDila, imgErode, kernel);			// 侵蚀边缘,减小边缘厚度


	cv::imshow("Image", img);						// 显示数据
	cv::imshow("Image Gray", imgGray);				// 显示灰色数据
	cv::imshow("Image Blur", imgBlur);				// 显示模糊数据
	cv::imshow("Image Canny", imgCanny);			// 显示边缘检测数据
	cv::imshow("Image imgDila", imgDila);			// 显示扩张边缘数据
	cv::imshow("Image imgErode", imgErode);			// 显示侵蚀检测数据


	cv::waitKey(0);									// 增加延时,0表示无穷
	return 0;
}

测试

3 resize and crop

调整图片和裁剪图片

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace std;
using namespace cv;


 resize and crop ///

int main(int argc, char** argv)
{
	string path = "Resources/test.png";		// 图片路径
	cv::Mat img = cv::imread(path);			// 读图片
	cv::Mat imgResize, imgCrop;				// 调整图片和裁剪图片

	// [768 x 559]
	//std::cout << img.size() << std::endl;
	// 调整大小
	//cv::resize(img, imgResize, Size(), 0.5, 0.5);  // 长宽各自缩小0.5
	cv::resize(img, imgResize, Size(680, 400));		 // 缩小到680*400

	// 裁剪
	// 从200*100处开始裁剪,各自裁剪300
	cv::Rect rect(200, 100, 300, 300);
	imgCrop = img(rect);

	// 显示
	cv::imshow("Image", img);
	cv::imshow("Image Resize", imgResize);
	cv::imshow("Image Crop", imgCrop);

	cv::waitKey(0);									// 增加延时,0表示无穷
	return 0;
}

测试

4 Draw shapes and Text

#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>

using namespace std;
using namespace cv;


 Draw shapes and Text ///

int main(int argc, char** argv)
{
	// blank image
	// 8bit3通道,白色
	cv::Mat img(512, 512, CV_8UC3, cv::Scalar(255, 255, 255));

	// 基于上图画一个圆,圆心在(256,256)处,半径是155,颜色是0, 69, 255,厚度是10
	// cv::circle(img, cv::Point(256, 256), 155, cv::Scalar(0, 69, 255), 10);
	cv::circle(img, cv::Point(256, 256), 155, cv::Scalar(0, 69, 255), FILLED);	// 填充

	// 画一个矩形
	// 左上角是(130, 226),右下角是(382, 286)
	// 颜色是cv::Scalar(255, 255, 255),厚度是3
	//cv::rectangle(img, cv::Point(130, 226), cv::Point(382, 286), cv::Scalar(255, 255, 255), 3);
	cv::rectangle(img, cv::Point(130, 226), cv::Point(382, 286), cv::Scalar(255, 255, 255), FILLED);

	// 画一条线
	cv::line(img, Point(130, 296), cv::Point(382, 296), cv::Scalar(255, 255, 255), 2);
	//cv::line(img, Point(130, 296), cv::Point(382, 450), cv::Scalar(255, 255, 255), 2);

	// 本文
	// FONT_HERSHEY_DUPLEX字体,0.75是比例
	cv:putText(img, "StudyWinter", cv::Point(160, 262), 
						cv::FONT_HERSHEY_DUPLEX, 0.75, cv::Scalar(0, 69, 255));


	cv::imshow("Image", img);

	cv::waitKey(0);
	return 0;
}

测试

5 wrap images

图像扭曲

#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>

using namespace std;
using namespace cv;


 wrap images ///
float w = 250, h = 350;
cv::Mat matrix, imgWrap;

int main(int argc, char** argv)
{
	string path = "Resources/cards.jpg";			// 图片路径
	cv::Mat img = cv::imread(path);					// 读数据

	cv::Point2f src[4] = { {529, 142}, {771, 190}, {405, 395}, {674, 457} };
	cv::Point2f dst[4] = { {0.0f, 0.0f}, {w, 0.0f}, {0.0f, h}, {w, h} };

	 使用圆圈,取四个点在图中标记,放在这里转换后图片有圆
	//for (int i = 0; i < 4; i++)
	//{
	//	cv::circle(img, src[i], 10, cv::Scalar(0, 0, 255), FILLED);
	//}

	// 转换
	matrix = getPerspectiveTransform(src, dst);
	cv::warpPerspective(img, imgWrap, matrix, cv::Point(w, h));

	// 使用圆圈,取四个点在图中标记
	for (int i = 0; i < 4; i++)
	{
		cv::circle(img, src[i], 10, cv::Scalar(0, 0, 255), FILLED);
	}

	cv::imshow("Image", img);						// 显示数据
	cv::imshow("Image Warp", imgWrap);				// 显示数据

	cv::waitKey(0);
	return 0;
}

这段代码的主要功能是读取一张图像,定义四个源点和对应的目标点,计算透视变换矩阵,对图像进行透视变换,并在源图像中标记源点,最后显示原始图像和变换后的图像。通过这种方式,可以将图像中的某个区域(如一张卡片)从任意角度变换为正视图。

测试

6 Color detection

test1

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
#include <string>


 Color detection ///
cv::Mat imgHSV, mask;
// h色调 s饱和度 v明度
int hmin = 0, smin = 110, vmin = 153;
int hmax = 19, smax = 240, vmax = 255;

int main()
{
	std::string path = "Resources/lambo.png";		// 图片路径
	cv::Mat img = cv::imread(path);					// 读数据
	// 颜色转换
	cv::cvtColor(img, imgHSV, cv::COLOR_BGR2HSV);

	// 创建窗口
	cv::namedWindow("Trackbars");
	// 创建跟踪栏
	cv::createTrackbar("Hue Min", "Trackbars", &hmin, 179);
	cv::createTrackbar("Hue Max", "Trackbars", &hmax, 179);
	cv::createTrackbar("Sat Min", "Trackbars", &smin, 255);
	cv::createTrackbar("Sat Max", "Trackbars", &smax, 255);
	cv::createTrackbar("Val Min", "Trackbars", &vmin, 255);
	cv::createTrackbar("Val Max", "Trackbars", &vmax, 255);


	while (1)
	{
		// 定义标量
		cv::Scalar lower(hmin, smin, vmin);
		cv::Scalar upper(hmax, smax, vmax);
		cv::inRange(imgHSV, lower, upper, mask);


		cv::imshow("Image", img);						// 显示数据
		cv::imshow("image HSV", imgHSV);				// 显示数据
		cv::imshow("image Mask", mask);					// 显示数据

		cv::waitKey(0);									// 增加延时,0表示无穷
	}
	return 0;
}

这段代码的主要功能是读取一张图像,将其从BGR颜色空间转换为HSV颜色空间,通过创建跟踪栏动态调整HSV颜色空间中的阈值,生成掩码图像,并显示原始图像、HSV图像和掩码图像。通过调整跟踪栏,可以实时看到不同阈值下检测到的颜色区域。

7 形状轮廓检测

这小节,将会通过OpenCV提供的函数进行,简单的形状检测,并给检测出来的形状添加boundingbox。整个过程的流程如下图所示:

图像的预处理阶段,实质上就是通过灰度处理、高斯模糊、边缘检测然后再加粗边缘得到一个二值化的图像,便于边界检测函数进行检测。

#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>

  ///


int main(int argc, char** argv)
{
	std::string path = "Resources/shapes.png";		// 图片路径
	cv::Mat img = cv::imread(path);					// 读数据

	// 预处理
	// cvt是convert的缩写,将图像从一种颜色空间转换为另一种颜色空间。
	cv::Mat imgGray, imgBlur, imgCanny, imgDil;
	cv::cvtColor(img, imgGray, cv::COLOR_BGR2GRAY);
	// 使用高斯滤波器模糊图像。该函数将源图像与指定的高斯核进行卷积,Size(7,7)是核大小,数字越大越模糊
	cv::GaussianBlur(imgGray, imgBlur, cv::Size(3, 3), 3, 0);
	// 边缘检测,阈值1,2可调,目的:显示更多的边缘
	cv::Canny(imgBlur, imgCanny, 25, 75);
	// 创建一个核,增加Size(只能是奇数),会扩张/侵蚀更多
	cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
	cv::dilate(imgCanny, imgDil, kernel);

	cv::imshow("Image", img);
	cv::imshow("Image Gray", imgGray);
	cv::imshow("Image Blur", imgBlur);
	cv::imshow("Image Canny", imgCanny);
	cv::imshow("Image dilate", imgDil);


	cv::waitKey(0);
	return 0;
}

测试

图片预处理之后,便可以进行形状检测了,需要使用到以下的函数:

void findContours(InputArray image, OutputArrayOfArrays contours,
                              OutputArray hierarchy, int mode,
                              int method);

InputArray image :这需要我们预处理之后得到的二值化图像(8bit单通道图像);

OutputArrayOfArrays contours:这是函数的输出,它是std::vector<vector> 类型的,可以看成是一个存储多个向量的组。每一个向量代表一个形状。

OutputArray hierarchy:该变量存储了contours中对应元素的相关拓扑信息,其类型为std::vector< cv::Vec4i > 。Vec4i 即 std::vector<int, 4>类型。

int mode,int method :这里的mode 和 method是指形状检测的模式和方法,OpenCV提供了多种的模式和方法,这里不细讲,详细的可以去官网查一下。

#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <vector>
#include <iostream>

  ///

// imgDil是传入的扩张边缘的图像用来查找轮廓,img是要在其上绘制轮廓的图像
void getContours(cv::Mat imgDil, cv::Mat img)
{
	// 轮廓检测到的轮廓。每个轮廓线存储为一个点的向量
	std::vector<std::vector<cv::Point>> contours;
	// 包含关于映像拓扑的信息  typedef Vec<int, 4> Vec4i;具有4个整数值
	std::vector<cv::Vec4i> hierarchy;
	// 在二值图像中查找轮廓
	cv::findContours(imgDil, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
	// 获得提取的轮廓以后,通过下面的函数将检测到的轮廓在图上表示出来
	// 其中 -1 表示把全部检测到的轮廓都输出, 向量Scalar(255, 0, 255) 表示颜色, 2 表示轮廓厚度
	cv::drawContours(img, contours, -1, cv::Scalar(255, 0, 255), 2);

}


int main(int argc, char** argv)
{
	std::string path = "Resources/shapes.png";		// 图片路径
	cv::Mat img = cv::imread(path);					// 读数据

	// 预处理
	// cvt是convert的缩写,将图像从一种颜色空间转换为另一种颜色空间。
	cv::Mat imgGray, imgBlur, imgCanny, imgDil;
	cv::cvtColor(img, imgGray, cv::COLOR_BGR2GRAY);
	// 使用高斯滤波器模糊图像。该函数将源图像与指定的高斯核进行卷积,Size(7,7)是核大小,数字越大越模糊
	cv::GaussianBlur(imgGray, imgBlur, cv::Size(3, 3), 3, 0);
	// 边缘检测,阈值1,2可调,目的:显示更多的边缘
	cv::Canny(imgBlur, imgCanny, 25, 75);
	// 创建一个核,增加Size(只能是奇数),会扩张/侵蚀更多
	cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
	cv::dilate(imgCanny, imgDil, kernel);

	// 形状检测
	getContours(imgDil, img);

	cv::imshow("Image", img);
	//cv::imshow("Image Gray", imgGray);
	//cv::imshow("Image Blur", imgBlur);
	//cv::imshow("Image Canny", imgCanny);
	//cv::imshow("Image dilate", imgDil);

	cv::waitKey(0);
	return 0;
}

测试

不难发现,图像中的所有形状都被检测出来了,因为这张图像是比较理想情况,如果图像中出现一些噪点(例如图像中右上角的小黑圆圈),很可能也会被检测出来,这是不想看到的,这个时候,需要采取一些手段来去除这些噪点,这里提供一种根据形状图像面积过滤小形状的方法:

#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <vector>
#include <iostream>

  ///

// imgDil是传入的扩张边缘的图像用来查找轮廓,img是要在其上绘制轮廓的图像
void getContours(cv::Mat imgDil, cv::Mat img)
{
	// 轮廓检测到的轮廓。每个轮廓线存储为一个点的向量
	std::vector<std::vector<cv::Point>> contours;
	// 包含关于映像拓扑的信息  typedef Vec<int, 4> Vec4i;具有4个整数值
	std::vector<cv::Vec4i> hierarchy;
	// 在二值图像中查找轮廓
	cv::findContours(imgDil, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
	// 获得提取的轮廓以后,通过下面的函数将检测到的轮廓在图上表示出来
	// 其中 -1 表示把全部检测到的轮廓都输出, 向量Scalar(255, 0, 255) 表示颜色, 2 表示轮廓厚度
	//cv::drawContours(img, contours, -1, cv::Scalar(255, 0, 255), 2);

	// 根据形状图像面积过滤小形状
	for (int i = 0; i < contours.size(); i++)
	{
		// 获取每个形状的面积
		double area = cv::contourArea(contours[i]);
		if (area - 15000 > 0.00000001 || area - 15000 > -0.00000001)
		{
			// 输出
			cv::drawContours(img, contours, i, cv::Scalar(255, 0, 255), 2);
		}
	}

}


int main(int argc, char** argv)
{
	std::string path = "Resources/shapes.png";		// 图片路径
	cv::Mat img = cv::imread(path);					// 读数据

	// 预处理
	// cvt是convert的缩写,将图像从一种颜色空间转换为另一种颜色空间。
	cv::Mat imgGray, imgBlur, imgCanny, imgDil;
	cv::cvtColor(img, imgGray, cv::COLOR_BGR2GRAY);
	// 使用高斯滤波器模糊图像。该函数将源图像与指定的高斯核进行卷积,Size(7,7)是核大小,数字越大越模糊
	cv::GaussianBlur(imgGray, imgBlur, cv::Size(3, 3), 3, 0);
	// 边缘检测,阈值1,2可调,目的:显示更多的边缘
	cv::Canny(imgBlur, imgCanny, 25, 75);
	// 创建一个核,增加Size(只能是奇数),会扩张/侵蚀更多
	cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
	cv::dilate(imgCanny, imgDil, kernel);

	// 形状检测
	getContours(imgDil, img);

	cv::imshow("Image", img);
	//cv::imshow("Image Gray", imgGray);
	//cv::imshow("Image Blur", imgBlur);
	//cv::imshow("Image Canny", imgCanny);
	//cv::imshow("Image dilate", imgDil);

	cv::waitKey(0);
	return 0;
}

测试

添加此函数以后,可以看到,面积小于15000的没有被表示出来。

8 检测人脸

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/objdetect.hpp>
#include <iostream>

 Webcam ///
// 视频是一系列的图像,因此需要遍历所有的图像/帧,捕获并且显示


int main()
{
	cv::VideoCapture capture(0);					// 只有一个相机
	cv::Mat img;
	while (1)
	{
		capture.read(img);							// 读到img中

		// opencv提供的分类器
		cv::CascadeClassifier faceCascade;
		// 从加载模型(已经训练好的)
		faceCascade.load("Resources/haarcascade_frontalface_default.xml");
		// 检测文件是否加载成功
		if (faceCascade.empty())
		{
			std::cout << "XML file not loaded" << std::endl;
		}
		// 定义用于接收检测结果的
		std::vector<cv::Rect> faces;

		// 在输入图像中检测不同大小的对象,检测到的对象以矩形的列表的形式返回
		// 通过增加最近邻的值可以消除误报,但是过大将会导致漏检测
		// img/*输入*/, faces/*输出*/, 1.1/*比例因子*/, 3/*最近邻*/
		faceCascade.detectMultiScale(img, faces, 1.1, 3);

		// 绘制矩形
		for (int i = 0; i < faces.size(); i++)
		{
			cv::rectangle(img, faces[i].tl(), faces[i].br(), cv::Scalar(255, 0, 255), 3);
		}


		cv::imshow("Vedio", img);					// 显示
		cv::waitKey(1);								// 延时1ms,数值越大,视频越慢
	}
	return 0;
}

自行测试

学习:4h上手C++版Opencv_哔哩哔哩_bilibili

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2278681.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python编程与在线医疗平台数据挖掘与数据应用交互性研究

一、引言 1.1 研究背景与意义 在互联网技术飞速发展的当下,在线医疗平台如雨后春笋般涌现,为人们的就医方式带来了重大变革。这些平台打破了传统医疗服务在时间和空间上的限制,使患者能够更加便捷地获取医疗资源。据相关报告显示,中国基于互联网的医疗保健行业已进入新的…

网安快速入门之Windows命令

在Windows中 我们今天介绍几个命令&#xff1a; help copy dir cd type del ipconfig net netstat tasklist sc1. help 显示命令的帮助信息。或者显示Windows内置命令。 常用参数&#xff1a; <命令>&#xff1a;查看指定命令的帮助。 示例&#xff1a;help copy 显…

python convert.py -s Rubble

E0222 12:08:50.144686 1326795 logging.cc:56] [option_manager.cc:813] Check failed: ExistsDir(*image_path) E0222 12:08:50.144773 1326795 option_manager.cc:879] Invalid options provided. ERROR:root:Feature extraction failed with code 256. Exiting.在运行pytho…

[BrainShadow-V1] VR头戴设备统计报告

Brain-Shadow-V1 EventVR headsetsReported byXiao enDate2025/01/15Version1.0 HTC Vive Pro 2 Pro HTC Vive Pro 2 是一款高端虚拟现实头显&#xff0c;配备双 2.5K 显示屏&#xff0c;组合分辨率达到 48962448&#xff0c;提供 120 的视场角和 120Hz 的刷新率。该设备支持…

多监控m3u8视频流,怎么获取每个监控的封面图(纯前端)

文章目录 1.背景2.问题分析3.解决方案3.1解决思路3.2解决过程3.2.1 封装播放组件3.2.2 隐形的视频div3.2.3 截取封面图 3.3 结束 1.背景 有这样一个需求&#xff1a; 给你一个监控列表&#xff0c;每页展示多个监控&#xff08;至少12个&#xff0c;m3u8格式&#xff09;&…

Golang Gin系列-2:搭建Gin 框架环境

开始网络开发之旅通常是从选择合适的工具开始的。在这个全面的指南中&#xff0c;我们将引导你完成安装Go编程语言和Gin框架的过程&#xff0c;Gin框架是Go的轻量级和灵活的web框架。从设置Go工作空间到将Gin整合到项目中&#xff0c;本指南是高效而强大的web开发路线图。 安装…

日志收集Day001

1.ElasticSearch 作用&#xff1a;日志存储和检索 2.单点部署Elasticsearch与基础配置 rpm -ivh elasticsearch-7.17.5-x86_64.rpm 查看配置文件yy /etc/elasticsearch/elasticsearch.yml&#xff08;这里yy做了别名&#xff0c;过滤掉空行和注释行&#xff09; yy /etc/el…

SW - 快捷键

文章目录 SW - 快捷键概述笔记视图缩放视图平移视图旋转END SW - 快捷键 概述 鼠标中键不好使了&#xff0c;导致鼠标滚轮的操作在SW中不好使。 已经拆过鼠标&#xff0c;清理过中键计数轮那里的灰尘。只好用几天&#xff0c;然后鼠标中键又不好使了。 先查一下能代替鼠标中键…

Freeswitch使用media_bug能力实现回铃音检测

利用freeswitch的media bug能力来在智能外呼时通过websocket对接智能中心的声音检测接口,来实现回铃音检测,来判断用户当前是否已响应,拒接,关机等。 1.回铃音处理流程 2.模块源码目录结构 首先新建一个freeswitch的源码的src/application目录下新建一个子目录mod_ringba…

【2024年华为OD机试】(B卷,100分)- 恢复数字序列 (Java JS PythonC/C++)

一、问题描述 题目解析 题目描述 对于一个连续正整数组成的序列&#xff0c;可以将其拼接成一个字符串&#xff0c;再将字符串里的部分字符打乱顺序。例如&#xff0c;序列 8 9 10 11 12 拼接成的字符串为 89101112&#xff0c;打乱一部分字符后得到 90811211&#xff0c;原…

ZNS SSD垃圾回收优化方案解读-2

四、Brick-ZNS 关键设计机制解析 Brick-ZNS 作为一种创新的 ZNS SSD 设计&#xff0c;聚焦于解决传统 ZNS SSDs 在垃圾回收&#xff08;GC&#xff09;过程中的数据迁移低效问题&#xff0c;其核心特色为存储内数据迁移与地址重映射功能。在应用场景中&#xff0c;针对如 Rock…

云消息队列 Kafka 版 V3 系列荣获信通院“云原生技术创新标杆案例”

2024 年 12 月 24 日&#xff0c;由中国信息通信研究院&#xff08;以下简称“中国信通院”&#xff09;主办的“2025 中国信通院深度观察报告会&#xff1a;算力互联网分论坛”&#xff0c;在北京隆重召开。本次论坛以“算力互联网 新质生产力”为主题&#xff0c;全面展示中国…

单元测试与unittest框架

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;薪资嘎嘎涨 单元测试的定义 1. 什么是单元测试&#xff1f; 单元测试是指&#xff0c;对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作&am…

EF Core全局查询筛选器

目录 概述 用法 添加全局查询筛选器 禁用全局查询筛选器 概述 全局查询筛选器&#xff1a;EF Core 会自动将这个查询筛选器应用于涉及这个实体类型的所有 LINQ 查询。 场景&#xff1a;软删除、多租户。 什么是软删除&#xff1f; 逻辑删除&#xff0c;并不是真正地从数…

【机器学习实战入门项目】MNIST数字分类机器学习项目

Python 深度学习项目&#xff1a;手写数字识别 为了使机器更加智能&#xff0c;开发者们正在深入研究机器学习和深度学习技术。人类通过不断练习和重复来学习执行某项任务&#xff0c;从而记住如何完成这些任务。然后&#xff0c;大脑中的神经元会自动触发&#xff0c;他们能够…

[Datawheel学习]用Llama-index创建Agent、数据库对话Agent和RAG接入Agent

1.Llama-index创建Agent 1.0 背景知识 什么是Llama-index? LlamaIndex&#xff08;原名GPT Index&#xff09;是一个专为大语言模型&#xff08;LLMs&#xff09;设计的数据框架&#xff0c;旨在帮助用户将外部数据与LLMs结合&#xff0c;实现更高效的数据检索和知识增强生成…

FPGA:Quartus软件与操作系统版本对照表

文章目录 1.软件概述2.软件版本3.设计流程4.支持的设备5.新特性6.版本对照 1.软件概述 Quartus软件是由英特尔&#xff08;Intel&#xff09;公司开发的一款功能强大的FPGA&#xff08;现场可编程逻辑门阵列&#xff09;设计工具&#xff0c;广泛应用于数字电路设计、仿真、综…

【网络协议】【http】【https】AES-TLS1.2

【网络协议】【http】【https】AES-TLS1.2 https并不是一个协议 而是在传输层之间添加了SSL/TLS协议TLS TLS 协议用于应用层协议&#xff08;如 HTTP&#xff09;和传输层&#xff08;如 TCP&#xff09;之间&#xff0c;增加了一层安全性来解决 HTTP 存在的问题&#xff0c;H…

数智化转型 | 星环科技Defensor 助力某银行数据分类分级

在数据驱动的金融时代&#xff0c;数据安全和隐私保护的重要性日益凸显。某银行作为数字化转型的先行者&#xff0c;面临着一项艰巨的任务&#xff1a;如何高效、准确地对分布在多个业务系统、业务库与数仓数湖中的约80万个字段进行数据分类和分级。该银行借助星环科技数据安全…

微信小程序:播放音频

在小程序开发中&#xff0c;音频播放是一个重要的功能。本文将详细介绍小程序音频播放的相关知识点&#xff0c;帮助开发者更好地掌握小程序音频播放的实现方法。 一、小程序音频播放的基本流程 在小程序中&#xff0c;音频播放的基本流程如下&#xff1a; 获取音频数据&#…