opencv实现人脸识别(c++实现)

2023-11-16

1 说明

  • 本文章基于opencv + VS2015 实现人脸检测

2 效果

请添加图片描述

  • 可以直接打开摄像头对人脸进行识别,这些标识框也会跟随你的人脸移动。隐私问题,我这里对图片进行了识别。

3 相关类及函数介绍

opencv中文文档

3.1 cv::VideoCapture

官方文档说明

  • 功能 :用于从视频文件、图像序列或摄像机捕获视频的类

3.1.1 open

  • bool cv::VideoCapture::open(int index);
  • 功能 : 打开相机进行视频捕获
  • 参数介绍
    • index : 要打开的视频捕获设备的索引(0表示打开默认摄像机)

3.1.2 read

  • bool cv::VideoCapture::read(OutputArray image);
  • 功能 : 抓取、解码并返回下一个视频帧
  • 参数介绍
    • image:图像视频帧在此处返回。如果未抓取任何帧,则图像将为空。

3.1.3 release

  • cv::VideoCapture::release();
  • 功能 : 关闭视频文件或捕获设备

3.2 cv::CascadeClassifier

官方文档说明

  • 功能 : CascadeClassifier是opencv下objdetect模块中用来做目标检测的级联分类器的一个类, 早期opencv版本仅支持haar特征的目标检测,分别在opencv2.2和2.4之后开始支持LBP和HOG特征的目标检测.

3.2.1 load

  • bool cv::CascadeClassifier::load(const String &filename);

  • 功能 : 从文件中加载级联分类器

  • 参数介绍

    • filename : 需要加载的分类器文件
  • opencv安装包中包含以及训练好的分类器文件(opencv\sources\data\haarcascades)

    • haarcascade_frontalface_alt.xml 检测人脸的分类器文件
    • haarcascade_eye.xml 检测眼睛的分类器文件
    • haarcascade_mcs_mouth.xml 检测嘴部的分类器文件(opencv安装包中没有携带, 可从github上去下载)
  • 分类器文件下载

3.2.2 detectMultiScale

  • void cv::CascadeClassifier::detectMultiScale(const Mat& image, CV_OUT vector& objects, double scaleFactor = 1.1, int minNeighbors = 3, int flags = 0, Size minSize = Size(),Size maxSize = Size());
  • 功能 : 检测输入图像中不同大小的对象。检测到的对象将作为矩形列表返回
  • 参数介绍
    • image : 包含检测对象的图像的CV_8U类型矩阵
    • objects : 矩形的向量,其中每个矩形包含被检测的对象, 矩形可以部分位于原始图像之外
    • scaleFactor : 指定在每个图像缩放时的缩放比例. 默认为1.1 即每次搜索窗口扩大10%
    • minNeighbors : 指定每个候选矩形需要保留多少个相邻矩形(匹配成功所需要的周围矩形框的数目,每一个特征匹配到的区域都是一个矩形框,只有多个矩形框同时存在的时候,才认为是匹配成功,比如人脸,这个默认值是3)
    • flag
      • CASCADE_DO_CANNY_PRUNING : 利用canny边缘检测来排除一些边缘很少或者很多的图像区域
      • CASCADE_SCALE_IMAGE : 正常比例检测
      • CASCADE_FIND_BIGGEST_OBJECT : 只检测最大的物体
      • CASCADE_DO_ROUGH_SEARCH : 初略的检测
    • minSize : 目标区域最小范围
    • maxSize : 目标区域最大范围

3.3 cv::waitKey

  • int cv::waitKey(int delay = 0);
  • 功能 : 等待按键按下
  • 参数介绍
    • delay : 超时时间, 单位为毫秒
  • 返回值 : 返回按下按键的值

3.4 cv::imshow

  • void cv::imshow(const String &winname, InputArray mat);
  • 功能 : 将图片显示在窗口中,通过设备屏幕展现出来
  • 参数介绍
    • winname: 窗口名
    • mat:要显示的图片

3.5 cv::destroyAllWindows

  • void cv::destroyAllWindows();
  • 功能 : 删除窗口

3.6 cv::putText

  • void cv::putText(InputOutputArray img, const String& text, Point org, int fontFace, double fontScale, Scalar color, int thickness = 1, int lineType = LINE_8, bool bottomLeftOrigin = false);

  • 功能 : 给视频图像添加文字说明

  • 参数介绍

    • img : 需要添加文字说明的图形对象
    • text : 需要写入的文本内容
    • org : 第一个字符左下角坐标
    • fontFace : 字体类型
      • 衬线体就是有边角装饰的字体, 无衬线字体通常是机械和统一粗细的线条, 没有边角的装饰

      • FONT_HERSHEY_SIMPLEX : 正常大小的无衬线字体

      • FONT_HERSHEY_PLAIN : 小号无衬线字体

      • FONT_HERSHEY_DUPLEX : 正常大小的无衬线字体(比FONT_HERSHEY_SIMPLEX更复杂)

      • FONT_HERSHEY_COMPLEX : 正常大小的衬线字体

      • FONT_HERSHEY_TRIPLEX : 正常大小的衬线字体(比FONT_HERSHEY_COMPLEX更复杂)

      • FONT_HERSHEY_COMPLEX_SMALL : FONT_HERSHEY_COMPLEX的较小版本

      • FONT_HERSHEY_SCRIPT_SIMPLEX : 手写样式字体

      • FONT_HERSHEY_SCRIPT_COMPLEX : 更复杂的FONT_HERSHEY_SCRIPT_SIMPLEX变体

      • FONT_ITALIC : 斜体字体的标志

    • fontScale : 字体大小
    • color : 字体颜色
    • thickness : 字体粗细
    • lineType : 线型
      • LINE_4 : 4联通线型
      • LINE_8 : 8联通线型
      • LINE_AA : 抗锯齿线

4 源代码

  • mian.cpp
#include <iostream>
#include <opencv2/opencv.hpp>

char* face_cascade_name = "D:\\opencv\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml";
char* eyes_cascade_name = "D:\\opencv\\opencv\\sources\\data\\haarcascades\\haarcascade_eye.xml";
char* mouth_cascade_name = "D:\\opencv\\opencv\\sources\\data\\haarcascades\\haarcascade_mcs_mouth.xml";

void faceRecongize(cv::CascadeClassifier faceCascade, cv::CascadeClassifier eyesCascade, cv::CascadeClassifier mouthCascade, cv::Mat frame);

int main(){
    cv::VideoCapture *videoCap = new cv::VideoCapture;

	cv::CascadeClassifier faceCascade;
	cv::CascadeClassifier eyesCascade;
	cv::CascadeClassifier mouthCascade;

    // 加载脸部分类器文件
	if (!faceCascade.load(face_cascade_name)) {
		std::cout << "load face_cascade_name failed. " << std::endl;
		return -1;
	}

    // 加载眼睛部分分类器文件
	if (!eyesCascade.load(eyes_cascade_name)) {
		std::cout << "load eyes_cascade_name failed. " << std::endl;
		return -1;
	}

    // 加载嘴部分类器文件
	if (!mouthCascade.load(mouth_cascade_name)) {
		std::cout << "load mouth_cascade_name failed. " << std::endl;
		return -1;
	}

    // 打开摄像机
	videoCap->open(0);


	if (!videoCap->isOpened()) {
		videoCap->release();
		std::cout << "open camera failed"<< std::endl;
        return -1;
	}

	std::cout << "open camera success"<< std::endl;

    while(1){
		cv::Mat frame;
		//读取视频帧
		videoCap->read(frame);

		if (frame.empty()) {
			videoCap->release();
			return -1;
		}

        //进行人脸识别
		faceRecongize(faceCascade, eyesCascade, mouthCascade, frame);

        //窗口进行展示
        imshow("face", frame);

        //等待回车键按下退出程序
		if (cv::waitKey(30) == 13) {
			cv::destroyAllWindows();
			return 0;
		}
    }

    system("pause");
    return 0;
}

void faceRecongize(cv::CascadeClassifier faceCascade, cv::CascadeClassifier eyesCascade, cv::CascadeClassifier mouthCascade, cv::Mat frame) {
	std::vector<cv::Rect> faces;

    // 检测人脸
	faceCascade.detectMultiScale(frame, faces, 1.1, 2, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(30, 30));
	for (int i = 0; i < faces.size(); i++) {
		
        // 用椭圆画出人脸部分
        cv::Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2);
		ellipse(frame, center, cv::Size(faces[i].width / 2, faces[i].height / 2), 0, 0, 360, cv::Scalar(255, 0, 255), 4, 8, 0);
		
		cv::Mat faceROI = frame(faces[i]);
		std::vector<cv::Rect> eyes;

        // 检测眼睛
		eyesCascade.detectMultiScale(faceROI, eyes, 1.1, 2, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(30, 30));
		for (int j = 0; j < eyes.size(); j++)
		{
            // 用圆画出眼睛部分
			cv::Point eye_center(faces[i].x + eyes[j].x + eyes[j].width / 2, faces[i].y + eyes[j].y + eyes[j].height / 2);
			int radius = cvRound((eyes[j].width + eyes[j].height)*0.25);
			circle(frame, eye_center, radius, cv::Scalar(255, 0, 0), 4, 8, 0);
		}

		cv::Mat mouthROI = frame(faces[i]);
		std::vector<cv::Rect> mouth;

        // 检测嘴部
		mouthCascade.detectMultiScale(mouthROI, mouth, 1.1, 2, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(30, 30));
		for (int k = 0; k < mouth.size(); k++)
		{
            //用长方形画出嘴部
			cv::Rect rect(faces[i].x + mouth[k].x, faces[i].y + mouth[k].y, mouth[k].width, mouth[k].height);
			rectangle(frame, rect, cv::Scalar(0, 255, 0), 2, 8, 0);
		}

        // 检测到两个眼睛和一个嘴巴, 可认为检测到有效人脸
		if (eyes.size() >= 2 && mouth.size() >= 1) {
            
            // 人脸上方区域写字进行标识
			cv::Point centerText(faces[i].x + faces[i].width / 2 - 40, faces[i].y - 20);
			cv::putText(frame, "face", centerText, cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 0, 255), 2);
		}

	}
}
  • CMakeLists.txt
cmake_minimum_required (VERSION 3.5)
project (faceRecongize2015)

MESSAGE(STATUS "PROJECT_SOURCE_DIR " ${PROJECT_SOURCE_DIR})
SET(SRC_LISTS ${PROJECT_SOURCE_DIR}/src/main.cpp)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

# 配置头文件目录
include_directories(${PROJECT_SOURCE_DIR}/src)
include_directories("D:\\opencv\\opencv\\build\\include")
include_directories("D:\\opencv\\opencv\\build\\include\\opencv2")

# 设置不显示命令框
if(MSVC)
	set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
endif()

# 添加库文件
set(PRO_OPENCV_LIB "D:\\opencv\\opencv\\build\\x64\\vc15\\lib\\opencv_world460.lib" "D:\\opencv\\opencv\\build\\x64\\vc15\\lib\\opencv_world460.lib")

IF(WIN32)
    # 生成可执行程序
	ADD_EXECUTABLE(faceRecongize2015 ${SRC_LISTS})
	# 链接库文件
    TARGET_LINK_LIBRARIES(faceRecongize2015 ${PRO_OPENCV_LIB})
ENDIF()

5 编译说明

  • 编译前先安装opencv, cmake, Visual Studio 2015

  • 我的opencv的安装目录(D:\opencv), 源码安装比较麻烦, 建议直接下载安装包进行安装。

  • opencv安装包下载

  • opencv源码下载

  • 目录结构

- src
  - mian.cpp
- build_x64
- CMakeLists
  • 编译命令(在build_x64目录下执行)
cmake -G "Visual Studio 14 2015 Win64" ..
cmake --build ./ --config Release
  • 说明
    • 编译成功后,将opencv\build\x64\vc15\bin下的opencv_world460.dll opencv_world460d.dll拷贝到生成的可执行程序目录下, 然后再运行程序。
    • 下载的opencv安装包中只包含了64位的库, 如果需要32位的库可下载源代码去编译。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

opencv实现人脸识别(c++实现) 的相关文章

  • 结构化绑定中缺少类型信息

    我刚刚了解了 C 中的结构化绑定 但有一件事我不喜欢 auto x y some func is that auto正在隐藏类型x and y 我得抬头看看some func的声明来了解类型x and y 或者 我可以写 T1 x T2 y
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • 如何在 Cassandra 中存储无符号整数?

    我通过 Datastax 驱动程序在 Cassandra 中存储一些数据 并且需要存储无符号 16 位和 32 位整数 对于无符号 16 位整数 我可以轻松地将它们存储为有符号 32 位整数 并根据需要进行转换 然而 对于无符号 64 位整
  • std::list 线程push_back、front、pop_front

    std list 线程安全吗 我假设不是这样 所以我添加了自己的同步机制 我认为我有正确的术语 但我仍然遇到问题 每个函数都由单独的线程调用 Thread1 不能等待 它必须尽可能快 std list
  • 如何从 Visual Studio 将视图导航到其控制器?

    问题是解决方案资源管理器上有 29 个项目 而且项目同时具有 ASP NET MVC 和 ASP NET Web 表单结构 在MVC部分中 Controller文件夹中有大约100个子文件夹 每个文件夹至少有3 4个控制器 视图完全位于不同
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • 如何从本机 C(++) DLL 调用 .NET (C#) 代码?

    我有一个 C app exe 和一个 C my dll my dll NET 项目链接到本机 C DLL mynat dll 外部 C DLL 接口 并且从 C 调用 C DLL 可以正常工作 通过使用 DllImport mynat dl
  • -webkit-box-shadow 与 QtWebKit 模糊?

    当时有什么方法可以实现 webkit box shadow 的工作模糊吗 看完这篇评论错误报告 https bugs webkit org show bug cgi id 23291 我认识到这仍然是一个问题 尽管错误报告被标记为RESOL
  • 如何连接重叠的圆圈?

    我想在视觉上连接两个重叠的圆圈 以便 becomes 我已经有部分圆的方法 但现在我需要知道每个圆的重叠角度有多大 但我不知道该怎么做 有人有主意吗 Phi ArcTan Sqrt 4 R 2 d 2 d HTH Edit 对于两个不同的半
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • 两个静态变量同名(两个不同的文件),并在任何其他文件中 extern 其中一个

    在一个文件中将变量声明为 static 并在另一个文件中进行 extern 声明 我认为这会在链接时出现错误 因为 extern 变量不会在任何对象中看到 因为在其他文件中声明的变量带有限定符 static 但不知何故 链接器 瑞萨 没有显
  • 为什么使用小于 32 位的整数?

    我总是喜欢使用最小尺寸的变量 这样效果就很好 但是如果我使用短字节整数而不是整数 并且内存是 32 位字可寻址 这真的会给我带来好处吗 编译器是否会做一些事情来增强内存使用 对于局部变量 它可能没有多大意义 但是在具有数千甚至数百万项的结构
  • C 函数 time() 如何处理秒的小数部分?

    The time 函数将返回自 1970 年以来的秒数 我想知道它如何对返回的秒数进行舍入 例如 对于100 4s 它会返回100还是101 有明确的定义吗 ISO C标准没有说太多 它只说time 回报 该实现对当前日历时间的最佳近似 结
  • 如何在 Android 中使用 C# 生成的 RSA 公钥?

    我想在无法假定 HTTPS 可用的情况下确保 Android 应用程序和 C ASP NET 服务器之间的消息隐私 我想使用 RSA 来加密 Android 设备首次联系服务器时传输的对称密钥 RSA密钥对已在服务器上生成 私钥保存在服务器
  • C++ 继承的内存布局

    如果我有两个类 一个类继承另一个类 并且子类仅包含函数 那么这两个类的内存布局是否相同 e g class Base int a b c class Derived public Base only functions 我读过编译器无法对数
  • 在OpenGL中,我可以在坐标(5, 5)处精确地绘制一个像素吗?

    我所说的 5 5 正是指第五行第五列 我发现使用屏幕坐标来绘制东西非常困难 OpenGL 中的所有坐标都是相对的 通常范围从 1 0 到 1 0 为什么阻止程序员使用屏幕坐标 窗口坐标如此严重 最简单的方法可能是通过以下方式设置投影以匹配渲
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template
  • 如何确定 CultureInfo 实例是否支持拉丁字符

    是否可以确定是否CultureInfo http msdn microsoft com en us library system globalization cultureinfo aspx我正在使用的实例是否基于拉丁字符集 我相信你可以使
  • 使用 WGL 创建现代 OpenGL 上下文?

    我正在尝试使用 Windows 函数创建 OpenGL 上下文 现代版本 基本上代码就是 创建窗口类 注册班级 创建一个窗口 choose PIXELFORMATDESCRIPTOR并设置它 创建旧版 OpenGL 上下文 使上下文成为当前

随机推荐

  • vb 字符串截取 资料 搜集

    1 ASC X Chr X 转换字符字符码 格式 P Asc X 返回字符串X的第一个字符的字符码 P Chr X 返回字符码等于X的字符 2 Len X 计算字符串X的长度 格式 P Len X 说明 空字符串长度为0 空格符也算一个字符
  • yolov5网络结构学习

    注 原文链接是深入浅出Yolo系列之Yolov5核心基础知识完整讲解 我觉得这篇文章写的很好 所以自己手敲了一遍 并修改了很小一部分的细节 或者加了一些来自作者另一篇文章深入浅出Yolo系列之Yolov3 Yolov4 Yolov5核心基础
  • Go(十三)Error接口和错误处理

    Go 语言中的错误处理与其他语言不太一样 它把错误当成一种值来处理 更强调判断错误 处理错误 而不是一股脑的 catch 捕获异常 目录 Error 接口 Error 接口 创建错误 fmt Errorf 错误结构体类型 Error 接口
  • 图像处理+边缘检测算法

    一 边缘检测算子类别 常见边缘检测算子 Roberts Sobel Prewitt Laplacian Log Marr Canny Kirsch Nevitia 二 一阶微分算子 Roberts Sobel Prewitt Robert算
  • Spark DataFrame的Join操作和withColumn、withColumnRenamed方法实践案例(Scala Demo代码)

    import org apache log4j Level Logger import org apache spark sql SparkSession import org apache spark sql functions obje
  • opencv Mat的一些基础操作

    cout lt lt value lt
  • Huawei MatePad Pro安装GMS服务详细图文教程

    一 导读 由于国际贸易环境的变化 谷歌公司自2019年起已不再为华为提供 GMS 服务 所以在此时间后华为新出的手机 平板等设备将不再集成 GMS 服务 对于国内普遍用户而言 应该影响不大或有的甚至毫无影响 但对于海外用户和国内一些特殊人群
  • matplotlib中的黑魔法:constrained和tight layout

    欢迎关注 生信修炼手册 在画图时 经常会遇到文字等图形元素超过了图片边框 显示不全的问题 比如以下代码 gt gt gt plt scatter x np random randn 10 y np random randn 10 s 40
  • electron-vue2 项目初始化

    不要使用网上或者 github 的模板初始化项目 直接上代码 安装 vuecli 脚手架 npm update vue cli 初始化 project name 项目 vue create project name 进入项目 cd proj
  • 栈(stack)栈的链式存储(链表)

    目录 栈的概念 栈的特点 火车调度案例演示 编辑 栈的结构体 数组的首地址做栈顶还是栈底比较好 栈的初始化 入栈 出栈 遍历栈中元素 链式存储 栈 栈链式存储结构体 初始化栈 案例 入栈 出栈 栈的概念 栈 stack 又名堆栈 它是一种运
  • 【计算机毕业设计】242高校图书馆设计与实现

    一 系统截图 需要演示视频可以私聊 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术 让传统数据信息的管理升级为软件存储 归纳 集中处理数据信息的管理方式 本高校图书馆就是在这样的大环境下诞生 其可以帮助管理者在短时间内处理完毕庞大的
  • react-native 中使用echarts 水波图

    echarts liquidfill min js加放到库中 并在tpl html中引用便可
  • 操作符详解上(非常详细)

    目录 二进制介绍 二进制 2进制转10进制 10进制转2进制数字 2进制转8进制和16进制 2进制转8进制 2进制转16进制 原码 反码 补码 移位操作符 左移操作符 右移操作符 位操作符 逗号表达式 二进制介绍 在初学计算机时我们常常会听
  • GO语言gin框架初步介绍

    1 下载gin框架 go get u github com gin gonic gin 当无法下载时 大概率是被墙了 需要配置环境变量 go env w GOPROXY https goproxy io direct go env w GO
  • Hello World程序 Pycharm

    由于电脑原因 进行了系统重装 所以最近把所用的软件给重新装了一遍 最近突然萌生写博客的想法 那就start 下载完成了Python3 7之后 安装Pycharm python3 7 IDLE界面 那么开启pycharm的第一个程序 开启py
  • GAN的学习记录

    最近看了一下神经网络和卷积神经网络 CNN 的基础概念 然后开始看生成对抗网络 GAN 的基础知识 之后会自己写一下代码 用GAN对数据集进行训练 一 12月的计划 1 先看懂GAN的基础理论 2 找一些代码 想办法把轴承的数据集放到GAN
  • 最近收集的9000个英语单词

    wrong adj 错误的 不道德的 不适合的 不正常的adv 错误地n 坏事 不公正的事 错误v 无礼地对待 冤枉 visualize v 想像 设想 形象化 显现 unwise a 无智的 愚笨的 不智的 unlikely adj 不太
  • 机器学习原来这么有趣 Part3: 深度学习与卷积神经网络

    最近看了Adam Geitgey的机器学习系列文章 寻思着闲着也是闲着 干脆翻译以下 顺便学习下英语啥的哈哈哈 第一次做这种事 有不到位的地方欢迎指教噢 前言 你是否已经厌倦了在查阅了无数有关深度学习的文章之后仍然不能参透其中深意的无力感
  • python PyQt5学习笔记 事件和信号 有注释 p2

    事件和信号 事件 所有的应用都是事件驱动的 事件大部分都是由用户的行为产生的 当然也有其他的事件产生方式 比如网络的连接 窗口管理器或者定时器等 调用应用的exec 方法时 应用会进入主循环 主循环会监听和分发事件 在事件模型中 有三个角色
  • opencv实现人脸识别(c++实现)

    1 说明 本文章基于opencv VS2015 实现人脸检测 2 效果 可以直接打开摄像头对人脸进行识别 这些标识框也会跟随你的人脸移动 隐私问题 我这里对图片进行了识别 3 相关类及函数介绍 opencv中文文档 3 1 cv Video