基于人脸68特征点识别的美颜算法(一) 大眼算法 C++

news2024/10/6 2:23:46

1、加载一张原图,并识别人脸的68个特征点

	cv::Mat img = cv::imread("5.jpg");
    // 人脸68特征点的识别函数
	vector<Point2f> points_vec = dectectFace68(img);
    // 大眼效果函数
	Mat dst0 = on_BigEye(800, img, points_vec);

请添加图片描述
2、函数

vector<Point2f> dectectFace68(Mat src)
{
	vector<Point2f> points_vec;
	
	int* pResults = NULL;
	//在检测函数中使用了pBuffer。  
	//如果你调用多个线程中的函数,请为每个线程创建一个缓冲区!  
	unsigned char* pBuffer = (unsigned char*)malloc(DETECT_BUFFER_SIZE);
	if (!pBuffer)
	{
		fprintf(stderr, "Can not alloc buffer.\n");
		//return 100;
	}
	Mat gray;
	cvtColor(src, gray, CV_BGR2GRAY);
	int doLandmark = 1;// do landmark detection  
	pResults = facedetect_multiview_reinforce(pBuffer, (unsigned char*)(gray.ptr(0)), gray.cols, gray.rows, (int)gray.step,
		1.2f, 2, 48, 0, doLandmark);

	int cxa = *pResults;

	ofstream file("facedata.txt", ios::out);
	//打印检测结果 



	if (0 == cxa)
	{
	}
	else
	{
		
		for (int i = 0; i < (pResults ? *pResults : 0); i++)
		{
			
			short* p = ((short*)(pResults + 1)) + 142 * i;
			//rectangle(src, Rect(p[0], p[1], p[2], p[3]), Scalar(0, 255, 0), 2);
			if (doLandmark)
			{
				for (int j = 0; j < 68; j++)
				{
					char c[8];
					_itoa(j, c, 10);
					
					

					Point2f ff(p[6 + 2 * j], p[6 + 2 * j + 1]);
					points_vec.push_back(ff);
					file << ff.x << "\t" << ff.y << endl;

				/*	circle(src, Point((int)p[6 + 2 * j], (int)p[6 + 2 * j + 1]), 3, Scalar(0, 0, 255), 3);
					CvPoint font;
					putText(src, c, Point((int)p[6 + 2 * j], (int)p[6 + 2 * j + 1]), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 23, 0), 1);*/
					
				}
			}
		}


	

	}



	return points_vec;
}




// 双线性插值算法
void BilinearInsert(Mat& src, Mat& dst, float ux, float uy, int i, int j)
{
	auto Abs = [&](float f) {
		return f > 0 ? f : -f;
		};

	int c = src.channels();
	if (c == 3)
	{
		//存储图像得浮点坐标
		CvPoint2D32f uv;
		CvPoint3D32f f1;
		CvPoint3D32f f2;

		//取整数
		int iu = (int)ux;
		int iv = (int)uy;
		uv.x = iu + 1;
		uv.y = iv + 1;

		//step图象像素行的实际宽度  三个通道进行计算(0 , 1 2  三通道)
		f1.x = ((uchar*)(src.data + src.step * iv))[iu * 3] * (1 - Abs(uv.x - iu)) + \
			((uchar*)(src.data + src.step * iv))[(iu + 1) * 3] * (uv.x - iu);
		f1.y = ((uchar*)(src.data + src.step * iv))[iu * 3 + 1] * (1 - Abs(uv.x - iu)) + \
			((uchar*)(src.data + src.step * iv))[(iu + 1) * 3 + 1] * (uv.x - iu);
		f1.z = ((uchar*)(src.data + src.step * iv))[iu * 3 + 2] * (1 - Abs(uv.x - iu)) + \
			((uchar*)(src.data + src.step * iv))[(iu + 1) * 3 + 2] * (uv.x - iu);


		f2.x = ((uchar*)(src.data + src.step * (iv + 1)))[iu * 3] * (1 - Abs(uv.x - iu)) + \
			((uchar*)(src.data + src.step * (iv + 1)))[(iu + 1) * 3] * (uv.x - iu);
		f2.y = ((uchar*)(src.data + src.step * (iv + 1)))[iu * 3 + 1] * (1 - Abs(uv.x - iu)) + \
			((uchar*)(src.data + src.step * (iv + 1)))[(iu + 1) * 3 + 1] * (uv.x - iu);
		f2.z = ((uchar*)(src.data + src.step * (iv + 1)))[iu * 3 + 2] * (1 - Abs(uv.x - iu)) + \
			((uchar*)(src.data + src.step * (iv + 1)))[(iu + 1) * 3 + 2] * (uv.x - iu);

		((uchar*)(dst.data + dst.step * j))[i * 3] = f1.x * (1 - Abs(uv.y - iv)) + f2.x * (Abs(uv.y - iv));  //三个通道进行赋值
		((uchar*)(dst.data + dst.step * j))[i * 3 + 1] = f1.y * (1 - Abs(uv.y - iv)) + f2.y * (Abs(uv.y - iv));
		((uchar*)(dst.data + dst.step * j))[i * 3 + 2] = f1.z * (1 - Abs(uv.y - iv)) + f2.z * (Abs(uv.y - iv));

	}
}


//图像局部缩放算法
void LocalTranslationWarp_Eye(Mat& img, Mat& dst, int warpX, int warpY, int endX, int endY, float radius)
{
	//平移距离 
	float ddradius = radius * radius;
	//计算|m-c|^2
	//size_t mc = (endX - warpX) * (endX - warpX) + (endY - warpY) * (endY - warpY);
	//计算 图像的高  宽 通道数量
	int height = img.rows;
	int width = img.cols;
	int chan = img.channels();

	auto Abs = [&](float f) 
		{
		return f > 0 ? f : -f;
		};

	for (int i = 0; i < width; i++)
	{
		for (int j = 0; j < height; j++)
		{
			// # 计算该点是否在形变圆的范围之内
			//# 优化,第一步,直接判断是会在(startX, startY)的矩阵框中
			if ((Abs(i - warpX) > radius) && (Abs(j - warpY) > radius))
				continue;

			float distance = (i - warpX) * (i - warpX) + (j - warpY) * (j - warpY);
			if (distance < ddradius)
			{
				float rnorm = sqrt(distance) / radius;
				float ratio = 1 - (rnorm - 1) * (rnorm - 1) * 0.5;
				//映射原位置
				float UX = warpX + ratio * (i - warpX);
				float UY = warpY + ratio * (j - warpY);

				//根据双线性插值得到UX UY的值
				BilinearInsert(img, dst, UX, UY, i, j);
			}
		}
	}
}

//大眼效果
Mat on_BigEye(int b, Mat src, vector<Point2f> points_vec)
{
	
	Mat dst = src.clone();


	Point2f left_landmark = points_vec[38];
	Point2f	left_landmark_down = points_vec[27];

	Point2f	right_landmark = points_vec[44];
	Point2f	right_landmark_down = points_vec[27];

	Point2f	endPt = points_vec[30];

	//# 计算第4个点到第6个点的距离作为距离
	/*float r_left = sqrt(
		(left_landmark.x - left_landmark_down.x) * (left_landmark.x - left_landmark_down.x) +
		(left_landmark.y - left_landmark_down.y) * (left_landmark.y - left_landmark_down.y));
	cout << "左眼距离:" << r_left;*/
	float r_left = b;

	//	# 计算第14个点到第16个点的距离作为距离
	//float	r_right = sqrt(
	//	(right_landmark.x - right_landmark_down.x) * (right_landmark.x - right_landmark_down.x) +
	//	(right_landmark.y - right_landmark_down.y) * (right_landmark.y - right_landmark_down.y));
	//cout << "右眼距离:" << r_right;
	float r_right = b;
	//	# 瘦左                     
	//LocalTranslationWarp_Eye(src, dst, left_landmark.x, left_landmark.y, endPt.x, endPt.y, r_left);
	//	# 瘦右
	LocalTranslationWarp_Eye(src, dst, right_landmark.x, right_landmark.y, endPt.x, endPt.y, r_right);


	return dst;
}

3、图像结果
请添加图片描述
大眼睛结果
请添加图片描述

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

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

相关文章

BMA580 运动传感器

型号简介 BMA580是博世&#xff08;bosch-sensortec&#xff09;的一款先进的、超小型加速度传感器。具有独特的骨传导语音活动检测功能和先进的功率模式功能&#xff0c;是世界上最小的加速度传感器&#xff08;1.2 x 0.8 x 0.55 mm&#xff09;。它专为紧凑型设备&#xff08…

Query Rewriting for Retrieval-Augmented Large Language Models

文章目录 题目摘要方法实验 题目 检索增强大语言模型的查询重写 论文地址&#xff1a;https://arxiv.org/abs/2305.14283 项目地址&#xff1a;https://github.com/xbmxb/RAG-query-rewriting 摘要 大语言模型&#xff08;LLM&#xff09;在检索--然后阅读&#xff08;retriev…

Hack The Box-Blazorized

总体思路 Blazor JWT->SPN劫持->登录脚本劫持->DCSync 信息收集&端口利用 nmap -sSVC blazorized.htbStarting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-01 02:37 EDT Nmap scan report for blazorized.htb (10.10.11.22) Host is up (0.30s latency). N…

【网络安全】修改Host文件实现域名解析

场景 开发一个网站或者服务&#xff0c;需要在本地测试时&#xff0c;可以将线上的域名指向本地开发环境的IP地址。从而模拟真实环境中的域名访问&#xff0c;方便调试和开发。 步骤 1、以管理员身份打开命令提示符 2、编辑hosts文件&#xff1a; 输入以下命令打开hosts文…

云卓SKYDROID-H12PRO——只有你想不到的,没有我们做不到的

H12PRO采用高通八核处理器&#xff0c;搭载安卓嵌入式系统&#xff0c;采用先进的OFDM技术&#xff0c;和超级协议栈。让图像更加清晰&#xff0c;延迟更低&#xff0c;距离更远&#xff0c;抗干扰性更强&#xff0c;并支持1080P视频传输。支持SIM、数字摄像头、串口、s.bus、网…

SQL注入实战

1、orderBy报错注入 某大学 www.target.com?orderBy1 注入为orderBy注入&#xff0c;将orderby更改为id测试时并不能造成报错回显故不能当注入点 正常状态下 经过测试可知共14列&#xff0c;orderBy15时报错&#xff0c;由于列名可控?orderby$id 这里使用XPath报错注入&a…

放大器的输入电容Cin对放大电路的影响

1、OPA859构成的放大电路的设计 图中OPA859的增益G设定为1.16 &#xff0c;OPA859的增益带宽积GBP 900M , 放大器的带宽BW GBP / Acl 900 / 1.16 775.86M。 图&#xff1a;OPA859放大电路 由于需要在放大电路上加带宽的限制&#xff0c;所以在OPA859放大电路上有个低通限…

Java + MySQL 实现存储完整 Json

Java + MySQL 实现存储完整 Json 一、应用场景二、数据库配置三、后端代码配置1、实体类2、Service 实现类3、xml 文件四、测试1、新增接口2、查询接口3、数据表内容一、应用场景 将前端传过来的 Json 完整存储到 MySQL 中,涉及技术栈为 Java、MyBatis、MySQL。 注意:MySQL…

idea xml ctrl+/ 注释格式不对齐

处理前 处理后 解决办法 取消这两个勾选

LabVIEW代码性能优化

优化LabVIEW代码以提高软件性能是确保系统高效运行的关键。通过分析代码结构、数据管理、并行处理、内存使用和硬件资源的有效利用&#xff0c;我们可以从多个角度提升LabVIEW程序的执行速度和稳定性。 代码结构优化 模块化编程 将复杂的程序分解成多个子VI&#xff0c;每个子V…

Linux系统中交叉编译opencv库

目标&#xff1a;将opencv进行交叉编译&#xff0c;使其能在rk3326板子上运行使用。 环境&#xff1a; ubuntu&#xff1a;18.04 opencv:4.5.4 opencv源码从挂网下载&#xff1a;opencv源码下载地址 交叉编译链&#xff1a;gcc-arm-10.3-linux-gun 一.环境准备 1.交叉编译链我…

论文学习——使用基于多项式拟合的预测算法求解动态多目标问题

论文题目&#xff1a;Solving dynamic multi-objective problems using polynomial fitting-based prediction algorithm 使用基于多项式拟合的预测算法求解动态多目标问题&#xff08;Qingyang Zhang , Xiangyu He,Shengxiang Yang , Yongquan Dong , Hui Song , Shouyong Ji…

shopify后台设置为中文

shopify官网&#xff1a;https://link.juejin.cn/?targethttps%3A%2F%2Fshopify.dev%2F 1、点击右上角头像 2、选择个人资料 3、找到Language设置 开发者 1、创建开发商店 2、 3、点击左侧导航在线商店&#xff0c;点击右上角查看你的商店。在线商店链接为https://[商店名…

【FPGA 学习与实践】<初阶> 项目周计划

第1-2周&#xff1a;基础项目 - 4位加法器和计数器 目标&#xff1a;掌握Verilog基本语法和模块设计。 第1周&#xff1a; 学习Verilog的基本语法和结构&#xff08;模块、端口、数据类型&#xff09;。设计并实现一个4位加法器。编写测试平台&#xff08;Testbench&#xff0…

38、shell之免交互

免交互 交互&#xff1a;我们发出指令控制程序的运行&#xff0c;程序在接收到指令之后按照指令的效果做出对应的反应。 免交互&#xff1a;间接的&#xff0c;通过第三方的方式把指令传送给程序&#xff0c;不用直接的下达指令。 一、Here Document 免交互&#xff1a; 这…

谈谈在不同公司中的SAP职位

今天反客为主&#xff0c;聊一下这个HR的话题&#xff0c;考虑到SAP职位的专业性&#xff0c;感觉还是有必要谈一谈这个话题。最近跟几位HR的小伙伴聊了一下&#xff0c;讨论了下不同公司的SAP职位的招聘要求&#xff0c;感觉还是有那么几个存在的问题&#xff1a; 追求完美的…

goframe框架规范限制(but it should be named with “Res“ suffix like “XxxRes“)

背景&#xff1a; 首页公司最近要启动一个项目&#xff0c;公司主要业务是用java开发的&#xff0c;但是目前这个方向的项目&#xff0c;公司要求部署在主机上&#xff0c;就是普通的一台电脑上&#xff0c;电脑配置不详&#xff0c;还有经常开关机&#xff0c;所以用java面临…

Python实现万花筒效果:创造炫目的动态图案

文章目录 引言准备工作前置条件 代码实现与解析导入必要的库初始化Pygame定义绘制万花筒图案的函数主循环 完整代码 引言 万花筒效果通过反射和旋转图案创造出美丽的对称图案。在这篇博客中&#xff0c;我们将使用Python来实现一个动态的万花筒效果。通过利用Pygame库&#xf…

WebStorm配置路径别名(jsconfig.json)

项目是 ViteVueTs 新建一个 jsconfig.json文件 {"compilerOptions": {"baseUrl": ".","paths": {"/*": ["./src/*"]}},"exclude": ["node_modules", "dist"] }然后在 vite.confi…

LLM-Transformer:经典与前沿方法详解

LLM-Transformer&#xff1a;经典与前沿方法详解 前言 大规模语言模型&#xff08;LLM&#xff09;是当前自然语言处理&#xff08;NLP&#xff09;领域的核心技术&#xff0c;而Transformer架构作为LLM的基础&#xff0c;极大地推动了这一领域的发展。本文将详细介绍LLM-Tra…