相关

人脸识别免费框架

使用《大话西游》中一帧作为素材

素材

opencv

opencv中demo较为全面,人脸检测使用对应的haarcascades实现。

dlib

检测范围更多,精度与效果更好。但是需要使用到100mb的模型数据库,移动应用上使用不太现实。上图效果同样使用face_landmark_detectionx_ex 这个官方提供的demo。

flandmark

可以实现8个关键点检测,效果和效率一般,不过检测全面,而且模型只有5mb。

实现代码:

#include

#include

#include

#include

#include

#include "flandmark_detector.h"

void detectFaceInImage(IplImage orig, IplImage input, CvHaarClassifierCascade* cascade, FLANDMARK_Model model, int bbox, double landmarks)

{

// Smallest face size.

CvSize minFeatureSize = cvSize(60, 60);

int flags = CV_HAAR_DO_CANNY_PRUNING;

// How detailed should the search be.

float search_scale_factor = 1.2f;

CvMemStorage storage;

CvSeq rects;

int nFaces;

storage = cvCreateMemStorage(0);

cvClearMemStorage(storage);

double t = (double)cvGetTickCount();

// Detect all the faces in the greyscale image.

rects = cvHaarDetectObjects(input, cascade, storage, search_scale_factor, 3, 0, minFeatureSize);

nFaces = rects->total;

printf("face = %d",nFaces);

for (int iface = 0; iface < (rects ? nFaces : 0); ++iface)

{

CvRect r = (CvRect)cvGetSeqElem(rects, iface);

bbox[0] = r->x;

bbox[1] = r->y;

bbox[2] = r->x + r->width;

bbox[3] = r->y + r->height;

flandmark_detect(input, bbox, model, landmarks);

// display landmarks

cvRectangle(orig, cvPoint(bbox[0], bbox[1]), cvPoint(bbox[2], bbox[3]), CV_RGB(255,0,0) );

cvRectangle(orig, cvPoint(model->bb[0], model->bb[1]), cvPoint(model->bb[2], model->bb[3]), CV_RGB(0,0,255) );

cvCircle(orig, cvPoint((int)landmarks[0], (int)landmarks[1]), 3, CV_RGB(0, 0,255), CV_FILLED);

for (int i = 2; i < 2model->data.options.M; i += 2)

{

cvCircle(orig, cvPoint(int(landmarks[i]), int(landmarks[i+1])), 3, CV_RGB(255,0,0), CV_FILLED);

}

}

t = (double)cvGetTickCount() - t;

int ms = cvRound( t / ((double)cvGetTickFrequency() * 1000.0) );

if (nFaces > 0)

{

printf("Faces detected: %d; Detection of facial landmark on all faces took %d ms\n", nFaces, ms);

} else {

printf("NO Face\n");

}

cvReleaseMemStorage(&storage);

}

int main( int argc, char** argv )

{

char flandmark_window[] = "flandmark_example1";

double t;

int ms;

if (argc < 2)

{

fprintf(stderr, "Usage: flandmark_1 []\n");

exit(1);

}

char faceCascadeFilename[] = "haarcascade_frontalface_alt.xml";

// Load the HaarCascade classifier for face detection.

CvHaarClassifierCascade* faceCascade;

faceCascade = (CvHaarClassifierCascade)cvLoad(faceCascadeFilename, 0, 0, 0);

if( !faceCascade )

{

printf("Couldnt load Face detector '%s'\n", faceCascadeFilename);

exit(1);

}

t = (double)cvGetTickCount();

FLANDMARK_Model * model = flandmark_init("flandmark_model.dat");

if (model == 0)

{

printf("Structure model wasn't created. Corrupted file flandmark_model.dat?\n");

exit(1);

}

t = (double)cvGetTickCount() - t;

ms = cvRound( t / ((double)cvGetTickFrequency() * 1000.0) );

printf("Structure model loaded in %d ms.\n", ms);

// ------------- end flandmark load model

// input image

IplImage frame = cvLoadImage(argv[1]);

if (frame == NULL)

{

fprintf(stderr, "Cannot open image %s. Exiting...\n", argv[1]);

exit(1);

}

// convert image to grayscale

IplImage frame_bw = cvCreateImage(cvSize(frame->width, frame->height), IPL_DEPTH_8U, 1);

cvConvertImage(frame, frame_bw);

int bbox = (int)malloc(4sizeof(int));

double landmarks = (double)malloc(2model->data.options.Msizeof(double));

detectFaceInImage(frame, frame_bw, faceCascade, model, bbox, landmarks);

// cvShowImage(flandmark_window, frame);

// cvWaitKey(0);

if (argc == 3)

{

printf("Saving image to file %s...\n", argv[2]);

cvSaveImage(argv[2], frame);

}

// cleanup

free(bbox);

free(landmarks);

// cvDestroyWindow(flandmark_window);

cvReleaseImage(&frame);

cvReleaseImage(&frame_bw);

cvReleaseHaarClassifierCascade(&faceCascade);

flandmark_free(model);

}

flandmark就是基于opencv二次开发的,人脸检测这个步骤就是使用的oepncv的接口实现。

另外收费的人脸关键点检测的技术提供还有很多。

动态人脸贴纸

素材视频

input

输出效果

output

代码实现

#include

#include

#include

#include

#include

using namespace std;

using namespace cv;

void write_yuv_pic(Mat& img, CascadeClassifier& cascade,

CascadeClassifier& nestedCascade,

double scale, bool tryflip,FILE* out);

int is_yuv_file(const char * filename) ;

int width = 480,height = 480;

string cascadeName;

string nestedCascadeName;

int main( int argc, char** argv )

{

VideoCapture capture;

Mat frame, image;

char* inputName,outPutName;

bool tryflip;

CascadeClassifier cascade, nestedCascade;

double scale;

cascadeName = "./haarcascades/haarcascade_frontalface_alt.xml";

nestedCascadeName = "./haarcascades/haarcascade_eye_tree_eyeglasses.xml";

scale = 1;

tryflip = false;

if(argc !=3)

{

puts("useage:argv[0] yuv_input_file yuv_output_file");

return -1;

}

inputName = argv[1];

outPutName = argv[2];

int index = strlen(inputName)-1;

if(!(is_yuv_file(inputName)&&is_yuv_file(outPutName)))

{

puts("useage:argv[0] yuv_input_file yuv_output_file");

return -1;

}

int i = 0;

FILE * out = (FILE)fopen(outPutName,"wb+");

FILE * file = (FILE )fopen(inputName,"rb");

unsigned char * yuvbuff = (unsigned char )malloc(widthheight3/2);

cerr << cascadeName << endl << nestedCascadeName <

if ( !nestedCascade.load( nestedCascadeName ) )

cerr << "WARNING: Could not load classifier cascade for nested objects" << endl;

if( !cascade.load( cascadeName ) )

{

cerr << "ERROR: Could not load classifier cascade" << endl;

return -1;

}

for(i=0;i < 100;i++)

{

fread(yuvbuff,1,widthheight3/2,file);

Mat yuvMat(height+height/2,width,CV_8UC1,yuvbuff);

cvtColor(yuvMat,image,CV_YUV420p2RGB);

if( !image.empty() )

{

write_yuv_pic( image, cascade, nestedCascade, scale, tryflip,out);

}

}

fclose(file);

fclose(out);

free(yuvbuff);

return 0;

}

void write_yuv_pic(Mat& img, CascadeClassifier& cascade,

CascadeClassifier& nestedCascade,

double scale, bool tryflip,FILE* out)

{

double t = 0;

vector faces, faces2;

const static Scalar colors[] =

{

Scalar(255,0,0),

Scalar(255,128,0),

Scalar(255,255,0),

Scalar(0,255,0),

Scalar(0,128,255),

Scalar(0,255,255),

Scalar(0,0,255),

Scalar(255,0,255)

};

Mat gray, smallImg;

cvtColor( img, gray, COLOR_BGR2GRAY );

double fx = 1 / scale;

resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR );

equalizeHist( smallImg, smallImg );

t = (double)cvGetTickCount();

cascade.detectMultiScale( smallImg, faces,

1.1, 3, 0

//|CASCADE_FIND_BIGGEST_OBJECT

//|CASCADE_DO_ROUGH_SEARCH

|CASCADE_SCALE_IMAGE

,

Size(80, 80) );

t = (double)cvGetTickCount() - t;

printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()1000.) );

for ( size_t i = 0; i < faces.size(); i++ )

{

Rect r = faces[i];

Mat smallImgROI;

vector nestedObjects;

Point center;

Scalar color = colors[i%8];

int radius;

double aspect_ratio = (double)r.width/r.height;

if( 0.75 < aspect_ratio && aspect_ratio < 1.3 )

{

Point s ;

IplImage pimg = IplImage(img);

IplImage topimage = cvLoadImage( "head_top.png", 1 );

int iwidth = (topimage).width;

int iheight = (topimage).height;

printf("s.x = %d,s.y = %d,width = %d,height = %d\n",s.x,s.y,iwidth,iheight);

s.y= r.y-iheight;

s.x = r.x-(iwidth-r.width)/2;

if(s.y < 0 )

s.y = 0;

if(s.x < 0 )

s.x = 0;

printf("s.x = %d,s.y = %d,width = %d,height = %d\n",s.x,s.y,iwidth,iheight);

cvSetImageROI(topimage,CvRect(0,0,iwidth,iheight));

cvSetImageROI(&pimg,CvRect(s.x,s.y,iwidth,iheight));

cvAddWeighted(&pimg,1,topimage,0.5,0.0,&pimg);

cvResetImageROI(&pimg);

cvResetImageROI(topimage);

}

if( nestedCascade.empty() )

continue;

smallImgROI = smallImg( r );

t = (double)cvGetTickCount();

nestedCascade.detectMultiScale( smallImgROI, nestedObjects,

1.5, 3, 0

//|CASCADE_FIND_BIGGEST_OBJECT

//|CASCADE_DO_ROUGH_SEARCH

//|CASCADE_DO_CANNY_PRUNING

|CASCADE_SCALE_IMAGE

,

Size(20, 20) );

t = (double)cvGetTickCount() - t;

printf( "nestdetection time = %g ms\n", t/((double)cvGetTickFrequency()1000.) );

for ( size_t j = 0; j < nestedObjects.size(); j++ )

{

Rect nr = nestedObjects[j];

IplImage pimg = IplImage(img);

IplImage eyeimage = cvLoadImage( "eye.png", 1 );

int iwidth = (eyeimage).width;

int iheight = (eyeimage).height;

int x = nr.x+r.x ;

int y = nr.y +nr.height+r.y;

printf("s.x = %d,s.y = %d,width = %d,height = %d\n",x,y,iwidth,iheight);

cvSetImageROI(eyeimage,CvRect(0,0,iwidth,iheight-2));

cvSetImageROI(&pimg,CvRect(x,y,iwidth,iheight-2));

cvAddWeighted(&pimg,1,eyeimage,0.5,0.0,&pimg);

cvResetImageROI(&pimg);

cvResetImageROI(eyeimage);

}

}

unsigned char * yuvbuff = (unsigned char )malloc(widthheight3/2);

Mat yuvMat(height+height/2,width,CV_8UC1,yuvbuff);

cvtColor(img,yuvMat,CV_BGR2YUV_I420);

fwrite(yuvMat.data,1,widthheight*3/2,out);

free(yuvbuff);

}

int is_yuv_file(const char * filename) {

int i = 0;

char * end = ".yuv";

if(filename == NULL)

return 0;

int endlength = strlen(end);

int strlength = strlen(filename);

if(strlength <= endlength)

return 0;

while (i < endlength) {

if (end[i] != filename[strlength - (endlength - i)])

return 0;

i++;

}

return 1;

}

以上代码是基于opencv框架。

遗留问题

只是实现效果,并未深究细节,存在如下问题

贴纸并没有根据人脸倾斜角度而旋转缩放

应该加入记忆和基本纠错功能,防止某帧检测不精准而贴图位置出错

对于动态贴纸,应该解码贴纸视频获取贴纸的数据,如果贴纸素材较小动画简单也应该使用序列帧代替固定贴纸图片。

android识别人脸开放贴纸,人脸识别及动态贴纸相关推荐

  1. 票据识别android代码,Android 百度AI开放平台-文字识别-财务票据文字识别

    简单记录一下今天关于百度AI开放平台-文字识别-财务票据文字识别的实现过程 文字识别有对应的Android SDK集成及相关Demo,文档地址如下图: SDK目录图.png 但是SDK中的返回数据字段 ...

  2. 深度学习AI美颜系列----人像静态/动态贴纸特效算法实现

    人像静态/动态贴纸特效几乎已经是所有图像视频处理类/直播类app的必需品了,这个功能看起来复杂,实际上很简单,本文将给大家做个详细的讲解. 我们先来看一下FaceU的两张效果图: 这两张效果图中, 我 ...

  3. 深度学习AI美颜系列——人像静态/动态贴纸特效算法实现 | CSDN博文精选

    作者 | Trent1985 来源 | CSDN博客 人像静态/动态贴纸特效几乎已经是所有图像视频处理类/直播类app的必需品了,这个功能看起来复杂,实际上很简单,本文将给大家做个详细的讲解. 我们先 ...

  4. 美颜sdk动态贴纸是什么?

    美颜sdk如今已经成了广大视频拍摄平台的刚需,用户们也习惯了这种新颖的拍摄形式,原相机被无情"打入冷宫",特别是短视频和直播平台中,绝大部分用户都在使用美颜sdk的趣味功能进行拍摄 ...

  5. 直播美颜SDK动态贴纸详解

    打开如今的直播拍摄类平台,主播们使用直播美颜SDK已经是一件稀松平常的事情,特别是在"颜值区"这个分类里,几乎所有的主播都在用.大家喜欢用直播美颜SDK不单单是因为它可以为大家提升 ...

  6. 趣拍云:助力APP一周上线人脸识别+动态贴纸

    年初,某美图软件上线的"一秒变福娃"引发了全民COS狂潮.配合新年的欢乐气氛,人们纷纷拿起手机,将自己的照片P成福娃的模样,并发到朋友圈送出新年祝福.娱乐化的玩法,不仅收到了年轻粉 ...

  7. Android 用虹软SDK做人脸识别

    人脸识别第三方sdk比较多,但是大多都是收费的或者限制次数什么的,虹软的效果还不错,全免费也不需要联网 V1.2版本使用和快速集成:https://www.jianshu.com/p/8dee89ec ...

  8. 测一测!中科视拓免费开放口罩人脸检测与识别技术

    全民抗疫形势下,口罩已成为复工复产的标配.对于人脸识别技术厂商而言,两个应用需求应运而生: 1.检测人脸是否佩戴口罩: 2.在戴口罩的情况下依旧能够实现高精度人脸识别. 疫情初期,中科视拓紧急研发口罩 ...

  9. Android相机预览,指定区域显示预览框,在区域内出现人脸进行人脸识别,并抓拍人脸照片存在本地,CameraX,虹软人脸识别

    效果图: 第一种是使用camerax进行预览,android camerax预览官方文档,主要通过imageAnalysis,抓帧进行图片处理,然后通过android自带的图片人脸识别FaceDete ...

最新文章

  1. mysql切换到使用openssl_OpenSSL可以用来调试到MySQL服务器的SSL连接吗?
  2. Javascript类的写法
  3. 视频可以转换html,10 个免费的 HTML 视频转换工具
  4. Canonical 开源 MicroK8 | 云原生生态周报 Vol. 25
  5. 卷积神经网络迁移学习
  6. 一位资深程序员大牛给Java初学者的学习建议
  7. android聊天,存储聊天记录sqlite
  8. php 禁用外部实体,php – Doctrine 2 – 从实体外部禁用PrePersist
  9. ASP.NET Web API 跨域访问(CORS)要注意的地方
  10. ZOJ 2760 How Many Shortest Path 最大流+floyd求最短路
  11. AR.js专题-多Renderer支持
  12. 60、剑指offer--把二叉树打印成多行
  13. java applet介绍,Java Applet 介绍
  14. 转载十年 - 武汉公交杂记
  15. PCI/PCIE相关知识
  16. pod2g宣布A5的Sandbox破解成功
  17. 一文看懂人工智能产业链,未来10年2000亿美元市场
  18. 判断人物眼型matlab,怎么判断眼型和脸型?
  19. 在 Windows 下用 GCC 编译器练习 C/C++ 的简单教程
  20. 烤仔建工×MetaEstate×MetaCat | 明天来元宇宙过感恩节!

热门文章

  1. CAN 总线 之三 CAN 国际标准 ISO 11898 解读
  2. 2021-03-22
  3. C语言打印乘法口诀表
  4. 加速度运动/弹性运动/模拟重力场/拖拽运动
  5. UBLOX板卡基础设置--F9P板卡配置(基准站和流动站)
  6. 在信用证支付的情况下,空运单可否作成以银行为收货人?在此种情况下可否起到约束进口方付款的作用?...
  7. 微信公众号上传图片功能
  8. wireshark数据包流量分析
  9. 计算机科学 在职双证,计算机专业在职研究生有双证的吗?
  10. 小白从0学习推荐系统 ---01 推荐系统简介