Javacv下人脸识别算法EigenFace

这是我当年在安卓上用的一个人脸识别的算法。主要是用了PCA降维的方式,然后用欧式距离比较下最近的人脸。

趁热来一波刚出炉的Javacv写的特征脸算法,写得不是很好,但是也是费了一小番心思做的。我知道还有很多写得不好不对的地方,望请大家指正。不多说了,知道你们想看代码。


import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacpp.opencv_core.*;
import org.bytedeco.javacv.JavaCV;
import org.opencv.core.Core;

import android.util.Log;
import org.opencv.core.CvType;
import org.opencv.imgproc.Imgproc;
import static org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_highgui.*;
import static org.bytedeco.javacpp.opencv_imgproc.equalizeHist;
/**
 * 特征脸算法
 * @author 火烫火烫的
 *
 */
public class Eigenface {
	private double threshold = -1;	//阈值,不设置返回最相似的距离的标签
	private int num_components = -1;
	private PCA pca = null;
	private Mat result;	//经过投影后的矩阵
	private Mat labels;
	public double getThreshold() {
		return threshold;
	}

	public void setThreshold(double threshold) {
		this.threshold = threshold;
	}

	public int getNum_components() {
		return num_components;
	}

	public void setNum_components(int num_components) {
		this.num_components = num_components;
	}

	
	public Eigenface() {
	}

	public Eigenface(int num_components, double threshold) {
		super();
		this.threshold = threshold;
		this.num_components = num_components;
	}

	/**
	 * 训练方法
	 * @param images
	 * @param labels
	 */
	public void train(MatVector images, Mat labels) {
		this.labels = labels;
		Mat allsamples = new Mat();	//所有样本以行存放
		Mat mat;
		Mat convertMat = new Mat();	//转变后的矩阵
		Mat placeholder = new Mat();
		for (int i = 0; i < images.size(); ++i) {	//遍历每一个Mat
			mat = images.get(i);
			mat.reshape(1, 1).row(0).convertTo(convertMat, CV_32FC1);
			allsamples.push_back(convertMat);
		}
		if (num_components != -1) {	//说明最大维度为设置过
			pca = new PCA(allsamples, placeholder, CV_PCA_DATA_AS_ROW, num_components);	//pca
		} else {
			pca = new PCA(allsamples, placeholder, CV_PCA_DATA_AS_ROW);	//pca
		}
		result = pca.project(allsamples);
		Log.e("The size of result", result.rows() + "|" + result.cols());
	}
	
	/**
	 * 进行识别
	 * @param testImage
	 * @return 识别的标签,-1代表失败,-2代表没训练
	 */
	public int predict(Mat testImage) {
		if (pca != null) {
			Mat convertMat = new Mat();
			testImage.reshape(1, 1).row(0).convertTo(convertMat, CV_32FC1);
			IntBuffer labelsBuf = labels.getIntBuffer();
			double[] distance = new double[result.rows()];
			Mat testResult = pca.project(convertMat);
			Log.e("The size of testResult", testResult.rows() + "|" + testResult.cols());
			double min_distance = 0;
			int min_i = -1;
			for (int i = 0; i < result.rows(); i++){	//对每个向量进行求欧式距离
				distance[i] = norm(testResult, result.row(i));
				Log.e("distance", "" + distance[i]);
				if (i == 0) {
					min_distance = distance[0];
					min_i = i;
				} else if (min_distance > distance[i]){	//说明新的这个距离更小
					min_distance = distance[i];
					min_i = i;
				}
			}
			int label = -1;	//识别标签
			for (int i = 0; i <= min_i; ++i) {	//对应着取几次
				if (labelsBuf.hasRemaining()) {
					label = labelsBuf.get();
				} else {
					label = -1;
				}
			}
			if (threshold >= 0) {	//说明阈值被设置过
				if (threshold > min_distance) {	//是否超过阈值
					return label;
				} else {
					return -1;
				}
			} else {
				return label;
			}
		} else {
			return -2;
		}
	}
	
	/**
	 * 用来求欧式距离的
	 * @param mat1
	 * @param mat2
	 * @return
	 */
	public double norm(Mat mat1, Mat mat2) {
		return cvNorm(mat1.asCvMat(), mat2.asCvMat());
	}
	
}

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值