您的位置:首页 > 编程语言 > Java开发

javac写的简单的人脸识别知识点

2014-01-09 09:50 489 查看
1.参考java api中的File的用法

从目录中读取图片的名字,获取训练图片的名字

ArrayList<String> imageList = new ArrayList<String>();

File file = new File(filePath);

if (file.isDirectory()) {

String[] fileName = file.list();

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

imageList.add(filePath+"/"+fileName[i]);

}

}else {

return null;

}
2.加载训练图片
IpIImage是openCV库中一个很重要的结构体,库中的我图像都是保存为这个结构体后再进行操作的。用cvLoadImage来获得。如cvLoadImage(image[i], 0);
CvMat* cvCreateMat(int rows, int cols, int type); type: 矩阵元素类型. 格式为CV_<bit_depth>(S|U|F)C<number_of_channels>,例如: CV_8UC1 表示8位无符号单通道矩阵, CV_32SC2表示32位有符号双通道矩阵.
// 将图像数据转换为矩阵保存
CvMat mat = cvCreateMat(image.height(),image.width(),CV_32FC1);
cvConvert(image, mat);
PCA(principal component analysis)翻译过来就是主分量分析,是一种流行的数据降维方法。通过数据降维可以实现数据的压缩,同时方便数据分析和提高算法的处理速度。PCA的原理就是通过正交变换,最大化样本协方差阵的对角元素,最小化非对角元素。
在OPENCV中使用PCA非常简单,只要几条语句就可以了。
1、初始化数据
//每一行表示一个样本
CvMat* pData = cvCreateMat( 总的样本数, 每个样本的维数, CV_32FC1 );
CvMat* pMean = cvCreateMat(1, 样本的维数, CV_32FC1);
//pEigVals中的每个数表示一个特征值
CvMat* pEigVals = cvCreateMat(1, min(总的样本数,样本的维数), CV_32FC1);
//每一行表示一个特征向量
CvMat* pEigVecs = cvCreateMat( min(总的样本数,样本的维数), 样本的维数, CV_32FC1);
2、PCA处理,计算出平均向量pMean,特征值pEigVals和特征向量pEigVecs
cvCalcPCA( pData, pMean, pEigVals, pEigVecs, CV_PCA_DATA_AS_ROW );
3、选出前P个特征向量(主成份),然后投影,结果保存在pResult中,pResult中包含了P个系数
CvMat* pResult = cvCreateMat( 总的样本数, PCA变换后的样本维数(即主成份的数目), CV_32FC1 );
cvProjectPCA( pData, pMean, pEigVecs, pResult );
计算mat间的欧式距离:
double[] num = new double[trainData.rows()];

// 获取测试样本特征向量与训练样本特征矩阵每一行的欧式距离

for (int i = 0; i < trainData.rows(); i++) {

double sum = 0;

for (int j = 0; j < trainData.cols(); j++) {

sum += Math.pow(Math.abs(trainData.get(i, j))

- Math.abs(testData.get(0, j)), 2);

}

num[i] = Math.sqrt(sum);
}
显示图像:
cvShowImage("result", image);
vWaitKey()函数的功能是是程序暂停,等待用户触发一个按键操作。但如果该函数参数设为一个正数,则程序将暂停一段时间,时间长为该整数值个毫秒单位,然后继续执行程序,即使用户没有按下任何键。
代码:

5.3.1 FaceDecetion类的内容

// 待训练的数据

private CvMat trainImagesRow;

// 待识别的数据

private CvMat testImagesRow;

// 降维后的特征矩阵

private CvMat result;

// 测试样本得到的特征向量

private CvMat result2;

private CvMat avg;

private CvMat eigenVectors;

// 训练样本图像路径的集合

private ArrayList<String> photos;

public FaceDecetion() {

// 初始化数据

this.trainImagesRow = null;

this.testImagesRow = null;

this.result = new CvMat();

this.result2 = new CvMat();

this.avg = new CvMat();

this.eigenVectors = new CvMat();

this.photos = new ArrayList<String>();

}

5.3.2 加载有训练样本

获取train文件夹下的训练图片路径

调用方法:

// train为训练样品保存路径

String[] photos = FileUtil.readImageFromDir(“.//train”);

实现方法:

public static String[] readImageFromDir(String filePath) {

ArrayList<String> imageList=new ArrayList<String>();

File file = new File(filePath);

if (file.isDirectory()) {

// 获取文件夹下文件的名字

String[] fileName = file.list();

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

imageList.add(filePath+"/"+fileName[i]);

}

}else {

return null;

}

显示结果如:

.//train/orl_039_005.bmp

5.3.3 获取训练样本特征矩阵

调用方法:

doPCA()

实现方法:

public void doPCA() {

avg = cvCreateMat(1, trainImagesRow.cols(), CV_32FC1);

// 训练特征向量

CvMat eigenValues = cvCreateMat(1,

Math.min(trainImagesRow.rows(), trainImagesRow.cols()),

CV_32FC1);

eigenVectors = cvCreateMat(

Math.min(trainImagesRow.rows(), trainImagesRow.cols()),

trainImagesRow.cols(), CV_32FC1);

// 取特征向量的前P个特征值,作为比较结果

result = cvCreateMat(trainImagesRow.rows(),

Math.min(trainImagesRow.rows(), trainImagesRow.cols()),

CV_32FC1);

cvCalcPCA(trainImagesRow, avg, eigenValues, eigenVectors,

CV_PCA_DATA_AS_ROW);

// 生成训练样本特征矩阵

cvProjectPCA(trainImagesRow, avg, eigenVectors, result);

}

5.3.4 加载测试样本图片文件

调用方法:

loadTestImageData(".//test//orl_003_009.bmp");

实现方法:

public void loadTestImageData(String imagePath) {

// 根据图像文件的路径,将文件加载为IplImage类型

IplImage image = cvLoadImage(imagePath, 0);

// 根据image生成同样大小的测试样本矩阵

testImagesRow = cvCreateMat(1, image.width() * image.height(), CV_32FC1);

// 将图像数据保存为CvMat后加载至测试样本矩阵中

CvMat mat = cvCreateMat(image.height(), image.width(), CV_32FC1);

cvConvert(image, mat);

int index = 0;

for (int i = 0; i < mat.rows(); i++) {

for (int j = 0; j < mat.cols(); j++) {

testImagesRow.put(0, index, mat.get(i, j));

index++;

}

}

// 按照测试样本的大小,生成测试样本特征向量的大小

result2 = cvCreateMat(testImagesRow.rows(), result.cols(), CV_32FC1);

// 生成测试样本特征向量

cvProjectPCA(testImagesRow, avg, eigenVectors, result2);

}

5.3.5 获取欧式距离

调用方法:

euclideanDistance(result, result2)

实现方法:

public int euclideanDistance(CvMat trainData, CvMat testData) {

double[] num = new double[trainData.rows()];

// 获取测试样本特征向量与训练样本特征矩阵每一行的欧式距离

for (int i = 0; i < trainData.rows(); i++) {

double sum = 0;

for (int j = 0; j < trainData.cols(); j++) {

sum += Math.pow(Math.abs(trainData.get(i, j))

- Math.abs(testData.get(0, j)), 2);

}

num[i] = Math.sqrt(sum);

}

// 获取欧氏距离的和中最小的类的序号

return minArrayElement(num);

}

5.3.6 显示识别结果

调用方法:

faceDecetion.showResult(faceDecetion.photos, testImage);

实现方法:

public void showResult(ArrayList<String> photos, String testImage) {

// 取得是结果的类序号

int num = euclideanDistance(result, result2);

// 按类序号乘以类中图片的数量,获取识别结果的图像路径,显示图像

cvShowImage("result", cvLoadImage(photos.get(num * 5)));

// 根据测试样本图像的路径,显示图像

cvShowImage("src", cvLoadImage(testImage));

cvWaitKey(500000);

}

5.3 测试过程

mian函数调用流程:

FaceDecetion faceDecetion = new FaceDecetion();

// 项目根目录下的train文件夹中,保存有训练样本orl图像文件200张

String str1 = ".//train";

String[] photos = FileUtil.readImageFromDir(str1);

// 加载训练图片

faceDecetion.loadTrainImageData(photos);

// 显示识别结果

faceDecetion.doPCA();

// 测试图片

String testImage = ".//test//orl_003_009.bmp";

faceDecetion.loadTestImageData(testImage);

// 显示识别结果

faceDecetion.showResult(faceDecetion.photos, testImage);

// 将训练样本的特征矩阵写入文本文件中

FileUtil.writeMatToFile(faceDecetion.getResult(),".//data//cvMat.txt");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: