利用OpenCV做个熊猫表情包 二
之前写了一篇
利用OpenCV做个熊猫表情包吧_Leen的博客-CSDN博客
回想起来觉得有点太弱了,意犹未尽,每次使用需要自己去手动截取人脸,清除黑边什么的才能使用demo去合成表情,无奈之前由于安装的vs,opencv版本都比较低,也懒得再折腾。
恰逢前些天电脑硬盘坏了,数据丢了,一切都要重装,那直接高配走起,VS2022+OpenCV4.8,既然环境都有了,于是有空的时候就改进了一下,让它利用opencv,做简单的人脸识别,自动去图片中识别、提取人脸,同时去做黑边清理工作,自动化程度更高,用起来更省事儿~
原理呢就是在处理原始图片的流程中加入了面部识别,将面部单独切出来,同时对面部图片做黑边清晰处理,然后再进行表情的合成工作,下面介绍一下具体过程:
首先是识别到用户输入的原图

利用opencv进行面部识别

灰度化图片后提取面部,并清理黑边

再将面部跟熊猫脸进行融合

下面介绍关键步骤的代码:
初始化面部识别
int InitFaceDetect()
{if (!faceCascade.load("D:\\Workspace\\opencv\\build\\etc\\haarcascades\\haarcascade_frontalface_default.xml")) {cout << "人脸检测级联分类器没找到!!" << endl;return -1;}if (!eyes_Cascade.load("D:\\Workspace\\opencv\\build\\etc\\haarcascades\\haarcascade_eye_tree_eyeglasses.xml")) {cout << "眼睛检测级联分类器没找到!!" << endl;return -1;}return 0;
}
用到的两个xml特征文件均为openCV提供。
清楚灰度图像中的深色边角区域
/************************************************************************/
/* 消除图片四周的黑色边角区域 */
/************************************************************************/Mat RemoveBlackCorner(Mat img)
{int i, j;int h = img.size().height;int w = img.size().width;if (img.channels() == 1) //灰度图片{for (j = 0; j < h; j++){for (i = 0; i < w; i++){if (img.at<uchar>(j, i) < 110){img.at<uchar>(j, i) = 255;}else{break;}}for (i = w - 1; i >= 0; i--){if (img.at<uchar>(j, i) < 110){img.at<uchar>(j, i) = 255;}else{break;}}}for (i = 0; i < w; i++){for (j = 0; j < h; j++){if (img.at<uchar>(j, i) < 110){img.at<uchar>(j, i) = 255;}else{break;}}for (j = h - 1; j >= 0; j--){if (img.at<uchar>(j, i) < 110){img.at<uchar>(j, i) = 255;}else{break;}}}}return img;
}
人脸识别以及将加工后的人脸存成临时文件
bool parse_cmd(int argc, char* argv[])
{if (argc < 3){return false;}g_str_src = string(argv[1]);g_str_bg = string(argv[2]);return true;
}string GetFolderFromFile(string strFile)
{size_t last_slash = strFile.find_last_of("\\");std::string directory = strFile.substr(0, last_slash);return directory;
}int DetectFace(Mat img, Mat imgGray) {namedWindow("src", WINDOW_AUTOSIZE);vector<Rect> faces, eyes;faceCascade.detectMultiScale(imgGray, faces, 1.2, 5, 0, Size(30, 30));int retVal = -1;//目前只取一个脸if (faces.size() > 0) {for (size_t i = 0; i < faces.size(); i++) {//框出人脸位置rectangle(img, Point(faces[i].x+ faces[i].width / 8, faces[i].y+faces[i].height / 8), Point(faces[i].x + faces[i].width*7/8, faces[i].y + faces[i].height * 7 / 8), Scalar(0, 0, 255), 1, 8);cout << faces[i] << endl;//将人脸从灰度图中抠出来Mat face_ = imgGray(faces[i]);//缩小一点,默认取的矩形比较大Rect rect(Point(faces[i].width / 8, faces[i].height / 8),Point(faces[i].width * 7 / 8, faces[i].height * 7/ 8));Mat ROI = face_(rect);//RemoveBlackBorder(ROI, ROI);Mat imgOut = RemoveBlackCorner(ROI);//RemoveBlackBorder(ROI, imgOut);imwrite(g_str_face, imgOut);retVal = 0;eyes_Cascade.detectMultiScale(face_, eyes, 1.2, 2, 0, Size(30, 30));for (size_t j = 0; j < eyes.size(); j++) {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(img, eye_center, radius, Scalar(65, 105, 255), 4, 8, 0);}}}imshow("src", img);return retVal;
}
主逻辑流程
int main(int argc, char* argv[])
{if (!parse_cmd(argc, argv)){cout << "command error" << endl;return -1;}if (InitFaceDetect() != 0){return -1;}//string strDirBase = GetFolderFromFile(g_str_src);Mat img_src = imread(g_str_src);Mat img_background = imread(g_str_bg);g_str_face = strDirBase + "\\tmp_face.jpg";
#ifdef _DBG_SHOWnamedWindow("img_src");imshow("img_src", img_src);
#endifMat img_gray;cvtColor(img_src, img_gray, COLOR_BGR2GRAY); //图像灰度化int nFace = DetectFace(img_src, img_gray);waitKey(3000);
#ifdef _DBG_SHOWnamedWindow("gray", WINDOW_NORMAL);imshow("gray", img_gray);
#endif// 按照背景图大小等比缩放Size dsize = Size(img_background.cols * 0.55, img_background.rows * 0.55);//判断一下是否自动检测到了人脸Mat img_face;if (nFace == 0) {cout << "opencv find face,get face." << endl;img_face = imread(g_str_face);}else{cout << "can not find face.use image user input." << endl;img_face = img_gray;}resize(img_face, img_face, dsize, 1, 1, INTER_AREA);//输出缩放后效果图并重新加载Mat img_face2;threshold(img_face, img_face2, 105, 255, THRESH_BINARY);imwrite(strDirBase + "\\tmp.jpg", img_face2);//imshow("img_face2", img_face2);Mat img_face3 = imread(strDirBase + "\\tmp.jpg");//居中粘合两图Rect roi_rect = Rect((img_background.cols - img_face3.cols) / 2, (img_background.rows - img_face3.rows) / 2, img_face3.cols, img_face3.rows);img_face3.copyTo(img_background(roi_rect));//显示并输出imshow("mixed", img_background);imwrite(g_str_src + ".emoji.jpg", img_background);waitKey(5000);destroyAllWindows();return 0;
}
相关文章:
利用OpenCV做个熊猫表情包 二
之前写了一篇 利用OpenCV做个熊猫表情包吧_Leen的博客-CSDN博客 回想起来觉得有点太弱了,意犹未尽,每次使用需要自己去手动截取人脸,清除黑边什么的才能使用demo去合成表情,无奈之前由于安装的vs,opencv版本都比较低…...
华纳云服务器怎么清理cdn缓存?
清理 CDN(内容分发网络)缓存通常需要通过 CDN 提供商的管理界面或 API 进行操作。不同的 CDN 提供商可能有不同的方法和步骤,以下是一个通用的清理 CDN 缓存的一般步骤: 1. 登录到 CDN 提供商的管理界面: 打开你所使用的 CDN 提供商的网站。 …...
python functools.wraps保留被装饰函数属性
作用 普通装饰器 ,会覆盖函数名称,并且 会替换 函数 文档字符串 介绍 functools.wraps(wrapped[, assigned][, updated]) This is a convenience function for invoking partial(update_wrapper, wrappedwrapped, assignedassigned, updatedupdated) …...
【多线程 - 11、死锁】
死锁 1、介绍 在 Java 中使用多线程,就会有可能导致死锁问题。死锁会让程序一直卡住,程序不再往下执行。只能通过中止并重启的方式来让程序重新执行。要尽可能避免死锁的情况发生 2、造成死锁的原因 互斥条件: 同一资源同时只能由一个线程读…...
flask实现session开发
要在Flask应用中实现会话(session)开发,你可以使用Flask内置的session模块。以下是一个示例代码,演示在Flask应用中启用和使用会话功能: from flask import Flask, session, redirect, url_for, requestapp Flask(__…...
paddle dataset
paddle实现图像旋转 import numpy as np from PIL import Image from matplotlib import pyplot as plt from paddle.vision.transforms import functional as F import cv2imagecv2.imread(./1.jpg) imagecv2.cvtColor(image,cv2.COLOR_BGR2RGB)# 图像旋转 opencv # imgR90 …...
接口自动化测试实战:JMeter+Ant+Jenkins+钉钉机器人群通知完美结合
前言 一、本地JAVA环境安装配置,安装JAVA8和JAVA17 二、安装和配置Jmeter 三、安装和配置ant 四、jmeter + ant配置 五、jenkins安装和配置持续构建项目 六、jenkins配置流程 前言 搭建jmeter+ant+jenkins环境有些前提条件,那就是要先配置好java环境,本地java环境…...
HAL库STM32串口开启DMA接收数据
STM32CubeMx的配置 此博客仅仅作为记录,这个像是有bug一样,有时候好使,有时候不好,所以趁现在好使赶紧记录一下,很多地方用到串口接收数据,DMA又是一种非常好的接收方式,可以节约CPU的时间&…...
Web安全研究(五)
Automated WebAssembly Function Purpose Identification With Semantics-Aware Analysis WWW23 文章结构 introbackgroundsystem design abstraction genapplying abstractionsclassifier data collection and handling data acquisitionstatistics of collected datamodule-…...
2023.11.17-hive调优的常见方式
目录 0.设置hive参数 1.数据压缩 2.hive数据存储格式 3.fetch抓取策略 4.本地模式 5.join优化操作 6.SQL优化(列裁剪,分区裁剪,map端聚合,count(distinct),笛卡尔积) 6.1 列裁剪: 6.2 分区裁剪: 6.3 map端聚合(group by): 6.4 count(distinct): 6.5 笛卡尔积: 7…...
ts 联合react 实现ajax的封装,refreshtoken的功能
react ts混合双打,实现ajax的封装,以及401的特殊处理 import axios from axios import {AMDIN_EXPIRES_KEY,AMDIN_KEY,AMDIN_REFRESH_EXPIRES_KEY,AMDIN_REFRESH_KEY,COMMID_KEY,getToken,removeToken } from ../utils/user-token import { showMessage…...
CISP模拟试题(一)
免责声明 文章仅做经验分享用途,利用本文章所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任,一旦造成后果请自行承担!!! 1.下面关于信息安全保障的说法错误的是:C A.信息安全保障的概念是与信息安全的概念同时产生的 …...
轻量封装WebGPU渲染系统示例<35>- HDR环境数据应用到PBR渲染材质
当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/BasePbrMaterialTest.ts 当前示例运行效果: 微调参数之后的效果: 此示例基于此渲染系统实现,当前示例TypeScript源码如下: export class BasePbrMateri…...
春秋云境靶场CVE-2022-28512漏洞复现(sql手工注入)
文章目录 前言一、CVE-2022-28512靶场简述二、找注入点三、CVE-2022-28512漏洞复现1、判断注入点2、爆显位个数3、爆显位位置4 、爆数据库名5、爆数据库表名6、爆数据库列名7、爆数据库数据 总结 前言 此文章只用于学习和反思巩固sql注入知识,禁止用于做非法攻击。…...
数字化文化的守护之星:十八数藏的非遗创新之道
在数字时代的浪潮中,十八数藏犹如一颗璀璨的守护之星,为传统文化注入了新的生命力。这个非遗创新项目以数字化为工具,以守护为使命,开辟了文化传承的新航道。 十八数藏是文化数字守护的引领者,通过数字技术࿰…...
[机缘参悟-119] :反者道之动与阴阳太极
目录 一、阴阳对立、二元对立的规律 1.1 二元对立 1.2 矛盾的对立与统一 二、阴阳互转、阴阳变化、变化无常 》无序变化和有序趋势的规律 三、阴阳合一、佛魔一体、善恶同源 四、看到积极的一面 五、反者道之动 5.1 概述 5.2 "否极泰来" 5.3 “乐极生悲”…...
Docker搭建Redis集群
Docker搭建Redis集群 创建一个专属redis的网络 docker network create redis --subnet 172.38.0.0/16通过shell脚本创建并启动6个redis服务 #通过脚本一次创建6个redis配置 for port in $(seq 1 6); \ do \ mkdir -p /mydata/redis/node-${port}/conf touch /mydata/redis/n…...
学习Opencv(蝴蝶书/C++)代码——2.OpenCV初探
文章目录 0. 图像读取与显示1. 视频文件读取与操作1.1 示例代码1.1 OpenCV支持的视频格式2. 加入滑动条2.1 示例代码2.2 报错/Warning2.3 关于toolbar3. 简易视频播放器3.1 OpenCV检测方向键被按下3.1.1 Windows下3.1.2 linux下3.1 方向键控制视频变化4. 简单的变换5. 写视频5.…...
基于AVR单片机的便携式心电监测设备设计与实现
基于AVR单片机的便携式心电监测设备是一种常用的医疗设备,用于随时监测和记录人体的心电信号。本文将介绍便携式心电监测设备的设计原理和实现步骤,并提供相应的代码示例。 1. 设计概述 便携式心电监测设备是一种小巧、方便携带的设备,能够…...
微机原理_14
一、单项选择题(本大题共15小题,每小题3分,共45分。在每小题给出的四个备选项中,选出一个正确的答案。) 1,下面寻址方式的操作数不在存储器中的是() A. 堆栈寻址 B. 寄存器间址 C.寄存器寻址 D. 直接寻址 2,条件转移指令JNE的条件是() A. CF…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
