Tags:DIP
HSV 颜色阈值分割
先将图像转换到HSV空间,然后在HSV空间进行阈值分割
两种颜色阈值都可以试试:
[0,10,60]
[20,150,255]
[7,10,60]
[20,150,255]
YCrCb 颜色阈值分割
经验而言, 黄种人皮肤像素值在Cr, Cb空间的分布为:Cr 133-173, Cb 77-127
至于为什么选择YCrCb空间以及阈值的确定, 可以参考这篇论文A New Fast Skin Color Detection Technique .
基于椭圆皮肤模型的YCrCb空间检测
可以参考这篇文章: https://www.cnblogs.com/skyfsm/p/7868877.html
YCrCb + OStu 自动阈值分割
也是主要参考👆那篇文章.
先将RGB图像转换到YCrCb颜色空间,提取Cr分量图像,然后对Cr做自二值化阈值分割处理
参考代码:
Mat ycrcb_image;
cvtColor(src, ycrcb_image, COLOR_BGR2YCrCb); //首先转换成到YCrCb空间
Mat detect;
vector<Mat> channels;
split(ycrcb_image, channels);
Mat output_mask = channels[1];
// imshow("YCrCb", output_mask);
threshold(output_mask, output_mask, 0, 255, THRESH_BINARY | THRESH_OTSU);
src.copyTo(detect, output_mask);
dlib 关键点定位
此外可以考虑使用dlib中的关键点定位模型,得到人脸的keypoints然后使用这些关键点对人脸的形状进行逼近,从而得到人脸区域。这种方法鲁棒性比较好,但是问题有两点:无法定位额头区域,需要自己推测;由关键点逼近人脸区域存在误差,特别是在边缘区域的误差会对效果造成较大的影响。
如:
原图:
dlib关键点信息:
由关键点得到的mask,
综合以上几种方法和自己的经验,暂时觉得在YCrCb空间进行颜色分割是比较靠谱的方法,当然得到的初步mask需要进行很多处理,这里就不细说了。看几组结果吧:
第一组:
第二组:
第三组:
由上至下分别为HSV, YCrCb_OStu分割, YCrCb阈值分割
基于神经网络的分割
实际上除了以上这些传统的分割方法,现在很多产品都是基于神经网络进行分割,皮肤分割只是portrait segmentation的一个子问题,只要由足够的训练样本和网络的速度足够快,可以取得非常好的分割效果。
这种方法的主要问题一是需要足够多的训练样本,二是速度限制,毕竟分割完成之后还需要进行进一步处理(各种美颜算法),效果可以很好,但是对技术的要求也很高。
下次贴一张我自己用分割网络做的人脸分割的效果图。