思路:思路很简单,前面有一篇讲了如何利用3000fps检测人脸特征点,把特征点检测出来之后,就有了人脸的大概轮廓。如下图。

上图只是显示了部分特征点,从0-16个特征点可以知道大概的脸型。
但是还有上半部分没有特征点,无法确定头发部分。怎么办呢?通过查看文献,其中这篇论文《Face Image Quality Assessment Based on Learning to Rank》提到了一个方法把人脸抠出来,然后对齐。
如下图

图中(a)是一般的框人脸方法,图(b)是通过人脸的四个眼角,两个嘴角特征点画出一个圆,然后图(c)人眼睛的四个眼角确定矩形框的倾斜角度,矩形的长和宽是4r和2.4r时效果最好,对齐之后的效果图中(efg)。
借鉴这种画圆求半径的思想,那我能不能利用这个半径再往上取一个矩形框呢?
于是动手试了一下,效果如下图。

效果还可以啊,换一张图试一下。

测试了很多张图片效果都还行。于是就才用这种方法了。
下面是核心代码,比较多测试时用的注释哈,将就看一下,使用起来也方便。后续我会将代码放在github上,有兴趣可以去看看。

void Detection( std::vector<cv::String> files) {LBFRegressor regressor;extern string cascadeName;CascadeClassifier cascade;double scale = 1.0;int i = 0;regressor.Load(modelPath + "LBF.model");// -- 1. Load the cascadesif (!cascade.load(cascadeName)) {cerr << "ERROR: Could not load classifier cascade" << endl;}const static Scalar colors[] = { CV_RGB(0,0,255),CV_RGB(0,128,255),CV_RGB(0,255,255),CV_RGB(0,255,0),CV_RGB(255,128,0),CV_RGB(255,255,0),CV_RGB(255,0,0),CV_RGB(255,0,255) };int count = files.size();for (int j = 0; j < count; j++){Mat gray;double t = 0;vector<Rect> faces;//vector<double> polygonX;//多边形轮廓点集合//vector<double> polygonY;vector<Point> polygon;Mat img = imread(files[j]);cvtColor(img, gray, CV_BGR2GRAY);// --Detectiont = (double)cvGetTickCount();//cascade.detectMultiScale(gray, faces,//  1.1, 2, 0//  //|CV_HAAR_FIND_BIGGEST_OBJECT//  //|CV_HAAR_DO_ROUGH_SEARCH//  | CV_HAAR_SCALE_IMAGE//  ,//  Size(30, 30));cascade.detectMultiScale(gray, faces, 1.3, 1, 0, Size(30, 30));t = (double)cvGetTickCount() - t;printf("detection time = %g ms\n", t / ((double)cvGetTickFrequency()*1000.));// --Alignmentt = (double)cvGetTickCount();//检测到超过一个人脸,则只计算一个人脸的特征,因为送入的图片本身就只包含一张人脸,检测出现两个//人脸,则检测出错,所以加facesize,保证只检测大的人脸特征点。不然特征点会多于18个,绘制的roi中间//会被挖空。//for (vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++) {for (vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r= faces.end(), i++) {Point center;Scalar color = colors[i % 8];BoundingBox boundingbox;boundingbox.start_x = r->x*scale;boundingbox.start_y = r->y*scale;boundingbox.width = (r->width - 1)*scale;boundingbox.height = (r->height - 1)*scale;boundingbox.centroid_x = boundingbox.start_x + boundingbox.width / 2.0;boundingbox.centroid_y = boundingbox.start_y + boundingbox.height / 2.0;t = (double)cvGetTickCount();Mat_<double> current_shape = regressor.Predict(gray, boundingbox, 1);t = (double)cvGetTickCount() - t;printf("alignment time = %g ms\n", t / ((double)cvGetTickFrequency()*1000.));//        // draw bounding box//        rectangle(img, cvPoint(boundingbox.start_x,boundingbox.start_y),//                  cvPoint(boundingbox.start_x+boundingbox.width,boundingbox.start_y+boundingbox.height),Scalar(0,255,0), 1, 8, 0);// draw result :: reddouble deta = current_shape(0, 0) - current_shape(15, 0);double rec_point1_y = current_shape(0, 1) + deta / 2;//第0个特征点与第15个特征点的差值的一般作为矩形的宽double rec_point1_x = current_shape(0, 0);//如果超过则赋值为0,到图片边界if (rec_point1_x < 0) { rec_point1_x = 0.0; }if (rec_point1_y < 0) { rec_point1_y = 0.0; }Point  rec_point1 = Point(rec_point1_x, rec_point1_y);//对角线两个点Point  rec_point2 = Point(current_shape(16, 0), current_shape(16, 1));Point  rec_point3 = Point(rec_point1_x, current_shape(16, 1));Point  rec_point4 = Point(current_shape(16, 0), rec_point1_y);polygon.push_back(rec_point1);polygon.push_back(rec_point3);//cout << deta << endl;//cout << rec_point1 << endl;//cout << rec_point2<< endl;//rectangle(img, rec_point1, rec_point2, Scalar(255, 255, 0), 2, 8, 0);for (int i = 0; i <16 /*global_params.landmark_num*/; i++) {//circle(img, Point2d(current_shape(i, 0), current_shape(i, 1)), 3, Scalar(255, 255, 255), -1, 8, 0);//cout << current_shape(i, 0) << endl;//cout << current_shape(i, 1) << endl;//cout << global_params.landmark_num << endl;Point pp = Point (current_shape(i, 0), current_shape(i, 1));Point pp2 = Point (current_shape(i+1, 0), current_shape(i+1, 1));//putText(img, std::to_string(i), pp, FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 0, 255),1, 4);//在图片上写文字//cout << std::to_string(i)<<pp << endl;//cout << pp << endl;//line(img, pp,pp2, Scalar(255, 255, 0),2);//imshow("底板", img);//polygonX.push_back(current_shape(i, 0));//添加多边形轮廓点//polygonY.push_back(current_shape(i, 1));//添加多边形轮廓点polygon.push_back(pp);//cout << polygonX[i] << endl;//waitKey(300);}//double deta = current_shape(0, 0) - current_shape(15, 0);//double rec_point1_y = current_shape(0, 1) + deta / 2;//第0个特征点与第15个特征点的差值的一般作为矩形的宽//double rec_point1_x = current_shape(0, 0);如果超过则赋值为0,到图片边界//if (rec_point1_x < 0) { rec_point1_x = 0.0; }//if (rec_point1_y < 0) { rec_point1_y = 0.0; }//Point  rec_point1 = Point(rec_point1_x, rec_point1_y);//对角线两个点//Point  rec_point2 = Point(current_shape(16, 0), current_shape(16, 1));//Point  rec_point3 = Point(rec_point1_x, current_shape(16, 1));//Point  rec_point4 = Point(current_shape(16, 0), rec_point1_y);cout << deta << endl;cout << rec_point1 << endl;cout << rec_point2<< endl;//rectangle(img, rec_point1,rec_point2,Scalar(255,255,0), 2, 8, 0);//line(img, Point(current_shape(36,0),current_shape(36,1)), Point(current_shape(45,0),current_shape(45,1)), Scalar(255, 255, 0), 2);//cv::imshow("result", img);//waitKey(300);polygon.push_back(rec_point2);polygon.push_back(rec_point4);//cout << files[j] << endl;string depthFace_dir, RGBFace_dir;string roi_depthFace_dir, roi_RGBFace_dir;//抠出的人脸轮廓//depthFace_dir = files[j];//RGB图片绝对路径RGBFace_dir = files[j];//RGB图片绝对路径//depthFace_dir.replace()depthFace_dir = string_replace(RGBFace_dir, "RGBFace", "DepthFace");depthFace_dir = string_replace(depthFace_dir, "jpg", "png");Mat Depth_image = imread(depthFace_dir, CV_LOAD_IMAGE_UNCHANGED);//读取CV_16UC1类型的数据//cout << depthFace_dir << endl;if (!Depth_image.empty()) {Mat roi_depthFace = contour_roi(Depth_image, polygon);//新建一个roi_depthFace_dir文件夹,用于保存处理后的深度图片roi_depthFace_dir = string_replace(depthFace_dir, "DepthFace", "roi_DepthFace");//cout << roi_depthFace_dir << endl;imwrite(roi_depthFace_dir, roi_depthFace);Mat roi_RGBFace = contour_roi(img, polygon);//新建一个roi_RGBFace_dir文件夹,用于保存处理后的RGB图片//保存这个图是为了方便删除抠出的人脸是无效的,可以直接删除roi_RGBFace_dir = string_replace(RGBFace_dir, "RGBFace", "roi_RGBFace");//cout << roi_RGBFace_dir << endl;imwrite(roi_RGBFace_dir, roi_RGBFace);}else {cout << depthFace_dir << endl;ofstream out;out.open("E:/学习/深度学习/活体检测/数据集/Captrue_Data/dataset/real/read_image_emtpy.txt",ios::out);out << depthFace_dir << "\n";continue;}}//cv::imshow("result", img);//waitKey(10);//Mat image = imread("E:/201842516518997.png", CV_LOAD_IMAGE_UNCHANGED);//CV_16UC1类型的数据//读取16位的深度图//waitKey(100);//waitKey(100);}}

利用3000fps把人脸面部抠出来(一)相关推荐

  1. 在线会议中人脸面部轮廓图像提取(三)——Dlib库人脸面部轮廓图像特征提取

    前言:所使用图片并无盈利等目的,如有侵犯他人肖像权请联系删除. 当当当当,第三期来廖!接上一期在线会议中人脸面部轮廓图像提取(二)--HOG人脸面部轮廓图像特征提取,介绍完HOG特征提取我们继续学习D ...

  2. python爬虫背景_利用Python代码实现一键抠背景功能

    前言 又是一个逛csdn发现的一个有趣的小项目,可以一键抠背景,需要用到removebg模块及其API,API可从其官网免费获取,网址如下https://www.remove.bg/zh ps:加上/ ...

  3. python实现背景抠除_利用Python代码实现一键抠背景功能

    这篇文章主要给大家介绍了关于如何利用Python代码实现一键抠背景的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Python具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧 前 ...

  4. 利用OpenCV实现人脸检测

    如何在一副图片中检测到人脸,这涉及到计算机图形学中一些非常复杂的计算,如果这些计算都靠程序员自己来编程,那么工作量就相当大.OpenCV全称是Open Computer Vision,是指开放的计算机 ...

  5. 利用百度进行人脸搜索

       感谢优秀的你打开了小白的文章 "希望在看文章的你今天又进步了一点点,离美好生活更近一步!" 目录 前言 实例代码 返回结果 选择要识别的人脸照片 人脸搜索 前言 在上一篇文章 ...

  6. java调起本地摄像头,利用openCV进行人脸识别(一)

    嗨咯,又好久没有更新了.今天写个前阵子做的人脸识别程序.该程序客户端基于Jave JFrame 客户端的主要作用是,调用电脑的摄像头(我的直接调用笔记本摄像头),然后回显摄像头录取的信息,再利用ope ...

  7. 【百度大脑新品体验】人脸面部动作识别

    [百度大脑新品体验]人脸面部动作识别 作者:busyboxs 最近在尝试做一个类似于 Facedance challenge 的应用,这个应用需要识别人脸五官的动作.目前可能的解决方法就是通过对关键点 ...

  8. python opencv调用摄像头并追踪移动物体,浅析Python+OpenCV使用摄像头追踪人脸面部血液变化实现脉搏评估...

    使用摄像头追踪人脸由于血液流动引起的面部色素的微小变化实现实时脉搏评估. 效果如下(演示视频): 由于这是通过比较面部色素的变化评估脉搏所以光线.人体移动.不同角度.不同电脑摄像头等因素均会影响评估效 ...

  9. 开启android人脸解锁,vivos1pro如何开启人脸面部解锁?

    想必大家会有一个问题,vivoS1pro怎么设置人脸解锁?时尚的潮流滚滚向前,指纹解锁现在已经不是最时尚的了!时尚的我们已经开始人脸解锁了,特此为大家带来vivoS1pro怎么人脸解锁具体方法教程,感 ...

最新文章

  1. TCP网络那点破事!三次握手、四次挥手、TIME-WAIT、HTTP 2.0 ....
  2. 段永朝:界面——之内、之外与之间
  3. 晚上,睡前只需1分钟,一觉到天亮!
  4. 如何阅读微控制器数据手册:简介和第一步
  5. CTFshow 信息收集 web7
  6. 启用nginx status状态详解
  7. Linux环境部署jenkins
  8. python(numpy,pandas10)——pandas 合并数据 concat,append
  9. 入门前端学习路线图【送书】
  10. JavaScript浮点运算0.2+0.1 !== 0.3
  11. 特斯拉全自动驾驶订阅包来了:199美元包月 老用户99美元
  12. 最适合说故事的插画素材,应用到UI设计中,感情线有了!
  13. mysql设置最大查询时间_mysql如何限制sql查询时间
  14. shell中lsort,uniq,cut,wc,seq命令使用
  15. Edmonds-Karp算法
  16. 【嵌入式系统设计师备考(1)】嵌入式系统基础知识
  17. jQuery项目:京东商品详情页
  18. php fatal error: cannot redeclare,Fatal error: Cannot redeclare 常见问题
  19. 备份指南——Ghost前的系统配置大全(转)
  20. ospf多区域的原理和配置实例

热门文章

  1. element-ui中select组件创建条目创建条目为空时报错的解决方案
  2. C++风格指南(Google版)
  3. c语言实战项目之一 贪吃蛇(源码免费开放)
  4. 基于Java的学生兼职平台设计与实现
  5. 模拟电路50(开关电容滤波器)
  6. Kubernets 污点与容忍
  7. 云栖独栋别墅_绿野云溪花海独栋别墅
  8. 利用手机作为渗透工具的一些思路
  9. 服务器 开机时间 linux,查看Linux系统启动时间和运行时间
  10. scrapy实战项目(简单的爬取知乎项目)