OpenCV开发之——在官方人脸检测的基础上添加人脸识别

120 阅读3分钟

4.1 人脸检测成功

4.1.1 过程

  • 检测到了人脸(facesArray数组不为空)

  • 2秒内检测到的人脸大于5个

  • 人懒检测失败后,重新进行检测

  • 人脸检测成功,进行人脸识别

4.1.2 代码

人脸检测代码

boolean isFirst = true;

long startTime;

long endTime;

public Mat onCameraFrame(CvCameraViewFrame inputFrame) {

//...省略代码部分

Rect[] facesArray = faces.toArray();

for (Rect rect : facesArray) {

Imgproc.rectangle(mRgba, rect.tl(), rect.br(), FACE_RECT_COLOR, 3);

}

//执行人脸识别操作

if (isFirst && facesArray.length != 0) {

startTime = System.currentTimeMillis();

endTime = System.currentTimeMillis() + 2000;

isFirst = false;

}

if (isFaceRecon(System.currentTimeMillis(), endTime, facesArray) && facesArray.length != 0) {

onFaceLocalLib(mRgba, facesArray[0], mOpenCvCameraView);

} else { //识别失败,重新识别

isFirst = true;

}

return mRgba;

}

2s内识别人脸个数大于5

/**

  • 在2秒内识别出的数目>5才是识别成功

*/

public boolean isFaceRecon(long startTime, long endTime, Rect[] facesArray) {

if (startTime < endTime) {

if (facesArray.length == 1) {

num++;

} else {

num = 0;

}

}

return num > 5;

}

4.2 人脸识别

4.2.1 界面布局

第一个图像显示识别出的图像

相似度:根据识别出的图像与本地库对比结果

照片库:显示照片库中的图片

4.2.2 FaceUtil工具类

public class FaceUtil {

private static final String TAG = "FaceUtil";

private FaceUtil() {

}

/**

  • 特征保存

  • @param image Mat

  • @param rect 人脸信息

  • @return 保存是否成功

*/

public static boolean saveImage(Mat image, Rect rect) {

// 原图置灰

Mat grayMat = new Mat();

Imgproc.cvtColor(image, grayMat, Imgproc.COLOR_BGR2GRAY);

//Imgproc.cvtColor(image, grayMat, Imgproc.COLORMAP_JET);

// 把检测到的人脸重新定义大小后保存成文件

Mat sub = grayMat.submat(rect);

Mat mat = new Mat();

Size size = new Size(100, 100);

Imgproc.resize(sub, mat, size);

return Imgcodecs.imwrite(getRecFileName(), mat);

}

/**

  • 删除特征

  • @param context Context

  • @param fileName 特征文件

  • @return 是否删除成功

*/

public static boolean deleteImage(Context context, String fileName) {

// 文件名不能为空

if (TextUtils.isEmpty(fileName)) {

return false;

}

// 文件路径不能为空

String path = getRecFileNameList()[0];

if (path != null) {

File file = new File(path);

return file.exists() && file.delete();

} else {

return false;

}

}

/**

  • 提取特征

  • @param

  • @param fileName 文件名

  • @return 特征图片

*/

public static Bitmap getImage(String fileName) {

//String filePath = getRecFileNameList()[0];

if (TextUtils.isEmpty(fileName)) {

return null;

} else {

return BitmapFactory.decodeFile(fileName);

}

}

public static double recon(Context context) {

String[] dataPath = getDataFileNameList();

String recPath = getRecFileNameList()[0];

double diff = 0;

for (int i = 0; i < dataPath.length; i++) {

diff = compare(dataPath[i], recPath);

if (diff >= 90) {

break;

}

}

return diff;

}

/**

  • 特征对比

  • @param

  • @param fileName1 人脸特征

  • @param fileName2 人脸特征

  • @return 相似度

*/

public static double compare(String fileName1, String fileName2) {

try {

IplImage image1 = cvLoadImage(fileName1, opencv_imgcodecs.IMREAD_GRAYSCALE);

IplImage image2 = cvLoadImage(fileName2, opencv_imgcodecs.IMREAD_GRAYSCALE);

if (null == image1 || null == image2) {

return -1;

}

int l_bins = 256;

int hist_size[] = {l_bins};

float v_ranges[] = {0, 255};

float ranges[][] = {v_ranges};

IplImage imageArr1[] = {image1};

IplImage imageArr2[] = {image2};

CvHistogram Histogram1 = CvHistogram.create(1, hist_size, CV_HIST_ARRAY, ranges, 1);

CvHistogram Histogram2 = CvHistogram.create(1, hist_size, CV_HIST_ARRAY, ranges, 1);

cvCalcHist(imageArr1, Histogram1, 0, null);

cvCalcHist(imageArr2, Histogram2, 0, null);

cvNormalizeHist(Histogram1, 100.0);

cvNormalizeHist(Histogram2, 100.0);

// 参考:blog.csdn.net/nicebooks/a…

double c1 = cvCompareHist(Histogram1, Histogram2, CV_COMP_CORREL) * 100;

double c2 = cvCompareHist(Histogram1, Histogram2, CV_COMP_INTERSECT);

// Log.i(TAG, "compare: ----------------------------");

// Log.i(TAG, "compare: c1 = " + c1);

// Log.i(TAG, "compare: c2 = " + c2);

// Log.i(TAG, "compare: 平均值 = " + ((c1 + c2) / 2));

// Log.i(TAG, "compare: ----------------------------");

return (c1 + c2) / 2;

} catch (Exception e) {

e.printStackTrace();

return -1;

}

}

/**

  • @return 路径

*/

public static File getDataSourcePath() {

File file = new File(Environment.getExternalStorageDirectory(), "/FaceDetect/sourcePic/");

if (!file.exists()) {

file.mkdirs();

}

return file;

//return new File(Environment.getExternalStorageDirectory(),"/FaceDetect/sourcePic/");

}

public static File getRecPath() {

File file = new File(Environment.getExternalStorageDirectory(), "FaceDetect");

if (!file.exists()) {

file.mkdirs();

}

return file;

// return new File(Environment.getExternalStorageDirectory(),"FaceDetect");

}

private static String getRecFileName() {

String name = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss").format(new Date()) + ".jpg";

return new File(getRecPath().getAbsolutePath(), name).getAbsolutePath();

//return getRecPath().getAbsolutePath() + new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss").format(new Date()) + ".jpg";

}

/**

  • @return

  • @description:获取识别库下的所有文件

*/

public static String[] getDataFileNameList() {

File pathName = getDataSourcePath();

File[] files = pathName.listFiles();

String[] fileNames = null;

if (files != null) {

fileNames = fileFilterEnd(files, "jpg");

Arrays.sort(fileNames, Collections.reverseOrder());

}

return fileNames;

}

/**

  • @return

  • @description:获取最近识别出的文件

*/

public static String getRecFileAbsolutePath() {

String fileName = FaceUtilNew.getRecFileNameList()[0];

return new File(getRecPath().getAbsolutePath(), fileName).getAbsolutePath();

}

public static String[] getRecFileNameList() {

File pathName = getRecPath();

File[] files = pathName.listFiles();

String[] fileNames = null;

if (files != null) {

fileNames = fileFilterEnd(files, "jpg");

Arrays.sort(fileNames, Collections.reverseOrder());

}

return fileNames;

}

//删除所有临时文件

public static void deleteRecFiles(){

String [] recStringFiles=getRecFileNameList();

for (String str:recStringFiles) {

File file=new File(getRecPath().getAbsolutePath(),str);

file.delete();

}

}

private static String[] fileFilterEnd(File[] f, String end) {

int count = 0;

for (int i = 0; i < f.length; i++) {

if (f[i].getName().endsWith(end)) count++;

}

String[] s1 = new String[count];

count = 0;

for (int i = 0; i < f.length; i++) {

if (f[i].getName().endsWith(end)) {

s1[count] = f[i].getName();

count++;

}

}

return s1;

}

}

4.2.3 识别成功后,将识别到的图像保存到本地文件夹下([内部存储]/FaceDetect/yyyy-MM-dd-HH:mm:ss.jpg)

FaceUtil.saveImage(mat, rect); //将当前识别到的图像保存到/SDCard/FaceDetect文件夹下

4.2.4 将识别到图片与本地库进行对比

public void onFaceLocalLib(final Mat mat, final Rect rect, final CameraBridgeViewBase mOpenCvCameraView) {

最后

文末放一个小福利给大家,点击我的GitHub即可领取

群内有许多技术大牛,有任何问题,欢迎广大网友一起来交流,群内还不定期免费分享高阶Android学习视频资料和面试资料包~

偷偷说一句:群里高手如云,欢迎大家加群和大佬们一起交流讨论啊!