写了一个实时检测皮肤,并且美化的代码,这块怎么优化一下呢?

shiter
人工智能领域优质创作者
博客专家认证
2016-03-04 08:52:06
有点延迟,肤色是判断一个颜色空间,做成一个mask,对于属于这个空间的分割出来像素类似 ,

完后针对皮肤进行滤波,完后把这些肤色copy回原图,纯黑的部分就类似背景了,我感觉加了判断之后,变的很慢。

应该怎么写呢?



//皮肤检测,并针对皮肤进行增强,模糊
void MySkinEnhance(Mat &frame)
{
Mat input_image =frame;
Mat output_mask;
Mat output_image;
Mat mask;
//肤色椭圆
/*椭圆皮肤模型*/
Mat skinCrCbHist = Mat::zeros(Size(256, 256), CV_8UC1);
ellipse(skinCrCbHist, Point(113, 155.6), Size(23.4, 15.2), 43.0, 0.0, 360.0, Scalar(255, 255, 255), -1);

Mat element = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1) );

if(input_image.empty())
return ;

Mat ycrcb_image;
output_mask = Mat::zeros(input_image.size(), CV_8UC1);
cvtColor(input_image, ycrcb_image, CV_BGR2YCrCb); //首先转换成到YCrCb空间

for(int i = 0; i < input_image.rows; i++) //利用椭圆皮肤模型进行皮肤检测
{
uchar* p = (uchar*)output_mask.ptr<uchar>(i);
Vec3b* ycrcb = (Vec3b*)ycrcb_image.ptr<Vec3b>(i);
for(int j = 0; j < input_image.cols; j++)
{
if(skinCrCbHist.at<uchar>(ycrcb[j][1], ycrcb[j][2]) > 0)
p[j] = 255;
}
}

//morphologyEx(output_mask,output_mask,MORPH_CLOSE,element);

//output_mask.setTo(0);

dilate(output_mask,output_mask,Mat(16,16,CV_8U),Point(-1,-1),2);
//imwrite("dilate.jpg",dst);
// output_image.setTo(0);
input_image.copyTo(output_image, output_mask);
//for(int i = 0; i < input_image.rows; i++) //将底色设置为白色
//{
// uchar* p = (uchar*)output_mask.ptr<uchar>(i);
//
// for(int j = 0; j < input_image.cols; j++)
// {
// if((p[j]) == 0)
// {
// output_image.at<Vec3b>(i,j)[0] = 255;
// output_image.at<Vec3b>(i,j)[1] = 255;
// output_image.at<Vec3b>(i,j)[2] = 255;
// }
// }
//}



Mat enhance = output_image;
medianBlur(output_image,enhance,11);
//blur(enhance,enhance,Size(4,4),Point(-1,-1),4);
imshow("blur face",enhance);
for(int i = 0; i < output_image.rows; i++) //
{
uchar* p = (uchar*)output_mask.ptr<uchar>(i);

for(int j = 0; j < output_image.cols; j++)
{
if((enhance.at<Vec3b>(i,j)[0] < 50) && (enhance.at<Vec3b>(i,j)[1] < 50)&& (enhance.at<Vec3b>(i,j)[2] < 50) )
{
//不是纯黑的背景,加了这个判断慢了很多


}
else
{

frame.at<Vec3b>(i,j)[0] = enhance.at<Vec3b>(i,j)[0];

frame.at<Vec3b>(i,j)[1] = enhance.at<Vec3b>(i,j)[1];
frame.at<Vec3b>(i,j)[2] = enhance.at<Vec3b>(i,j)[2];
}
}
}
// 图像融合
//addWeighted(input_image, 0.95, enhance, 0.05, 0.0, input_image);
imshow("ouput image",frame);

}

...全文
303 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2016-03-08
  • 打赏
  • 举报
回复
暴露了楼主的真实形象? 没见婚纱照大多都是曝光过度的吗?
redui 2016-03-06
  • 打赏
  • 举报
回复
MMX指令有饱和和非饱和之分,就是专门对付数据溢出的,设置好模式,不需要你判断 if >255,这是普通CPU指令做不到的
shiter 2016-03-05
  • 打赏
  • 举报
回复
引用 2 楼 redui 的回复:
显然算法需要优化,处理图片像素最忌双重for循环,想不慢都不行,GDI+都做了很多优化还是被人骂太慢。 可选优化方案: 分割图片用多线程并行处理; 设计算法用MMX指令提速; 利用DX/OPENGL或者显卡厂商提供的SDK,用GPU处理大量重复的运算(推荐,但是学习成本高,且需要适配显卡种类)。
引用 3 楼 CharlesSimonyi 的回复:
OpenCV中遍历每个像素的方法有很多,其中at是所有方法中最慢的一种,比直接使用指针慢了50多倍,可以参考下这篇文章: http://blog.csdn.net/xiaowei_cqu/article/details/19839019 换用速度更快的遍历方式,这篇文章底部有一个测试对比数据可以参考下
对,这个还有一个问题就是,比如对一个零到255之间的像素,做了线性变换,比如提高亮度什么的时候,回数据溢出 这时候需要加判断,if >255,就是又从零开始加,这种操作也很费时,我发现 有的性能也是卡在这个地方了
redui 2016-03-05
  • 打赏
  • 举报
回复
显然算法需要优化,处理图片像素最忌双重for循环,想不慢都不行,GDI+都做了很多优化还是被人骂太慢。 可选优化方案: 分割图片用多线程并行处理; 设计算法用MMX指令提速; 利用DX/OPENGL或者显卡厂商提供的SDK,用GPU处理大量重复的运算(推荐,但是学习成本高,且需要适配显卡种类)。
encoderlee 2016-03-05
  • 打赏
  • 举报
回复
OpenCV中遍历每个像素的方法有很多,其中at是所有方法中最慢的一种,比直接使用指针慢了50多倍,可以参考下这篇文章: http://blog.csdn.net/xiaowei_cqu/article/details/19839019 换用速度更快的遍历方式,这篇文章底部有一个测试对比数据可以参考下
shiter 2016-03-04
  • 打赏
  • 举报
回复

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧