需要知识点,从相机抓取到数据,给opencv进行人脸定位,再用SeetaFaceEngine眼睛的定位,然后渲染的时候在片元着色器中进行计算,对眼睛进行局部放大;
opencv官网地址:Releases - OpenCV
下载Android 版本:
把已经编译号的库放到我们项目中
把整个头文件放到项目中
把训练的人脸模板放到项目中:
最后在app build.gradle中添加opencv的相关配置:
externalNativeBuild {
cmake {
//OpenCV新版本用这个C++11的特效
cppFlags "-std=c++11"
//NDK从r16开始就切换到了llvm的libC++,所以opencv4从libstdC++切换到了libc++。
//导致链接错误的根本原因是设置了-DANDRID_STL=gnustl_shared,
//因为opencv利用的libc++编的,而非gnustl
//arguments "-DANDROID_STL=gnustl_static" // OpenCV旧版本用这个
//新版本的opencv 需要添加这个变量
arguments "-DANDROID_STL=c++_shared"
abiFilters 'armeabi-v7a'
}
}
在CmakeLists中配置:
cmake_minimum_required(VERSION 3.4.1)
#opencv 头文件
include_directories(include)
#opencv 库文件
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
add_library( # Sets the name of the library.
native-lib
SHARED
native-lib.cpp)
target_link_libraries( # Specifies the target library.
native-lib
#链接opencv,也就是libopencv_java4
opencv_java4
)
人脸关键点定位使用中科院开源的
https://github.com/seetaface/SeetaFaceEngine
集成到项目中:
把model中的模板放到项目中:
修改CMakeList:
# 他需要用到 C++11特性
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
# 设置他需要的参数
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
# 设置他需要的参数
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.1")
# 导入头文件
include_directories(include)
set(src_files # CPP源码关联
src/cfan.cpp
src/face_alignment.cpp
src/sift.cpp
)
# 生成静态库
add_library(seeta_fa_lib STATIC ${src_files})
在总的CMakeList中引入
结合前面的音视频录制,把数据给opencv 定位出人脸,再给SeetaFace去定位眼睛的关键点,然后传给着色器,
FaceTrack.cpp 中处理人脸定位,关键点定位
初始化opencv追踪器,及seeta关键点
FaceTrack::FaceTrack(const char *model, const char *seet) {
Ptr mainDetector = makePtr(makePtr(model)); // OpenCV主探测器
Ptr trackingDetector = makePtr(makePtr(model)); // OpenCV跟踪探测器
DetectionBasedTracker::Parameters detectorParams;
// OpenCV创建追踪器,为了下面的(开始跟踪,停止跟踪)
tracker = makePtr(mainDetector, trackingDetector, detectorParams);
// 上面是OpenCV模板代码人脸追踪区域, 下面是Seeta人脸关键点代码+OpenCV
faceAlignment = makePtr(seet); // Seeta中科院关键特征点
}
获取关键点
void FaceTrack::detector(Mat src, vector &rects) {
vector faces;
// src :灰度图(去除 不需要的色彩信息)
tracker->process(src); // 处理灰度图(OpenCV的东西,灰度,色彩 影响我们人脸追踪)
tracker->getObjects(faces); // 得到人脸框框的Rect - OpenCV的东西
if (faces.size()) { // 判断true,说明非零,有人脸
Rect face = faces[0]; // 有人脸就去第一个人脸,我没有去管,多个人脸了哦
// 然后把跟踪出来的这个人脸,保存到rects里面去
rects.push_back(Rect2f(face.x, face.y, face.width, face.height));
// 根据前面的OpenCV人脸最终结果, 做人脸关键点定位
seeta::ImageData image_data(src.cols, src.rows); // image_data就是图像数据
image_data.data = src.data; // (人脸的信息 要送去检测的) = (把待检测图像)
// 人脸追踪框 信息绑定 人脸关键点定位
seeta::FaceInfo face_info; // 人脸的信息 要送去检测的
seeta::Rect bbox; // 人脸框框的信息
bbox.x = face.x; // 把人脸信息的x 给 face_info
bbox.y = face.y; // 把人脸信息的y 给 face_info
bbox.width = face.width; // 把人脸信息的width 给 face_info
bbox.height = face.height; // 把人脸信息的height 给 face_info
face_info.bbox = bbox; // 把人脸信息的bbox 给 face_info
seeta::FacialLandmark points[5]; // 特征点的检测,固定了5个点
// 执行采集出 五个点
faceAlignment->PointDetectLandmarks(image_data, face_info, points);
// 把五个点 转换 ,因为第二个参数需要 Rect2f
for (int i = 0; i < 5; ++i) { // 为何不需要宽和高,只需要保存点就够了
rects.push_back(Rect2f(points[i].x, points[i].y, 0, 0));
}
}
}
大眼算法见:http://www.gson.org/thesis/warping-thesis.pdf
代码地址:Seven: Android音视频