查阅了博客上绝大多数关于皮肤分割和磨皮美颜的算法,然后自己找了各位博主的代码,有自己将各部分代码组合修改调试,最终写了份参照代码。至于引用哪些博主的代码,找的博客太多分不清楚了,有博主看到引用代码可以私聊我加上你的引用。我感觉做出来的效果不太好,不如别人算法效果好。此代码只是做了皮肤分割和滤波磨皮,美白的代码还没写。还有就是发布文章我不太懂它的分类选项,只好随便选了。发布文章的规则我也不懂,有什么问题可以给我说下。

代码如下:


#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgproc/imgproc_c.h>
#include <opencv2/imgproc/types_c.h>
#include <iostream>
#include <vector>  using namespace std;
using namespace cv;//椭圆检测
Mat ellipse_detect(Mat &src)
{Mat img = src.clone();Mat skinCrCbHist = Mat::zeros(Size(256, 256), CV_8UC1);//256*256的矩阵,相当于CrCb分量的横纵坐标//利用Opencv自带的椭圆生成函数生成一个肤色椭圆模型ellipse(skinCrCbHist, Point(113, 155.6), Size(23.4, 15.2), 43.0, 0.0, 360.0, Scalar(255, 255, 255), -1);Mat ycrcb_image;Mat output_mask = Mat::zeros(img.size(), CV_8UC1);cvtColor(img, ycrcb_image, CV_BGR2YCrCb); //首先转换成到YCrCb空间for (int i = 0; i < img.cols; i++){for (int j = 0; j < img.rows; j++){Vec3b ycrcb = ycrcb_image.at<Vec3b>(j, i);if (skinCrCbHist.at<uchar>(ycrcb[1], ycrcb[2]) > 0)//如果该点落在皮肤模型椭圆区域内,则该点是皮肤像素点。output_mask.at<uchar>(j, i) = 255;}}return output_mask;
}/*YCrCb颜色空间Cr分量+Otsu法*/
Mat YCrCb_Otsu_detect(Mat& src)
{Mat ycrcb_image;cvtColor(src, ycrcb_image, CV_BGR2YCrCb); //首先转换成到YCrCb空间vector<Mat> channels;split(ycrcb_image, channels);//分割颜色通道Mat output_mask = channels[1];//取Cr通道的图像threshold(output_mask, output_mask, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);//自动阈值分割return output_mask;}Mat YCrCb_detect(Mat &src)//矩形区域分割
{Mat img = src.clone();Mat skinCrCbHist = Mat::zeros(Size(256, 256), CV_8UC1);//256*256的矩阵,相当于CrCb分量的横纵坐标//利用Opencv自带的椭圆生成函数生成一个肤色椭圆模型ellipse(skinCrCbHist, Point(113, 155.6), Size(23.4, 15.2), 43.0, 0.0, 360.0, Scalar(255, 255, 255), -1);Mat ycrcb_image;Mat output_mask = Mat::zeros(img.size(), CV_8UC1);cvtColor(img, ycrcb_image, CV_BGR2YCrCb); //首先转换成到YCrCb空间for (int i = 0; i < img.cols; i++){for (int j = 0; j < img.rows; j++){Vec3b ycrcb = ycrcb_image.at<Vec3b>(j, i);if ((ycrcb[1] > 137) && (ycrcb[1] < 175) && (ycrcb[2] > 100) && (ycrcb[2] < 118))output_mask.at<uchar>(j, i) = 255;//皮肤区域}}return output_mask;}//锐化函数
Mat sharpen(Mat imageSrc, double threshold, double amount)
{Mat blurred;double sigma = 1;GaussianBlur(imageSrc, blurred, Size(), sigma, sigma);//int depth = CV_MAT_DEPTH(imageSrc.type());Mat lowContrastMask = abs(imageSrc - blurred) < threshold;Mat dst = imageSrc*(1 + amount) + blurred*(-amount);      //original + (original - blurred) * amountimageSrc.copyTo(dst, lowContrastMask);                  //将imageSrc中lowContrastMask对应的非0部分复制到dst中//lowContrastMask等于1时,说明高频分量比较小,有可能是噪声,此时不做锐化return dst;
}Mat skinDivision(Mat ima)
{Mat detect0, detect1, detect2;各分割结果均返回灰度图mask矩形分割//Mat mer = YCrCb_detect(ima);//imshow("矩形分割", detect0);椭圆分割//resize(ima, ima, Size(ima.cols / 2, ima.rows / 2));//Mat mer = ellipse_detect(ima);//imshow("椭圆分割", detect1);//Cr+Otsu法阈值分割Mat mer = YCrCb_Otsu_detect(ima);imshow("阈值分割", mer);return mer;
}Mat wave(Mat detect)//滤波函数
{Mat ret = detect.clone();//int g_nBilateralFilterValue = 25;  //双边滤波参数值,连通域大小//bilateralFilter(ret, detect, 40, g_nBilateralFilterValue * 2, g_nBilateralFilterValue / 2);//ret结果图,detect输入int value1 = 3, value2 = 3;int dx = value1 * 5;    //双边滤波参数之一double fc = value1*12.5; //双边滤波参数之一int p = 50;//透明度Mat temp2;//双边滤波bilateralFilter(ret, detect, dx, fc, fc);temp2 = (detect - ret + 128);//高斯模糊GaussianBlur(temp2, temp2, Size(2 * value2 - 1, 2 * value2 - 1), 0, 0);temp2 = ret + 2 * temp2 - 255;ret = (ret*(100 - p) + temp2*p) / 100;return ret;
}int main()
{Mat srcImage = imread("d:\\4.jpg");if (!srcImage.data){printf("could not load image...\n");return -1;}imshow("原图", srcImage);Mat mer = skinDivision(srcImage);//肤色分割的maskMat detect;srcImage.copyTo(detect, mer);//返回肤色分割图detectimshow("肤色分割", detect);//皮肤区域磨皮Mat ret = wave(detect);//滤波函数float w = 0.3;//滤波图像和原图像选择性结合,把背景和皮肤区域结合for (int i = 0; i < detect.rows ; i++){for (int j = 0; j < detect.cols ; j++){if(mer.at<uchar>(i, j) == 0)ret.at<Vec3b>(i, j) = srcImage.at<Vec3b>(i, j);else{ret.at<Vec3b>(i, j) = w*srcImage.at<Vec3b>(i, j) + (1-w)*detect.at<Vec3b>(i, j);}}}imshow("双边滤波", ret);ret=sharpen(ret,1 ,1); imshow("锐化", ret);waitKey(0);return 0;}

注释的部分代码是自己调试使用的,其中有关于使用不同皮肤分割的算法。
各位有什么问题可以一起交流呀!

基于皮肤分割的磨皮算法相关推荐

  1. 技术的真相 | 基于双边滤波的磨皮算法及优化

    一.背景简介 现在视频类应用非常火热,直播.美妆.医美应用层出不穷.用户们在使用这类应用时都希望自己在屏幕上的样子美美的,皮肤细腻光滑.本文就介绍一种实现简单.效果很好的磨皮算法以及对它的优化思路. ...

  2. java opencv磨皮算法_深度学习AI美颜系列 - AI美颜磨皮算法[转]

    原文:OpenCV学堂 原创作者:胡耀武 转载,以学习,记录,备忘. 这里先放对比结果图,原图来自网络: 1. 算法的流程 [1] - 皮肤分割算法 [2] - 人脸关键点识别算法 [3] - 基于皮 ...

  3. 深度学习AI美颜系列---AI美颜磨皮算法二

    这里先放两张对比结果图,原图来自网络: 算法的流程如下: 1,皮肤分割算法: 目前主流的语义分割等都可以实现,准确度要求较高.本人使用U-net和PSPNet. 2,人脸关键点识别算法: 这一步可以使 ...

  4. 4种基于像素分割的文本检测算法

    摘要:文本检测是文本读取识别的第一步,对后续的文本识别有着重大的影响.一般场景下,可以通过对通用目标检测算法进行配置修改,来实现对文本行的检测定位.本文主要介绍基于像素分割的文本检测算法. 本文分享自 ...

  5. 空间中的语义直线检测_基于语义分割的车道线检测算法研究

    龙源期刊网 http://www.qikan.com.cn 基于语义分割的车道线检测算法研究 作者:张道芳 张儒良 来源:<科技创新与应用> 2019 年第 06 期 摘 ; 要:随着半自 ...

  6. 【Matlab】基于皮肤概率建模的人脸检测算法雏形

    原理 通过色度计算图像中每个像素点是皮肤的概率,当概率大于某一值时就确定这个像素点是皮肤,并将它涂白,其余不是皮肤的像素点涂黑:对图像做适当处理后,把图像中不是脸部皮肤的区域分割开,随后把脸部特征还原 ...

  7. 基于颜色分割的盲道识别算法

    基于颜色分割的盲道识别算法 前言   本任务的要求是通过相关算法识别出城市区域中的盲道,通过对各种盲道进行调研,发现目前城市中的盲道基本分为两大部分,一类是具有明显样色和纹理特征的盲道,通常是黄色(当 ...

  8. 基于边缘检测的磨皮算法实现——OpenGL版

    一.背景 人脸磨皮算法的本质是模糊算法,但是与模糊算法最大的区别是,磨皮算法需要考虑保边效果,需要达到"磨皮了但又保留了脸部的各种纹理细节和边缘信息"的效果.保边的思路甚至与模糊的 ...

  9. 双边滤波的人脸磨皮算法(宋茜)

    本文将介绍双边滤波的原理以及在人脸磨皮中的应用. 文章目录 双边滤波原理 人脸磨皮算法 双边滤波原理 双边滤波器是保边滤波器中广为人知的一种.保边滤波器指在滤波过程中能够有效的保留图片中的边缘信息的一 ...

最新文章

  1. Radware:当前,CDN安全远远不足
  2. 第十章 基本数据结构——栈和队列
  3. win7删除计算机库文件,win7怎么将“库”从资源管理器导航栏中删除【图文】
  4. python if条件思维导图_跟老齐学Python之从if开始语句的征程
  5. CTR点击率预估干货分享
  6. C语言课后习题(23)
  7. 数据绑定控件Reperter
  8. 金山打字通五笔介绍及讲解
  9. PostgreSQL中的索引—9(BRIN)
  10. 面对复杂问题时,系统思考助你理解问题本质
  11. 地图制图领域使用计算机优点在于哪些方面,电子地图制图的运用与发展
  12. 京东 PC 首页 2019 改版前端总结
  13. IEC60870-5-104的解析方法
  14. 安装纯净版win系统
  15. mysql 高手_求mysql高手
  16. css强制换行和禁止换行
  17. java简单通讯录的实现02person类_java实现简单控制台通讯录
  18. RGBA 转 RGB
  19. 【ARM】寄存器与异常——第二篇
  20. 3DMAX经典问答---材质部分(3)

热门文章

  1. WEKA进行Apriori、FP-Tree、K-means算法测试
  2. HDLBits刷题全记录(五)
  3. 最强【网络安全】是哪些大学?看一下一流网络安全学院建设高校
  4. Android studio app启动时默认启动页面为自定义界面
  5. Samba服务器搭建,win10拒绝访问解决方法
  6. 一个程序员老总的年终总结2010版 1
  7. widget中文技术文档
  8. pytorch gpu安装 torch.cuda.is_available()是true才成
  9. oracle复杂语句练习
  10. 2018~2019学年第一学期期末考试试卷(A)卷《C语言程序设计》