Android 人脸识别+人脸匹配(OpenCV+JavaCV)

项目源码 http://download.csdn.net/detail/sky286753213/6617075 

之前不想上传源码是因为代码写的实在很烂,参考价值不是很大,主要代码都在CameraActivity中




这里吐下槽,目前Android人脸识别技术分享的感觉很少

我也是参考一些资料和别人的代码加以改进

上个项目中用到的技术现在有些遗忘了,把关键性的代码给大家分享下

public void DetectFace() {
		Mat image = Highgui.imread(FACE);
		MatOfRect faceDetections = new MatOfRect();
		mJavaDetector.detectMultiScale(image, faceDetections);

		for (Rect rect : faceDetections.toArray()) {
			Core.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x
					+ rect.width, rect.y + rect.height), new Scalar(0, 255, 0));
			// 把检测到的人脸重新定义大小后保存成文件
			Mat sub = image.submat(rect);
			Mat mat = new Mat();
			Size size = new Size(100, 100);
			Imgproc.resize(sub, mat, size);
			Highgui.imwrite(FACEDONE, mat);
		}
	}

FACE和FACEDONE为两个路径 一个是拍照完成的图片路径,另一个是生成的人脸图片的路径

这里使用了OpenCV中的人脸识别方法,方法很简单,把你的照片路径带进去他会检测到这张图片里有多少个人头,然后进行循环输出人脸图片

这里需要注意下的是 如果进行人脸比对的话需要每张图片的大小一样,否则会报异常


另外,想使用OpenCV之前还需定义一个BaseLoaderCallback对象来加载识别的人脸xml库

private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {

		public void onManagerConnected(int status) {
			switch (status) {
			case LoaderCallbackInterface.SUCCESS: {
				mJavaDetector = new CascadeClassifier(
						"/sdcard/FaceDetect/haarcascade_frontalface_alt2.xml");
			}
				break;
			default: {
				super.onManagerConnected(status);
			}
				break;
			}
		}
	};

然后在OnResume中加载BaseLoaderCallback对象

OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_5, this,
				mLoaderCallback);


人脸匹配使用的是JavaCV中的匹配方法

该方法的博客一会附上连接

public int Identification() {
		FaceRecognizer fr = createFisherFaceRecognizer();
		MatVector mv = new MatVector(faceList.size());
		CvMat cvMat = CvMat.create(faceList.size(), 1, CV_32SC1);
		for (int i = 0; i < faceList.size(); i++) {
			IplImage img = cvLoadImage(faceList.get(i).getPath(),
					CV_LOAD_IMAGE_GRAYSCALE);
			mv.put(i, img);
			cvMat.put(i, 0, i);
		}
		fr.train(mv, cvMat);
		IplImage testImage = cvLoadImage(
				Environment.getExternalStorageDirectory()
						+ "/FaceDetect/faceDone.jpg", CV_LOAD_IMAGE_GRAYSCALE);
		return fr.predict(testImage);

	}

faceList中放的是人脸图片文件夹里所有人脸图片的路径

循环把他们放入MatVector和CvMat中

然后对FaceRecognizer进行训练

/FaceDetect/faceDone.jpg
这个路径是经过上面识别方法处理完图片后所输出的人脸图片的路径

predict()方法把刚才的人脸图片放入训练模型中进行匹配 会返回一个模型中的索引值

获取到索引值后就大功告成了

下面一个方法可以获取到两张图片的相似度,最大值是100

public double CmpPic(String path) {
		int l_bins = 20;
		int hist_size[] = { l_bins };

		float v_ranges[] = { 0, 100 };
		float ranges[][] = { v_ranges };

		IplImage Image1 = cvLoadImage(Environment.getExternalStorageDirectory()
				+ "/FaceDetect/faceDone.jpg", CV_LOAD_IMAGE_GRAYSCALE);
		IplImage Image2 = cvLoadImage(path, CV_LOAD_IMAGE_GRAYSCALE);

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

		return cvCompareHist(Histogram1, Histogram2, CV_COMP_CORREL);
	}

带入两张图片的路径即可,这里不在阐述


下面是源码,写的很烂,仅供参考

package com.comdosoft.face;

import static com.googlecode.javacv.cpp.opencv_contrib.createFisherFaceRecognizer;
import static com.googlecode.javacv.cpp.opencv_core.CV_32SC1;
import static com.googlecode.javacv.cpp.opencv_highgui.CV_LOAD_IMAGE_GRAYSCALE;
import static com.googlecode.javacv.cpp.opencv_highgui.cvLoadImage;
import static com.googlecode.javacv.cpp.opencv_imgproc.CV_COMP_CORREL;
import static com.googlecode.javacv.cpp.opencv_imgproc.CV_HIST_ARRAY;
import static com.googlecode.javacv.cpp.opencv_imgproc.cvCalcHist;
import static com.googlecode.javacv.cpp.opencv_imgproc.cvCompareHist;
import static com.googlecode.javacv.cpp.opencv_imgproc.cvNormalizeHist;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.highgui.Highgui;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.Toast;
import com.comdosoft.pojo.FacePojo;
import com.googlecode.javacv.cpp.opencv_contrib.FaceRecognizer;
import com.googlecode.javacv.cpp.opencv_core.CvMat;
import com.googlecode.javacv.cpp.opencv_core.IplImage;
import com.googlecode.javacv.cpp.opencv_core.MatVector;
import com.googlecode.javacv.cpp.opencv_imgproc.CvHistogram;

public class CameraActivity extends Activity implements SurfaceHolder.Callback,
		Camera.PictureCallback {
	private List<FacePojo> faceList = new ArrayList<FacePojo>();

	private ProgressDialog proDialog;
	private CascadeClassifier mJavaDetector;
	private SurfaceView mSurfaceView;
	private SurfaceHolder holder;
	private Camera camera;

	private String FACE = "/sdcard/FaceDetect/face.jpg";
	private String FACEDONE = "/sdcard/FaceDetect/faceDone.jpg";
	private int index;
	private int type;
	private int t = 2;
	private int angle = 0;
	private boolean flag = true;
	private double value;
	private Toast toast;
	private FacePojo fp;
	private int cameraCount;
	private CameraUtil cu = new CameraUtil();
	private int[] iconArr = new int[] { R.drawable.icon1, R.drawable.icon2,
			R.drawable.icon3 };

	private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {

		public void onManagerConnected(int status) {
			switch (status) {
			case LoaderCallbackInterface.SUCCESS: {
				mJavaDetector = new CascadeClassifier(
						"/sdcard/FaceDetect/haarcascade_frontalface_alt2.xml");
			}
				break;
			default: {
				super.onManagerConnected(status);
			}
				break;
			}
		}
	};

	private Handler updateUI = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case 1:
				proDialog.dismiss();
				Intent intent = new Intent();
				if (type == 0 || type == 1) {
					index = Identification();
					fp = faceList.get(index);
					value = CmpPic(fp.getPath()) * 100;
				}
				// Toast.makeText(getApplicationContext(),
				// "相似度:" + value + "--" + num, 0).show();
				if (value < 70 && type != 2) {
					intent.setClass(getApplicationContext(), SignFail.class);
					startActivity(intent);
				} else {
					if (type == 0) {
						Bundle bundle = new Bundle();
						bundle.putString("id", fp.getId());
						bundle.putString("name", fp.getName());
						intent.putExtras(bundle);
						intent.setClass(getApplicationContext(), SignIn.class);
						startActivity(intent);
					} else if (type == 1) {
						Intent intent2 = getIntent();
						Bundle bundle2 = new Bundle();
						bundle2.putInt("status", 1);
						bundle2.putString("id", fp.getId());
						bundle2.putString("name", fp.getName());
						intent2.putExtras(bundle2);
						setResult(RESULT_OK, intent2);
						finish();
					} else if (type == 2) {
						Intent intent2 = getIntent();
						setResult(RESULT_OK, intent2);
						finish();
					}
				}
				break;
			}
		}
	};

	private Timer dataTimer = new Timer();
	private Handler dataHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			int msgId = msg.what;
			switch (msgId) {
			case 1:
				if (flag && t == -1) {
					// camera.autoFocus(null);
					camera.takePicture(null, null, CameraActivity.this);
					flag = false;
				}
				if (flag) {
					timeDown();
				}
			}
		}

	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		getWindow().clearFlags(
				WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
		requestWindowFeature(Window.FEATURE_NO_TITLE);// 设置横屏模式以及全屏模式
		setContentView(R.layout.camera);// 设置View

		proDialog = new ProgressDialog(this);

		Intent bundle = getIntent();
		type = bundle.getIntExtra("type", 0);

		mSurfaceView = (SurfaceView) findViewById(R.id.camera);
		holder = mSurfaceView.getHolder();
		holder.addCallback(this);
		holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);// 指定Push Buffer
	}

	@Override
	protected void onStart() {
		super.onStart();
		LoadFaceData();
	}

	@Override
	protected void onResume() {
		super.onResume();
		if (getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
			setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
		}
		OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_5, this,
				mLoaderCallback);
	}

	public void onPictureTaken(byte[] data, Camera camera) {
		try {
			String path = Environment.getExternalStorageDirectory()
					+ "/FaceDetect/face.jpg";
			// data2file(data, path);
			Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
			Matrix matrix = new Matrix();
			// 设置图像的旋转角度
			matrix.setRotate(angle);
			// 旋转图像,并生成新的Bitmap对像
			bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
					bitmap.getHeight(), matrix, true);
			cu.writePhoto(bitmap, bitmap.getWidth(), bitmap.getHeight(), path);
			if (type == 2) {
				proDialog.setMessage("正在检测...");
			} else {
				proDialog.setMessage("正在识别...");
			}
			proDialog.show();
			Thread loginThread = new Thread(new LoginFailureHandler());
			loginThread.start();
		} catch (Exception e) {
		}
		camera.startPreview();
	}

	class LoginFailureHandler implements Runnable {

		public void run() {
			DetectFace();
			Message message = new Message();
			message.what = 1;
			updateUI.sendMessage(message);
		}
	}

	public void surfaceCreated(SurfaceHolder holder) {
		try {
			camera = Camera.open(camera());// 摄像头的初始化
			camera.setPreviewDisplay(holder);
			dataTimer.schedule(new TimerTask() {

				@Override
				public void run() {
					Message message = new Message();
					message.what = 1;
					dataHandler.sendMessage(message);
				}

			}, 0, 2000);
		} catch (Exception e) {
		}

	}

	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		Camera.Parameters parameters = camera.getParameters();
		// parameters.setPreviewSize(1280, 800);
		camera.setParameters(parameters);// 设置参数
		int flag = getWindowManager().getDefaultDisplay().getRotation();
		angle = 450 - flag * 90;
		if (angle >= 360) {
			angle = angle - 360;
		}
		camera.setDisplayOrientation(angle);
		camera.startPreview();// 开始预览

	}

	public void surfaceDestroyed(SurfaceHolder holder) {
		camera.setPreviewCallback(null);
		camera.stopPreview();
		camera.release();
		camera = null;

	}

	// private void data2file(byte[] w, String fileName) throws Exception {//
	// 将二进制数据转换为文件的函数
	// FileOutputStream out = null;
	// try {
	// out = new FileOutputStream(fileName);
	// out.write(w);
	// out.close();
	// } catch (Exception e) {
	// if (out != null)
	// out.close();
	// throw e;
	// }
	// }

	public void DetectFace() {
		Mat image = Highgui.imread(FACE);
		MatOfRect faceDetections = new MatOfRect();
		mJavaDetector.detectMultiScale(image, faceDetections);

		int k = 0;

		for (Rect rect : faceDetections.toArray()) {
			Core.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x
					+ rect.width, rect.y + rect.height), new Scalar(0, 255, 0));
			// 把检测到的人脸重新定义大小后保存成文件
			Mat sub = image.submat(rect);
			Mat mat = new Mat();
			Size size = new Size(100, 100);
			Imgproc.resize(sub, mat, size);
			Highgui.imwrite(FACEDONE, mat);
			k++;
		}

		if (k == 0) {
			cu.writePhoto(BitmapFactory.decodeFile(FACE), 100, 100, FACEDONE);
		}
	}

	public int Identification() {
		FaceRecognizer fr = createFisherFaceRecognizer();
		MatVector mv = new MatVector(faceList.size());
		CvMat cvMat = CvMat.create(faceList.size(), 1, CV_32SC1);
		for (int i = 0; i < faceList.size(); i++) {
			IplImage img = cvLoadImage(faceList.get(i).getPath(),
					CV_LOAD_IMAGE_GRAYSCALE);
			mv.put(i, img);
			cvMat.put(i, 0, i);
		}
		fr.train(mv, cvMat);
		IplImage testImage = cvLoadImage(
				Environment.getExternalStorageDirectory()
						+ "/FaceDetect/faceDone.jpg", CV_LOAD_IMAGE_GRAYSCALE);
		return fr.predict(testImage);

	}

	public void LoadFaceData() {
		File[] files = new File("/sdcard/FaceData/").listFiles();
		File f;
		String id;
		String name;
		faceList.clear();
		for (int i = 0; i < files.length; i++) {
			f = files[i];
			if (!f.canRead()) {
				return;
			}
			if (f.isFile()) {
				id = f.getName().split("_")[0];
				name = f.getName().substring(f.getName().indexOf("_") + 1,
						f.getName().length() - 4);
				faceList.add(new FacePojo(id, name, Environment
						.getExternalStorageDirectory()
						+ "/FaceData/"
						+ f.getName()));
			}
		}
	}

	public double CmpPic(String path) {
		int l_bins = 20;
		int hist_size[] = { l_bins };

		float v_ranges[] = { 0, 100 };
		float ranges[][] = { v_ranges };

		IplImage Image1 = cvLoadImage(Environment.getExternalStorageDirectory()
				+ "/FaceDetect/faceDone.jpg", CV_LOAD_IMAGE_GRAYSCALE);
		IplImage Image2 = cvLoadImage(path, CV_LOAD_IMAGE_GRAYSCALE);

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

		return cvCompareHist(Histogram1, Histogram2, CV_COMP_CORREL);
	}

	public void writePhoto(Bitmap bmp) {
		File file = new File("/sdcard/FaceDetect/faceDone.jpg");
		try {
			Bitmap bm = Bitmap.createBitmap(bmp, 0, 0, 100, 100);
			BufferedOutputStream bos = new BufferedOutputStream(
					new FileOutputStream(file));
			if (bm.compress(Bitmap.CompressFormat.JPEG, 100, bos)) {
				bos.flush();
				bos.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void timeDown() {
		LayoutInflater inflater = getLayoutInflater();
		View layout = inflater.inflate(R.layout.custom,
				(ViewGroup) findViewById(R.id.llToast));
		ImageView image = (ImageView) layout.findViewById(R.id.tvImageToast);
		image.setImageResource(iconArr[t--]);
		toast = new Toast(getApplicationContext());
		toast.setDuration(Toast.LENGTH_SHORT);
		toast.setView(layout);
		toast.show();
	}

	public int camera() {
		Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
		cameraCount = Camera.getNumberOfCameras(); // get cameras number

		for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
			Camera.getCameraInfo(camIdx, cameraInfo);
			if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
				try {
					return camIdx;
				} catch (RuntimeException e) {
					e.printStackTrace();
				}
			}
		}
		return 1;
	}
}


  • 7
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 121
    评论
要在Java中使用JavaCV进行人脸识别,你可以使用OpenCV人脸识别模块。下面是一个简单的示例代码,演示了如何使用JavaCV进行人脸识别: ```java import org.bytedeco.opencv.opencv_core.*; import org.bytedeco.opencv.opencv_face.*; import org.bytedeco.opencv.opencv_objdetect.*; import static org.bytedeco.opencv.global.opencv_core.*; import static org.bytedeco.opencv.global.opencv_imgcodecs.*; import static org.bytedeco.opencv.global.opencv_imgproc.*; import static org.bytedeco.opencv.global.opencv_objdetect.*; public class FaceRecognitionExample { public static void main(String[] args) { // 加载人脸识别模型 String cascadeFile = "path/to/haarcascade_frontalface_default.xml"; CascadeClassifier cascadeClassifier = new CascadeClassifier(cascadeFile); // 加载人脸识别模型 String modelFile = "path/to/trained/model.yml"; LBPHFaceRecognizer faceRecognizer = LBPHFaceRecognizer.create(); faceRecognizer.read(modelFile); // 读取测试图像 Mat testImage = imread("path/to/test/image.jpg"); // 转换为灰度图像 Mat grayImage = new Mat(); cvtColor(testImage, grayImage, COLOR_BGR2GRAY); // 检测人脸 RectVector faces = new RectVector(); cascadeClassifier.detectMultiScale(grayImage, faces); // 对每一个检测到的人脸进行识别 for (int i = 0; i < faces.size(); i++) { Rect face = faces.get(i); // 提取人脸区域 Mat faceROI = new Mat(grayImage, face); // 标准化人脸图像 Mat normalizedFace = new Mat(); resize(faceROI, normalizedFace, new Size(100, 100)); // 进行人脸识别 IntPointer label = new IntPointer(1); DoublePointer confidence = new DoublePointer(1); faceRecognizer.predict(normalizedFace, label, confidence); // 获取识别结果 int predictedLabel = label.get(0); double predictedConfidence = confidence.get(0); // 在图像上绘制识别结果 String labelStr = "Unknown"; if (predictedConfidence < 70) { labelStr = "Person " + predictedLabel; } putText(testImage, labelStr, new Point(face.x(), face.y() - 10), FONT_HERSHEY_SIMPLEX, 0.9, Scalar.GREEN); rectangle(testImage, face, Scalar.RED); } // 显示结果图像 imshow("Face Recognition", testImage); waitKey(0); } } ``` 在这个示例中,我们首先加载了一个预训练的人脸检测器,即`haarcascade_frontalface_default.xml`。然后,我们加载了一个预训练的人脸识别模型,即`trained/model.yml`。接下来,我们读取一个测试图像,并将其转换为灰度图像。然后,我们使用人脸检测器检测图像中的人脸,并对每个检测到的人脸进行识别。最后,我们在图像上绘制识别结果,并显示结果图像。 请确保将代码中的文件路径替换为实际的文件路径。此外,你需要在项目中添加JavaCVOpenCV的依赖项。 这只是一个简单的示例,你可以根据实际需求进行修改和扩展。希望对你有所帮助!
评论 121
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值