当前位置: 首页 > news >正文

影楼精修-肤色统一算法解析

注意:本文样例图片为了避免侵权,均使用AIGC生成;

本文介绍影楼精修中肤色统一算法的实现方案,并以像素蛋糕为例,进行分析说明。

肤色统一就是将人像照片中皮肤区域的颜色进行统一,看起来颜色均匀一致,不会出现颜色不均匀问题。我们以像素蛋糕软件为例,示例图如下:

可以看到,在对人脸和身体进行肤色统一之后,皮肤的颜色一致性变好了不少,给人主观感受更佳。

像素蛋糕的肤色统一功能历经了多个版本的迭代,目前包含AI肤色统一和肤色统一两个版本,同时又将人脸和身体区域做了区分,得到了脸部区域肤色统一和身体区域肤色统一功能调节,从用户或者设计师角度来讲,可控性更强,同时支持了单人和多人的处理。

肤色统一和AI肤色统一功能的差异:可能是AI肤色统一使用了基于深度学习的模型方案,直接自动对皮肤颜色和亮度进行调节,而肤色统一则是基于传统图像处理方案构建的;

我们这里以传统肤色统一为例进行说明。通过效果上的测试,将像素蛋糕的肤色统一特点总结如下:

1.皮肤区域颜色一致性提高,颜色向某个颜色靠拢,而且,这个颜色并非皮肤区域的颜色均值,而是亮度较高的颜色;

2.皮肤暗部区域的亮度会自动调整变亮;

3.人脸和皮肤区域可分开处理;

我们将按照这三个特点来进行实现;

算法方案

假设原图为S,最终效果图为D;

1.对S进行皮肤分割,获得皮肤区域Mask图Mask_skin,这一步需要较高的准确性,皮肤区域为1-255的灰度值,非皮肤区域为0;目前皮肤分割相对比较准确的图片API,如:美图皮肤分割API > 阿里云皮肤分割API;

美图API:https://ai.meitu.com/index?t=1747366168417

阿里云API:https://vision.aliyun.com/experience/detail?tagName=imageseg&children=SegmentSkin

2.对S进行人脸点位检测,根据人脸关键点,计算人脸区域Mask图Mask_face;

3.将肤色统一划分为皮肤区域亮度统一和颜色统一两个模块;

3.1亮度统一,以身体皮肤区域处理为例,对皮肤区域进行基于直方图信息的暗部区域自动亮度矫正;

思路:统计皮肤区域亮度直方图,计算亮度中值,统计亮度低于中值的暗部区域皮肤像素数量,用于动态计算亮度增强程度,根据亮度增强程度,对暗部区域亮度进行矫正,非暗部区域保持不变;

这里给出亮度统一的核心代码:

void SkinBrightenWithHistogram(unsigned char* bgraData, int width, int height, int stride, unsigned char* skinMask) {int size = width * height;float* luminance = (float*)malloc(sizeof(float) * size);int histBins[256] = { 0 };int skinCount = 0;// 1. 提取亮度信息并构建直方图for (int y = 0; y < height; ++y) {unsigned char* row = bgraData + y * stride;for (int x = 0; x < width; ++x, row += 4) {int idx = y * width + x;float r = row[2], g = row[1], b = row[0];float yVal = 0.299f * r + 0.587f * g + 0.114f * b;luminance[idx] = yVal;if (skinMask[idx] > 20) {int bin = (int)CLIP3(yVal, 0, 255);histBins[bin]++;skinCount++;}}}if (skinCount == 0) {free(luminance);return;}// 2. 使用直方图累加计算中值亮度int medianIndex = skinCount / 2;int cumulative = 0;int medianBin = 0;for (int i = 0; i < 256; ++i) {cumulative += histBins[i];if (cumulative >= medianIndex) {medianBin = i;break;}}float medianY = (float)medianBin;// 3. 统计暗部像素数量(亮度 < 中值)int darkCount = 0;for (int i = 0; i < medianBin; ++i) {darkCount += histBins[i];}float darkRatio = (float)darkCount / skinCount;4. 根据暗部比例动态计算增强强度 alpha//float alpha = CLAMP(0.3f + darkRatio * 0.7f, 0.3f, 1.0f);//if (medianY < 80.0f) {//        alpha *= 1.2f;//}//float gamma = 1.2f;// 5. 根据暗部比例动态计算增强强度 alpha(提高提亮效果)float alpha = CLIP3(0.4f + darkRatio * 1.0f, 0.4f, 1.2f);  // 强化基础 alphaif (medianY < 80.0f) {alpha *= 1.4f;  // 放大提亮倍数}else if (medianY < 100.0f) {alpha *= 1.2f;  // 中等放大}float gamma = 1.4f;  // 增加 gamma(让暗部提亮更明显)// 6. 提亮暗部区域for (int y = 0; y < height; ++y) {unsigned char* row = bgraData + y * stride;for (int x = 0; x < width; ++x, row += 4) {int idx = y * width + x;if (skinMask[idx] < 5) continue;float Y = luminance[idx];if (Y < medianY) {float norm = CLIP3(1.0f - (Y / (medianY + 1e-5f)), 0.0f, 1.0f);float boost = alpha * powf(norm, gamma);float newY = CLIP3(Y + boost * medianY, 0, 255);float scale = newY / (Y + 1e-5f);int gray = row[1] * skinMask[idx] / 255;  // 用绿色通道估算灰度用于保色插值for (int c = 0; c < 3; ++c) {float val = row[2 - c] * scale;val = (unsigned char)CLIP3(val, 0, 255);row[2 - c] = (val * gray + row[2 - c] * (255 - gray)) / 255;}}}}free(luminance);
}

3.2颜色统一,基于HSV或Lab颜色空间,计算皮肤区域颜色亮度直方图统计的中值以上的皮肤像素RGB均值,映射到HSV或Lab颜色空间,得到对应H或ab的均值(也可直接统计H或ab的均值);以HSV为例,根据原图皮肤像素的HSV和目标均值HSV,重新映射得到颜色统一为均值颜色后的HSV,然后映射到RGB;

HSV_result=(H_mean, S_src,V_src)

RGB_result=HSV_result---->RGB

4.使用3的方式,分别对人脸区域和身体皮肤区域进行肤色统一,分别得到效果图D_face和D_body;

5.设置人脸区域肤色统一参数k_face,身体肤色统一参数k_body,范围[0,100],将原图S和D_face,D_body进行alpha blend,得到最终效果图D;

上述算法流程就是本人基于传统数字图像处理算法构建的肤色统一算法,效果测试和对比如下:

通过测试效果对比,可以看到,对比原图S,本文算法在脖子等暗部区域亮度有一定的自动校正,同时,人脸和身体皮肤区域的肤色区域一致,基本实现了像素蛋糕类似的功能;

对于AI肤色统一,效果上会比传统方法更自然,同时,对于暗部的亮度矫正也会更准确,后续将陆续进行分析;

http://www.xdnf.cn/news/477523.html

相关文章:

  • 7-15 计算圆周率
  • C++ Kafka客户端(cppkafka)安装与问题解决指南
  • Oracle — 总结
  • 智能接处警系统:以秒级联动响应重塑应急处置效能
  • 使用exceljs将excel文件转化为html预览最佳实践(完整源码)
  • 掌握HTML文件上传:从基础到高级技巧
  • 【HTML 全栈进阶】从语义化到现代 Web 开发实战
  • 数字化工厂升级引擎:Modbus TCP转Profinet网关助力打造柔性生产系统
  • SPL做量化---MTM(动量指数)
  • 在 Ubuntu 20.04 中使用 init.d 或者systemd实现开机自动执行脚本
  • 炼丹学习笔记3---ubuntu2004部署运行openpcdet记录
  • OrangePi Zero 3学习笔记(Android篇)11 - IR遥控器
  • 现在环保方面有什么新的技术动态
  • Qt/C++编写音视频实时通话程序/画中画/设备热插拔/支持本地摄像头和桌面
  • MySQL 8.0 OCP 1Z0-908 121-130题
  • 蓝牙协议架构与调试工具详解(含 BLE、HCI 命令、调试命令)
  • Prometheus实战教程:k8s平台-Mysql监控案例
  • 记一次缓存填坑省市区级联获取的操作
  • 自学嵌入式 day19-数据结构 链表
  • 【前端】构建关系图谱的前端组件推荐
  • SqlHelper 实现类,支持多数据库,提供异步操作、自动重试、事务、存储过程、分页、缓存等功能。
  • 使用哈希表封装myunordered_set和myunordered_map
  • 【Python CGI编程】
  • go-中间件的使用
  • Spring MVC 对 JavaWeb 的优化:从核心组件到注解
  • CentOS系统中升级Python 3.12.2版本
  • 数据通信原理 光纤通信 期末速成
  • 【Umi】项目初始化配置和用户权限
  • Chrome拓展(Chrome Extension)开发定时任务插件
  • 掌握 Kotlin Android 单元测试:MockK 框架深度实践指南