使用OpenCV DNN模块进行人脸检测

内容的一部分来源于贾志刚的《opencv4应用开发、入门、进阶与工程化实践》。这本书我大概看了一下,也就后面几章比较感兴趣,但是内容很少,并没有想像的那种充实。不过学习还是要学习的。

在实际工程项目中,并不是说我们将神经网络训练好拿来就直接落地,事实上,一个深度学习网络的落地在训练验证好才是开始的第一步,剩下为了部署网络,需要考虑场景问题,硬件配置,软件配置。需要对网络进行蒸馏,剪枝,轻量化,是模型大小适宜硬件配置,此外为了更好,更快速的推理,还需要将模型转成不同的模型格式,使其更加适配软件推理。目前使用较多推理加速工具英特尔的OpenVINO,Nvidia的TensorRT,都是目前主流的加速推理引擎软件,后期会继续学习。

OpenCV DNN模块在OpenCV3系列就已经正式发布,该模块是一个深度学习网络库,它支持多种预训练的深度学习模型,并可以用于多种图像和视频分析任务,如面部识别、对象检测、图像分类等。这个模块使得在OpenCV中使用深度学习模型变得相对简单,因为它可以加载由不同深度学习框架(如TensorFlow、Caffe、Torch/PyTorch等)训练的模型。其不仅可以基于CPU推理,也可基于GPU加速推理。使用方便。

使用dnn模块时,一般的步骤如下:

  1. 加载模型:使用cv2.dnn.readNetFrom*系列函数(例如readNetFromCaffereadNetFromTensorflow等)加载预训练模型。

  2. 准备输入:对输入图像进行必要的预处理(如缩放、中心化、标准化等),并将其转换为网络所需的格式。

  3. 前向传播:将处理后的图像传入网络进行前向传播,得到输出。

  4. 解析输出:根据模型的特性和应用需求,解析模型的输出,以得到最终的结果。

 Opencv samples 提供了基于resnet的SSD人脸检测模型示例,有基于caffe生成的,也有基于Tensorflow生成的。如果你安装opencv时是编译源码安装,则可以去源码位置处看看opencv4.6\opencv\sources\samples下有各类的示例,dnn文件夹下的face_detector下就有需要的网络权重文件与网络配置文件。

网络配置文件描述了一个神经网络的架构和结构。它包含了网络中的各层(如卷积层、池化层、全连接层等)的定义,以及这些层的参数(如核大小、步长、填充等)。此文件不包含训练后的模型权重,只定义了模型的结构。

这种文件通常是一个文本文件,可以使用JSON、XML、YAML或特定框架的专用格式(如Caffe的.prototxt文件)编写。在不同的深度学习框架中,配置文件的格式可能会有所不同。

网络权重文件包含了神经网络在训练过程中学习到的权重和偏置参数。这些参数是通过训练数据集上的反向传播过程优化得到的,它们决定了模型对新数据的预测能力。

权重文件通常是一个二进制文件,包含了数值型的参数数据。这种文件的格式也取决于使用的深度学习框架,常见格式包括TensorFlow的.ckpt、PyTorch的.pt.pth、Caffe的.caffemodel等。

如果你找不到,也可以在链接:https://pan.baidu.com/s/1suEmF7zgmgamnJbToegQ6Q?pwd=gcxy   提取码:gcxy 这里下载。

好了有了这些,那我还想实现一个视频检测,但是又没有摄像头,那没办法了,也可以整一个显示桌面窗口的。由于本人这里又两个显示屏,所以在将电脑显示屏窗口的一个内容获得,可以在另外一个窗口中用opencv的imshow观察。

下面提供一些重要代码。

1.window_capture

#include <opencv2/opencv.hpp>
#include <Windows.h>
#include <iostream>

using namespace std;
using namespace cv;

Mat hwnd2mat(HWND hwnd)
{
    HDC hwindowDC, hwindowCompatibleDC;

    int height, width, srcheight, srcwidth;
    HBITMAP hbwindow;
    Mat src;
    BITMAPINFOHEADER  bi;

    hwindowDC = GetDC(hwnd);
    hwindowCompatibleDC = CreateCompatibleDC(hwindowDC);
    SetStretchBltMode(hwindowCompatibleDC, COLORONCOLOR);

    RECT windowsize;    // get the height and width of the screen
    GetClientRect(hwnd, &windowsize);

    srcheight = windowsize.bottom;
    srcwidth = windowsize.right;
    height = windowsize.bottom / 1;  //change this to whatever size you want to resize to
    width = windowsize.right / 1;

    src.create(height, width, CV_8UC4);

    // create a bitmap
    hbwindow = CreateCompatibleBitmap(hwindowDC, width, height);
    bi.biSize = sizeof(BITMAPINFOHEADER);    //http://msdn.microsoft.com/en-us/library/windows/window/dd183402%28v=vs.85%29.aspx
    bi.biWidth = width;
    bi.biHeight = -height;  //this is the line that makes it draw upside down or not
    bi.biPlanes = 1;
    bi.biBitCount = 32;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrUsed = 0;
    bi.biClrImportant = 0;

    // use the previously created device context with the bitmap
    SelectObject(hwindowCompatibleDC, hbwindow);
    // copy from the window device context to the bitmap device context
    StretchBlt(hwindowCompatibleDC, 0, 0, width, height, hwindowDC, 0, 0, srcwidth, srcheight, SRCCOPY); //change SRCCOPY to NOTSRCCOPY for wacky colors !
    GetDIBits(hwindowCompatibleDC, hbwindow, 0, height, src.data, (BITMAPINFO*)&bi, DIB_RGB_COLORS);  //copy from hwindowCompatibleDC to hbwindow

    // avoid memory leak
    DeleteObject(hbwindow);
    DeleteDC(hwindowCompatibleDC);
    ReleaseDC(hwnd, hwindowDC);

    //src是BGRA 4通道显示
    return src;
}

有几个需要注意的问题,windows.h头文件需要在iostream或者其他C++标准库的前面,至于问什么就是如果写反了,windows会对一个量报重定义的错误,没法解决,应该是个冲突。

此外这段代码是将hwindowCompatibleDC的数据传给Mat类src,这里传入的输入是4通道的即RGBA类型,在 OpenCV 中处理图像时,一个常见的格式是 RGBA,其中包括四个通道:红色(R)、绿色(G)、蓝色(B)和 Alpha(A)。Alpha 通道代表透明度,其中值 0 表示完全透明,255 表示完全不透明。 这里非常重要,因为我们后续的处理时将一幅3通道的图传入网络进行推理,传入的数据格式错误就会报错。所以需要后期将RGBA格式转为RGB格式。

哦对了,这里再提一嘴,以上只是为了方便,说成RGB。在opencv中,彩色图像时BGR格式的,所以读入的4通道也是BGRA格式。

2.face_detect

void face_detect(Mat& image, Net& net) {
	int h = image.rows;
	int w = image.cols;
	cv::Mat inputBlob = cv::dnn::blobFromImage(image, 1.0, cv::Size(300, 300),
		Scalar(104.0, 177.0, 123.0), false, false);

	net.setInput(inputBlob, "data");
	cv::Mat detection = net.forward("detection_out");
	cv::Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());
	for (int i = 0; i < detectionMat.rows; i++)
	{
		float confidence = detectionMat.at<float>(i, 2);

		if (confidence > 0.125)
		{
			int x1 = static_cast<int>(detectionMat.at<float>(i, 3) * w);
			int y1 = static_cast<int>(detectionMat.at<float>(i, 4) * h);
			int x2 = static_cast<int>(detectionMat.at<float>(i, 5) * w);
			int y2 = static_cast<int>(detectionMat.at<float>(i, 6) * h);

			cv::rectangle(image, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(0, 255, 0),
				2, 8);
		}
	}
	namedWindow("人脸检测演示", WINDOW_NORMAL);
	imshow("人脸检测演示", image);

}

 这段代码就是推理的主要流程,其中几个比较重要的点就是blobFromImage函数是将待预测的图片转成网络输入的格式,一般网络的图像输入格式为N,C,H,W。N就是batch数,在推理时一般为1,C即通道数,H,W即为图像的高宽,除此之外这个函数还可缩放图像的像素值,默认1.0表示不变,也可以resize图像宽高,这里缩放到(300X300)为网络的输入。还有是否互换图像的R与B通道,数据类型(默认为浮点数)等。

然后将图像传入网络,前向推理获得结果,该网络的输出层是“detection_out”需要加输出层名称获得输出结果,我们这里是将结果用一个Mat类 detection获得。

该结果中输出格式为Nx7,N表示检测到的对象数目,7分别表示,批次,类别,得分,检测狂的左上角与右下角坐标。所以可以采用上面的代码对推理结果进行解析。这里根据置信度得分,筛选符合的条件,并将其绘制在图像显示。

3.整体流程

void screen_capture_facedetection(bool tf) {
	const std::string caffe_config = model_dir + "face_detector/deploy.prototxt";
	const std::string caffe_weight = model_dir + "face_detector/res10_300x300_ssd_iter_140000_fp16.caffemodel";

	const std::string tf_config = model_dir + "face_detector/opencv_face_detector.pbtxt";
	const std::string tf_weight = model_dir + "face_detector/opencv_face_detector_uint8.pb";

	Net net;
	if (tf) {
		net = cv::dnn::readNetFromTensorflow(tf_weight, tf_config);
	}
	else {
		net = cv::dnn::readNetFromCaffe(caffe_config, caffe_weight);
	}

	HWND hwndDesktop = GetDesktopWindow();
	//namedWindow("window", WINDOW_NORMAL);
	
	while (true) {
		Mat frame = hwnd2mat(hwndDesktop);
		if (frame.empty()) {
			break;
		}
		//从窗口获得的图像是BGRA4通道显示,可以将其转为3通道显示
		Mat frame3Channel;
		cvtColor(frame, frame3Channel, COLOR_BGRA2BGR);
		//imshow("window", frame3Channel);
		//cout << frame3Channel.channels() << endl;
		//break;

		face_detect(frame3Channel, net);

		char c = waitKey(10);
		if (c == 27) {
			break;
		}
	}
}

可以看到这里使用cvtColor将4通道转为3通道。

在int main 中调用即可,注意bool tf 选择caffee model,或者tensorflow model即可。推出,在显示窗口中按ESC即可退出。

后期当然也可以使用opencv的video writer,将视频录制下来。这里就不接着做了,感兴趣的可以试一下。

一下是一些效果。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Win10 使用 Nmap 扫描 Andorid 设备开放端口

Nmap Nmap 是 网络探测工具和安全/端口扫描器。 官网链接 Nmap参考指南(Man Page) 官网下载地址 Downloading Nmap Nmap 下载安装 到官网下载对应操作系统的安装包&#xff0c; 默认配置&#xff0c;一直下一步安装即可。安装过程中备份下安装路径&#xff0c;后续用到。…

【优化】XXLJOB修改为使用虚拟线程

【优化】XXLJOB修改为使用虚拟线程 新建这几个目录 类&#xff0c; 去找项目对应的xxljob的源码 主要是将 new Thread 改为 虚拟线程 Thread.ofVirtual().name("VT").unstarted 以下代码是 xxljob 2.3.0版本 举一反三 去修改对应版本的代码 <!-- 定…

C语言数据结构-----常用七种排序介绍、分类、实现及性能比较

前言 ①排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 ②稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c;若经过排序&#…

Spring中用到的设计模式

一、工厂模式 BeanFactory 1、简单工厂模型&#xff0c;是指由一个工厂对象决定创建哪一种产品类的实例&#xff0c;工厂类负责创建的对象较少&#xff0c;客户端只需要传入工厂类的参数&#xff0c;对于如何创建对象的逻辑不需要关心 优点&#xff1a; 只需传入一个正确的参数…

第四部分 一阶逻辑基本概念

目录 主要内容 一阶逻辑命题符号化 一阶逻辑公式及其解释 个体词——所研究对象中可以独立存在的具体或抽象的客体 谓词——表示个体词性质或相互之间关系的词 量词——表示数量的词 例1 用0元谓词将命题符号化 例2 在一阶逻辑中将下面命题符号化 例如 例如 例3 给定解释 I 如下…

京东JDAPI:电商行业的得力助手

一、引言 在当今电商行业中&#xff0c;数据的获取与利用显得尤为重要。作为中国领先的电商平台&#xff0c;京东提供了丰富的API接口&#xff0c;其中JD商品详情API是关键之一&#xff0c;它允许第三方开发者获取京东平台上的商品详情信息。本文将深入探讨京东JD商品详情API在…

欧洲版OpenAI疑似将在24年发布并开源GPT-4级别模型!

大家好&#xff0c;我是二狗。 今天在推特上看到一条振奋人心的消息&#xff1a; “ 欧洲版OpenAI、法国初创公司 Mistral 首席执行官 Arthur Mensch 在法国国家广播电台宣布&#xff0c;Mistral 将在 2024 年发布开源 GPT-4 级别模型。” 这位老哥接着表示甚至可能是免费的&a…

前端传输formDate格式的数据,后端不能用@RequestBody接收

写了个接口&#xff0c;跟前端对接&#xff0c;前端说怎么一直415的报错 我寻思不对啊&#xff0c;我swagger都请求成功了&#xff0c;后来发现前端一直是以formdata格式提交的数据&#xff0c;这样我其实是可以不加RequestBody的&#xff1b; 知识点&#xff1a; RequestBody…

TrustZone之与非安全虚拟化交互

到目前为止&#xff0c;我们在示例中忽略了非安全状态中可能存在的虚拟化程序。当存在虚拟化程序时&#xff0c;虚拟机与安全状态之间的许多通信将通过虚拟化程序进行。 例如&#xff0c;在虚拟化环境中&#xff0c;SMC用于访问固件功能和可信服务。固件功能包括诸如电源管理之…

将遗留系统分解为微服务:第 2 部分

在当今不断发展的技术环境中&#xff0c;从整体架构向微服务的转变对于许多企业来说都是一项战略举措。这在报销计算系统领域尤其重要。正如我在上一篇文章第 1 部分应用 Strangler 模式将遗留系统分解为微服务-CSDN博客中提到的&#xff0c;让我们探讨如何有效管理这种转变。 …

前端学习——指令

vue作为前端框架&#xff0c;为了简化或实现一些特定功能&#xff0c;提供了很多指令&#xff0c;那什么是指令呢&#xff1f; 所谓的指令就是能够完成特定功能的一些vue语法&#xff0c;比如属性绑定指令v-bind&#xff0c;事件绑定指令v-on&#xff0c;循环指令v-for等。在v…

【Amazon 实验②】使用Amazon WAF做基础 Web Service 防护之自定义规则

文章目录 1. 自定义规则1.1 介绍 2. 实验步骤2.1 测试2.2 输出 上一篇章介绍了使用Amazon WAF做基础 Web Service 防护中的Web ACLs 配置 & AWS 托管规则的介绍和演示操作 【Amazon 实验①】使用Amazon WAF做基础 Web Service 防护&#xff0c;本篇章将继续介绍关于自定义…

2009-2022年31省细分产品出口数据/按hs码分的22类细分产品的出口数据

2009-2022年31省细分产品出口数据/按hs码分的22类细分产品的出口数据 1、时间&#xff1a;2009-2022年 2、指标&#xff1a;时间、流向名称、商品编码、商品名称、伙伴名称、主题编码、方式名称、金额&#xff08;美元&#xff09; 3、来源&#xff1a;海关贸易统计数据/海关…

智能优化算法应用:基于骑手优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于骑手优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于骑手优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.骑手优化算法4.实验参数设定5.算法结果6.…

[SQL]实验 视图和索引的应用

实验目的&#xff1a; [实验目的和要求] 1、掌握视图的创建、修改和重命名的方法 2、掌握视图中数据的操作 3、了解索引的作用 4、掌握索引的创建方法 实验步骤&#xff1a; 1、在销售管理数据库中&#xff0c;创建一个女职工视图&#xff0c;包括员工的编号、姓名、性别、雇佣…

多标签分类中常用指标和可视化例子

多标签分类中常用指标 1. 准确率&#xff08;Accuracy&#xff09; 准确率计算的是正确预测的标签比例。对于多标签分类&#xff0c;这通常是一个较为严格的指标&#xff0c;因为要求每个实例的所有标签都预测正确。 Accuracy 正确预测的标签数 总标签数 \text{Accuracy} \…

Qt前端技术:5.QSS

这个是表示QFrame中的pushButton中的子类和它子类的子类都将背景变为red 写成大于的时候表示只有直接的子类对象才会变 这个图中的QGroupBox和QPushButton都是QFrame的直接的子类 这个中的QGroupBox是QFrame的直接的子类但是QPushButton 是QGroupBox的子类&#xff0c;QPushB…

3. 结构型模式 - 组合模式

亦称&#xff1a; 对象树、Object Tree、Composite 意图 组合模式是一种结构型设计模式&#xff0c; 你可以使用它将对象组合成树状结构&#xff0c; 并且能像使用独立对象一样使用它们 问题 如果应用的核心模型能用树状结构表示&#xff0c; 在应用中使用组合模式才有价值。 …

基于JavaWeb的个人健康信息管理系统论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本个人健康信息管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据…

laravel 对接支付,本地穿透问题

本地穿透有好多工具&#xff0c;参考链接&#xff1a;https://zhuanlan.zhihu.com/p/339923535 我这边是用的 NATAPP 官网&#xff1a;https://natapp.cn/ 客户端下载&#xff1a;https://natapp.cn/# NATAPP1分钟快速新手图文教程&#xff1a;https://natapp.cn/article/n…