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

/**

  • 在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);

// 参考:http://blog.csdn.net/nicebooks/article/details/8175002

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) {

runOnUiThread(new Runnable() {

@Override

public void run() {

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

String[] dataFileNameList = FaceUtil.getDataFileNameList(); //本地库所有源文件

recPath = FaceUtil.getRecFileAbsolutePath();

if (dataFileNameList.length == 0) {

Toast.makeText(FdActivity2.this,“图片库为空,请先准备本地图片库”,Toast.LENGTH_SHORT).show();

//FaceUtil.deleteRecFiles();

//finish();

return;

}

for (String fileName : dataFileNameList) {

dataNamePath = new File(FaceUtilNew.getDataSourcePath().getAbsolutePath(), fileName).getAbsolutePath();

diff = FaceUtil.compare(dataNamePath, recPath);

mImageViewFace1.setImageBitmap(FaceUtilNew.getImage(recPath));

mImageViewFace2.setImageBitmap(FaceUtilNew.getImage(dataNamePath));

mCmpPic.setText(String.format(“相似度 : %.2f”, diff) + “%”);

if (diff >= 75)

break;

}

if (diff <= 75) {

mOpenCvCameraView.enableView();

} else {

mOpenCvCameraView.disableView();

Toast.makeText(FdActivity2.this, “识别成功!!” + diff, Toast.LENGTH_LONG).show();

}

}

});

}

说明:

  • 若本地图片库为空,提示用户,实现存储本地图片库

架构师筑基包括哪些内容

我花了将近半个月时间将:深入 Java 泛型.、注解深入浅出、并发编程.、数据传输与序列化、Java 虚拟机原理、反射与类加载、高效 IO、Kotlin项目实战等等Android架构师筑基必备技能整合成了一套系统知识笔记PDF,相信看完这份文档,你将会对这些Android架构师筑基必备技能有着更深入、更系统的理解。

由于文档内容过多,为了避免影响到大家的阅读体验,在此只以截图展示部分内容

注:资料与上面思维导图一起看会更容易学习哦!每个点每个细节分支,都有对应的目录内容与知识点!



这份资料就包含了所有Android初级架构师所需的所有知识!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
show();

}

}

});

}

说明:

  • 若本地图片库为空,提示用户,实现存储本地图片库

架构师筑基包括哪些内容

我花了将近半个月时间将:深入 Java 泛型.、注解深入浅出、并发编程.、数据传输与序列化、Java 虚拟机原理、反射与类加载、高效 IO、Kotlin项目实战等等Android架构师筑基必备技能整合成了一套系统知识笔记PDF,相信看完这份文档,你将会对这些Android架构师筑基必备技能有着更深入、更系统的理解。

由于文档内容过多,为了避免影响到大家的阅读体验,在此只以截图展示部分内容

注:资料与上面思维导图一起看会更容易学习哦!每个点每个细节分支,都有对应的目录内容与知识点!

[外链图片转存中…(img-bKsLF6Q9-1715796651039)]
[外链图片转存中…(img-2jtPXoND-1715796651040)]
这份资料就包含了所有Android初级架构师所需的所有知识!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 28
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值