[java]代码库
import com.googlecode.javacpp.FloatPointer;
import com.googlecode.javacpp.Pointer;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import static com.googlecode.javacv.cpp.opencv_highgui.cvWaitKey;
import static com.googlecode.javacv.cpp.opencv_highgui.cvShowImage;
import static com.googlecode.javacv.cpp.opencv_highgui.cvSaveImage;
import static com.googlecode.javacv.cpp.opencv_highgui.cvDestroyWindow;
import static com.googlecode.javacv.cpp.opencv_highgui.CV_LOAD_IMAGE_GRAYSCALE;
import static com.googlecode.javacv.cpp.opencv_highgui.cvLoadImage;
import com.googlecode.javacv.FrameGrabber;
import com.googlecode.javacv.FrameGrabber.Exception;
import com.googlecode.javacv.OpenCVFrameGrabber;
import com.googlecode.javacv.VideoInputFrameGrabber;
import com.googlecode.javacv.cpp.opencv_core.CvFont;
import com.googlecode.javacv.cpp.opencv_core.CvMemStorage;
import com.googlecode.javacv.cpp.opencv_core.CvPoint;
import com.googlecode.javacv.cpp.opencv_core.CvRect;
import com.googlecode.javacv.cpp.opencv_core.CvScalar;
import com.googlecode.javacv.cpp.opencv_core.CvSeq;
import com.googlecode.javacv.cpp.opencv_core.IplImage;
import static com.googlecode.javacv.cpp.opencv_legacy.*;
import static com.googlecode.javacv.cpp.opencv_objdetect.CV_HAAR_DO_CANNY_PRUNING;
import static com.googlecode.javacv.cpp.opencv_objdetect.CV_HAAR_FIND_BIGGEST_OBJECT;
import static com.googlecode.javacv.cpp.opencv_objdetect.CV_HAAR_DO_ROUGH_SEARCH;
import static com.googlecode.javacv.cpp.opencv_objdetect.cvHaarDetectObjects;
import static com.googlecode.javacv.cpp.opencv_imgproc.CV_BGR2GRAY;
import static com.googlecode.javacv.cpp.opencv_imgproc.cvEqualizeHist;
import com.googlecode.javacv.cpp.opencv_objdetect.CvHaarClassifierCascade;
import static com.googlecode.javacv.cpp.opencv_core.CvMat;
import static com.googlecode.javacv.cpp.opencv_core.cvReleaseImage;
import static com.googlecode.javacv.cpp.opencv_core.cvLoad;
import static com.googlecode.javacv.cpp.opencv_core.CV_FONT_HERSHEY_COMPLEX_SMALL;
import static com.googlecode.javacv.cpp.opencv_core.cvGetSize;
import static com.googlecode.javacv.cpp.opencv_core.CV_32FC1;
import static com.googlecode.javacv.cpp.opencv_core.cvCreateMat;
import static com.googlecode.javacv.cpp.opencv_core.cvCloneImage;
import static com.googlecode.javacv.cpp.opencv_core.IPL_DEPTH_8U;
import static com.googlecode.javacv.cpp.opencv_core.cvCreateImage;
import static com.googlecode.javacv.cpp.opencv_core.CvSize;
import static com.googlecode.javacv.cpp.opencv_core.cvResetImageROI;
import static com.googlecode.javacv.cpp.opencv_core.cvClearMemStorage;
import static com.googlecode.javacv.cpp.opencv_core.cvSize;
import static com.googlecode.javacv.cpp.opencv_core.cvCopy;
import static com.googlecode.javacv.cpp.opencv_core.cvSetImageROI;
import static com.googlecode.javacv.cpp.opencv_core.CV_AA;
import static com.googlecode.javacv.cpp.opencv_core.cvPoint;
import static com.googlecode.javacv.cpp.opencv_core.cvInitFont;
import static com.googlecode.javacv.cpp.opencv_core.cvGetSeqElem;
import static com.googlecode.javacv.cpp.opencv_core.cvRectangle;
import static com.googlecode.javacv.cpp.opencv_core.cvPutText;
import static com.googlecode.javacv.cpp.opencv_core.CV_32SC1;
import static com.googlecode.javacv.cpp.opencv_core.CvTermCriteria;
import static com.googlecode.javacv.cpp.opencv_core.IPL_DEPTH_32F;
import static com.googlecode.javacv.cpp.opencv_core.CV_L1;
import static com.googlecode.javacv.cpp.opencv_core.CV_TERMCRIT_ITER;
import static com.googlecode.javacv.cpp.opencv_core.cvNormalize;
import static com.googlecode.javacv.cpp.opencv_core.CvFileStorage;
import static com.googlecode.javacv.cpp.opencv_core.cvWriteInt;
import static com.googlecode.javacv.cpp.opencv_core.cvTermCriteria;
import static com.googlecode.javacv.cpp.opencv_core.CV_STORAGE_WRITE;
import static com.googlecode.javacv.cpp.opencv_core.cvOpenFileStorage;
import static com.googlecode.javacv.cpp.opencv_core.cvWrite;
import static com.googlecode.javacv.cpp.opencv_core.cvWriteString;
import static com.googlecode.javacv.cpp.opencv_core.cvReleaseFileStorage;
import static com.googlecode.javacv.cpp.opencv_core.CV_STORAGE_READ;
import static com.googlecode.javacv.cpp.opencv_core.cvReadIntByName;
import static com.googlecode.javacv.cpp.opencv_core.cvReadStringByName;
import static com.googlecode.javacv.cpp.opencv_core.cvReadByName;
import static com.googlecode.javacv.cpp.opencv_core.cvRect;
import static com.googlecode.javacv.cpp.opencv_core.cvConvertScale;
import static com.googlecode.javacv.cpp.opencv_core.cvMinMaxLoc;
import static com.googlecode.javacv.cpp.opencv_imgproc.CV_INTER_LINEAR;
import static com.googlecode.javacv.cpp.opencv_imgproc.CV_INTER_AREA;
import static com.googlecode.javacv.cpp.opencv_imgproc.cvResize;
import static com.googlecode.javacv.cpp.opencv_imgproc.cvCvtColor;
import java.io.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
public class FaceRecognizer{
private static final Logger LOGGER = Logger.getLogger(FaceRecognizer.class.getName());
private int nTrainFaces = 0;
private int nPersons=0;
private int nEigens = 0;
private int countSavedFace=1;
private CvMat personNumTruthMat;
private CvMat eigenValMat;
private CvMat projectedTrainFaceMat;
private CvMat trainPersonNumMat=null;
final static List<String> personNames = new ArrayList<String>();
private CvHaarClassifierCascade cascade = new CvHaarClassifierCascade(cvLoad("data\\haarcascade_frontalface_alt2.xml"));
private static final int newWidth=50;
private static final int newHeight=50;
IplImage[] eigenVectArr;
IplImage[] trainingFaceImgArr;
IplImage[] testFaceImgArr;
IplImage pAvgTrainImg;
public static String personName;
private static String textName="unknow";
public static double g_confidence=0;
public FaceRecognizer() {
trainPersonNumMat = loadTrainingData();
}
private void learn(final String trainingFileName) {
int i;
// load training data
LOGGER.info("===========================================");
LOGGER.info("Loading the training images in " + trainingFileName);
trainingFaceImgArr = loadFaceImgArray(trainingFileName);
nTrainFaces = trainingFaceImgArr.length;
LOGGER.info("Got " + nTrainFaces + " training images");
if (nTrainFaces < 3) {
LOGGER.severe("Need 3 or more training faces\n"
+ "Input file contains only " + nTrainFaces);
return;
}
// do Principal Component Analysis on the training faces
doPCA();
LOGGER.info("projecting the training images onto the PCA subspace");
// project the training images onto the PCA subspace
projectedTrainFaceMat = cvCreateMat(
nTrainFaces, // rows
nEigens, // cols
CV_32FC1); // type, 32-bit float, 1 channel
// initialize the training face matrix - for ease of debugging
for (int i1 = 0; i1 < nTrainFaces; i1++) {
for (int j1 = 0; j1 < nEigens; j1++) {
projectedTrainFaceMat.put(i1, j1, 0.0);
}
}
LOGGER.info("created projectedTrainFaceMat with " + nTrainFaces + " (nTrainFaces) rows and " + nEigens + " (nEigens) columns");
if (nTrainFaces < 5) {
LOGGER.info("projectedTrainFaceMat contents:\n" + oneChannelCvMatToString(projectedTrainFaceMat));
}
final FloatPointer floatPointer = new FloatPointer(nEigens);
for (i = 0; i < nTrainFaces; i++) {
cvEigenDecomposite(
trainingFaceImgArr[i], // obj
nEigens, // nEigObjs
eigenVectArr, // eigInput (Pointer)
0, // ioFlags
null, // userData (Pointer)
pAvgTrainImg, // avg
floatPointer); // coeffs (FloatPointer)
if (nTrainFaces < 5) {
LOGGER.info("floatPointer: " + floatPointerToString(floatPointer));
}
for (int j1 = 0; j1 < nEigens; j1++) {
projectedTrainFaceMat.put(i, j1, floatPointer.get(j1));
}
}
if (nTrainFaces < 5) {
LOGGER.info("projectedTrainFaceMat after cvEigenDecomposite:\n" + projectedTrainFaceMat);
}
// store the recognition data as an xml file
storeTrainingData();
// Save all the eigenvectors as images, so that they can be checked.
storeEigenfaceImages();
}
private IplImage convertImageToGreyscale(IplImage imageSrc)
{
IplImage imageGrey;
// Either convert the image to greyscale, or make a copy of the existing greyscale image.
// This is to make sure that the user can always call cvReleaseImage() on the output, whether it was greyscale or not.
if (imageSrc.nChannels()==3) {
imageGrey = cvCreateImage( cvGetSize(imageSrc), IPL_DEPTH_8U, 1 );
cvCvtColor( imageSrc, imageGrey, CV_BGR2GRAY );
}
else {
imageGrey = cvCloneImage(imageSrc);
}
return imageGrey;
}
private IplImage resizeImage(IplImage origImg)
{
IplImage outImg = null;
int origWidth=0;
int origHeight=0;
if (origImg!=null) {
origWidth = origImg.width();
origHeight = origImg.height();
}
if (newWidth <= 0 || newHeight <= 0 || origImg == null || origWidth <= 0 || origHeight <= 0) {
LOGGER.info("ERROR in resizeImage: Bad desired image size of");
LOGGER.info(String.valueOf(newWidth)+","+String.valueOf(newHeight));
System.exit(1);
}
// Scale the image to the new dimensions, even if the aspect ratio will be changed.
outImg = cvCreateImage(cvSize(newWidth, newHeight), origImg.depth(), origImg.nChannels());
if (newWidth > origImg.width() && newHeight > origImg.height()) {
// Make the image larger
cvResetImageROI((IplImage)origImg);
cvResize(origImg, outImg, CV_INTER_LINEAR); // CV_INTER_CUBIC or CV_INTER_LINEAR is good for enlarging
}
else {
// Make the image smaller
cvResetImageROI((IplImage)origImg);
cvResize(origImg, outImg, CV_INTER_AREA); // CV_INTER_AREA is good for shrinking / decimation, but bad at enlarging.
}
return outImg;
}
private IplImage cropImage(IplImage img, CvRect region)
{
IplImage imageTmp;
IplImage imageRGB;
// size.height()=img.height();
// size.width() = img.width();
if (img.depth() != IPL_DEPTH_8U) {
LOGGER.info("ERROR in cropImage: Unknown image depth of");
LOGGER.info(String.valueOf(img.depth()));
LOGGER.info(" given in cropImage() instead of 8 bits per pixel.");
System.exit(1);
}
// First create a new (color or greyscale) IPL Image and copy contents of img into it.
imageTmp = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, img.nChannels());
cvCopy(img, imageTmp);
// Create a new image of the detected region
// Set region of interest to that surrounding the face
cvSetImageROI(imageTmp, region);
// Copy region of interest (i.e. face) into a new iplImage (imageRGB) and return it
imageRGB = cvCreateImage(cvSize(region.width(),region.height()), IPL_DEPTH_8U, img.nChannels());
cvCopy(imageTmp, imageRGB); // Copy just the region.
cvReleaseImage(imageTmp);
//region.setNull();
return imageRGB;
}
public boolean recognizeFromCam() throws Exception
{
OpenCVFrameGrabber grabber = null;
FileDialog fd;
IplImage pFrame=null;
int keypress = 0;
if(LoginShell.video_flag)//如果被选,刚用视频
{
fd=new FileDialog(LoginShell.sShell,SWT.OPEN);
fd.setFilterExtensions(new String[]{"*.avi","*.wmv","*.mp4","*.*"});
fd.setFilterNames(new String[]{".avi",".wmv",".mp4"});
String filename=fd.open();
grabber = OpenCVFrameGrabber.createDefault(filename);
}
else
grabber = OpenCVFrameGrabber.createDefault(0);
grabber.start();
pFrame = grabber.grab();
while( pFrame!=null ){
detectAndCropAndPre( pFrame,cascade,CV_HAAR_DO_CANNY_PRUNING | CV_HAAR_DO_ROUGH_SEARCH);
cvShowImage("Press 'Esc' to Stop!",pFrame);
pFrame = grabber.grab();
keypress=cvWaitKey(24);
System.out.println(g_confidence);
if( keypress== 27){
grabber.release();
cvDestroyWindow("Press 'Esc' to Stop!");
break;
}
}
cvWaitKey(1000);
cvReleaseImage(pFrame);
//cvDestroyWindow("BP_FaceRecognizer_FaceLogin");
grabber.release();
return false;
}
public void recongizeFormImage(String filePath){
IplImage signleImage=null;
System.out.println(filePath);
signleImage=cvLoadImage(filePath);
if(!signleImage.isNull());
detectAndCropFromImg(signleImage,cascade,CV_HAAR_DO_CANNY_PRUNING | CV_HAAR_DO_ROUGH_SEARCH);
cvShowImage("Press 'Esc' to exit",signleImage);
cvWaitKey(0);
cvDestroyWindow("Press 'Esc' to exit");
}
public boolean register(String name)throws Exception
{
boolean flag=true;
OpenCVFrameGrabber grabber = null;
FileDialog fd;
IplImage pFrame=null;
int keypress = 0;
int countSecond=0;
for(int i=0;i<personNames.size();i++){
if(name.equals(personNames.get(i).toString()))
{
MessageBox messageBox = new MessageBox(RegisterShell.sShell, SWT.ICON_QUESTION |SWT.YES | SWT.NO);
messageBox.setMessage("此用户已经被使用!!!连续按 “否” 返回");
messageBox.open();
flag=false;
}
}
if(LoginShell.video_flag)//用视频文件进行注册
{
fd=new FileDialog(LoginShell.sShell,SWT.OPEN);
fd.setFilterExtensions(new String[]{"*.avi","*.wmv","*.mp4","*.*"});
fd.setFilterNames(new String[]{".avi",".wmv",".mp4"});
String filename=fd.open();
grabber = OpenCVFrameGrabber.createDefault(filename);
}
else
grabber = OpenCVFrameGrabber.createDefault(0);
grabber.start();
pFrame = grabber.grab();
while( pFrame!=null )
{
countSecond++;
detectForRegister(pFrame,cascade,CV_HAAR_FIND_BIGGEST_OBJECT | CV_HAAR_DO_ROUGH_SEARCH,name);
cvShowImage("Press 'Esc' to Stop",pFrame);
pFrame = grabber.grab();
keypress=cvWaitKey(24);
if( keypress== 27 ||countSecond==100||countSavedFace==6)//||second==60
{
cvReleaseImage(pFrame);
grabber.release();
break;
}
}
personNames.add(name);
writeNameToTXT(name);
learn("data\\ForTraining.txt");
cvDestroyWindow("Press 'Esc' to Stop");
return flag;
}
private void detectForRegister(IplImage src,CvHaarClassifierCascade cascade,int flag,String name){
IplImage greyImg=null;
IplImage faceImg=null;
IplImage sizedImg=null;
IplImage equalizedImg=null;
CvRect r ;
CvFont font = new CvFont(CV_FONT_HERSHEY_COMPLEX_SMALL, 1, 1);
cvInitFont(font,CV_FONT_HERSHEY_COMPLEX_SMALL, 1.0, 0.8,1,1,CV_AA);
greyImg = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1 );
greyImg=convertImageToGreyscale(src);
CvMemStorage storage = CvMemStorage.create();
CvSeq sign = cvHaarDetectObjects(
greyImg,
cascade,
storage,
1.1,
3,
flag);
cvClearMemStorage(storage);
if(sign.total()==1)//只会有一个脸部
{
r = new CvRect(cvGetSeqElem(sign, 0));
faceImg = cropImage(greyImg, r);
sizedImg = resizeImage(faceImg);
equalizedImg = cvCreateImage(cvGetSize(sizedImg), 8, 1);
cvEqualizeHist(sizedImg, equalizedImg);
cvRectangle (
src,
cvPoint(r.x(), r.y()),
cvPoint(r.width() + r.x(), r.height() + r.y()),
CvScalar.WHITE,
1,
CV_AA,
0);
cvPutText(src, "This is your No."+String.valueOf(countSavedFace)+" photos. " ,cvPoint(r.x()-30, r.y() + r.height() + 30), font, CvScalar.RED);
cvSaveImage("img\\"+name+countSavedFace+".jpg",equalizedImg);
cvWaitKey(1000);
countSavedFace++;
cvReleaseImage(greyImg);
cvReleaseImage(faceImg);
cvReleaseImage(sizedImg);
cvReleaseImage(equalizedImg);
}
}
private void writeNameToTXT(String name){
String text=null;
int temp;
temp=personNames.size();
if(temp==0)
temp=temp+1;
try {
File file = new File("data\\ForTraining.txt");
FileOutputStream fos = new FileOutputStream(file,true);
OutputStreamWriter osw = new OutputStreamWriter(fos);
BufferedWriter bw = new BufferedWriter(osw);
// if(personNames.size()==0)
for(int i=1;i<6;i++){
text=temp+" "+name+" "+"img\\"+name+i+".jpg";
bw.write(text);
bw.newLine();
}
bw.flush();
bw.close();
osw.close();
fos.close();
}
catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e2) {
e2.printStackTrace();
}
}
private void eigenDecomImg(IplImage src){
//CvMat trainPersonNumMat=null;
float confidence = 0.0f;
int nearest=0;
int iNearest=0;
LOGGER.info("=====================================Waiting For the camera .....");
//
if( trainPersonNumMat==null) {
LOGGER.info("ERROR in recognizeFromCam(): Couldn't load the training data!\n");
System.exit(1);
}
float[] projectedTestFace = new float[nEigens];
cvEigenDecomposite(
src,
nEigens,
eigenVectArr,
0,
null,
pAvgTrainImg,
projectedTestFace);
final FloatPointer pConfidence = new FloatPointer(confidence);
iNearest = findNearestNeighbor(projectedTestFace, new FloatPointer(pConfidence));
confidence = pConfidence.get();
nearest = trainPersonNumMat.data_i().get(iNearest);
personName="";
textName=personNames.get(nearest-1);
personName=personNames.get(nearest-1);
g_confidence=confidence;
}
private void detectAndCropAndPre(IplImage src,CvHaarClassifierCascade cascade,int flag)
{
int nearest=0;
IplImage greyImg=null;
IplImage faceImg=null;
IplImage sizedImg=null;
IplImage equalizedImg=null;
boolean faceIsTrue=false;
CvRect r ;
CvFont font = new CvFont(CV_FONT_HERSHEY_COMPLEX_SMALL, 1, 1);
cvInitFont(font,CV_FONT_HERSHEY_COMPLEX_SMALL, 1.0, 0.8,1,1,CV_AA);
greyImg = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1 );
greyImg=convertImageToGreyscale(src);
CvMemStorage storage = CvMemStorage.create();
CvSeq sign = cvHaarDetectObjects(
greyImg,
cascade,
storage,
1.1,
3,
flag);
cvClearMemStorage(storage);
if(sign.total()>0)
{
for(int i=0;i<sign.total();i++)
{
r = new CvRect(cvGetSeqElem(sign, i));
faceImg = cropImage(greyImg, r);
sizedImg = resizeImage(faceImg);
if(i==0)
equalizedImg = cvCreateImage(cvGetSize(sizedImg), 8, 1);
cvEqualizeHist(sizedImg, equalizedImg);
cvRectangle (
src,
cvPoint(r.x(), r.y()),
cvPoint(r.width() + r.x(), r.height() + r.y()),
CvScalar.WHITE,
1,
CV_AA,
0);
eigenDecomImg(equalizedImg);
if(g_confidence*100>50){
cvPutText(src, textName,cvPoint(r.x()-10, r.y() + r.height() + 20), font, CvScalar.WHITE);
cvPutText(src, " conf="+Integer.valueOf((int) (g_confidence*100))+"%",cvPoint(r.x()-10, r.y() + r.height() + 40), font, CvScalar.GREEN);
textName="unknow";
}
else {
cvPutText(src, "unknow",cvPoint(r.x()-10, r.y() + r.height() + 20), font, CvScalar.WHITE);
cvPutText(src, " conf="+Integer.valueOf((int) (g_confidence*100))+"%",cvPoint(r.x()-10, r.y() + r.height() + 40), font, CvScalar.GREEN);
}
}
cvReleaseImage(greyImg);
cvReleaseImage(faceImg);
cvReleaseImage(sizedImg);
cvReleaseImage(equalizedImg);
}
}
private void detectAndCropFromImg(IplImage src,CvHaarClassifierCascade cascade,int flag)
{
IplImage greyImg=null;
IplImage faceImg=null;
IplImage sizedImg=null;
IplImage equalizedImg=null;
CvRect r ;
CvFont font = new CvFont(CV_FONT_HERSHEY_COMPLEX_SMALL, 1, 1);
cvInitFont(font,CV_FONT_HERSHEY_COMPLEX_SMALL, 1.0, 0.8,1,1,CV_AA);
greyImg = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1 );
greyImg=convertImageToGreyscale(src);
CvMemStorage storage = CvMemStorage.create();
CvSeq sign = cvHaarDetectObjects(
greyImg,
cascade,
storage,
1.1,
3,
flag);
cvClearMemStorage(storage);
if(sign.total()>0)
{
for(int i=0;i<sign.total();i++)
{
r = new CvRect(cvGetSeqElem(sign, i));
faceImg = cropImage(greyImg, r);
sizedImg = resizeImage(faceImg);
if(i==0)
equalizedImg = cvCreateImage(cvGetSize(sizedImg), 8, 1);
cvEqualizeHist(sizedImg, equalizedImg);
cvRectangle (
src,
cvPoint(r.x(), r.y()),
cvPoint(r.width() + r.x(), r.height() + r.y()),
CvScalar.WHITE,
1,
CV_AA,
0);
eigenDecomImg(equalizedImg);
if(g_confidence*100>50){
cvPutText(src, textName,cvPoint(r.x()-10, r.y() + r.height() + 20), font, CvScalar.WHITE);
cvPutText(src, " conf="+Integer.valueOf((int) (g_confidence*100))+"%",cvPoint(r.x()-10, r.y() + r.height() + 40), font, CvScalar.GREEN);
textName="unknow";
}
else{
cvPutText(src, "Unknow",cvPoint(r.x()-10, r.y() + r.height() + 20), font, CvScalar.WHITE);
cvPutText(src, " conf="+Integer.valueOf((int) (g_confidence*100))+"%",cvPoint(r.x()-10, r.y() + r.height() + 40), font, CvScalar.GREEN);
}
}
}
else
cvPutText(src, "can't find any face!",cvPoint(src.width()/2, src.height()/2), font, CvScalar.GREEN);
//cvReleaseImage(greyImg);
//if(!faceImg.isNull())
// cvReleaseImage(faceImg);
//cvReleaseImage(sizedImg);
//cvReleaseImage(equalizedImg);
}
private IplImage[] loadFaceImgArray(final String filename) {
IplImage[] faceImgArr;
BufferedReader imgListFile;
String imgFilename;
int iFace = 0;
int nFaces = 0;
int i;
try {
// open the input file
imgListFile = new BufferedReader(new FileReader(filename));
// count the number of faces
while (true) {
final String line = imgListFile.readLine();
if (line == null || line.isEmpty()) {
break;
}
nFaces++;
}
LOGGER.info("nFaces: " + nFaces);
imgListFile = new BufferedReader(new FileReader(filename));
// allocate the face-image array and person number matrix
faceImgArr = new IplImage[nFaces];
personNumTruthMat = cvCreateMat(
1, // rows
nFaces, // cols
CV_32SC1); // type, 32-bit unsigned, one channel
// initialize the person number matrix - for ease of debugging
for (int j1 = 0; j1 < nFaces; j1++) {
personNumTruthMat.put(0, j1, 0);
}
personNames.clear(); // Make sure it starts as empty.
nPersons = 0;
// store the face images in an array
for (iFace = 0; iFace < nFaces; iFace++) {
String personName;
String sPersonName;
int personNumber;
// read person number (beginning with 1), their name and the image filename.
final String line = imgListFile.readLine();
if (line.isEmpty()) {
break;
}
final String[] tokens = line.split(" ");
personNumber = Integer.parseInt(tokens[0]);
personName = tokens[1];
imgFilename = tokens[2];
sPersonName = personName;
LOGGER.info("Got " + iFace + " " + personNumber + " " + personName + " " + imgFilename);
// Check if a new person is being loaded.
if (personNumber > nPersons) {
// Allocate memory for the extra person (or possibly multiple), using this new person's name.
personNames.add(sPersonName);
nPersons = personNumber;
LOGGER.info("Got new person " + sPersonName + " -> nPersons = " + nPersons + " [" + personNames.size() + "]");
}
// Keep the data
personNumTruthMat.put(
0, // i
iFace, // j
personNumber); // v
// load the face image
faceImgArr[iFace] = cvLoadImage(
imgFilename, // filename
CV_LOAD_IMAGE_GRAYSCALE); // isColor
if (faceImgArr[iFace] == null) {
throw new RuntimeException("Can't load image from " + imgFilename);
}
}
imgListFile.close();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
LOGGER.info("Data loaded from '" + filename + "': (" + nFaces + " images of " + nPersons + " people).");
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("People: ");
if (nPersons > 0) {
stringBuilder.append("<").append(personNames.get(0)).append(">");
}
for (i = 1; i < nPersons && i < personNames.size(); i++) {
stringBuilder.append(", <").append(personNames.get(i)).append(">");
}
LOGGER.info(stringBuilder.toString());
return faceImgArr;
}
private void doPCA() {
int i;
CvTermCriteria calcLimit;
CvSize faceImgSize = new CvSize();
// set the number of eigenvalues to use
nEigens = nTrainFaces-1 ;
LOGGER.info("allocating images for principal component analysis, using " + nEigens + (nEigens == 1 ? " eigenvalue" : " eigenvalues"));
// allocate the eigenvector images
faceImgSize.width(trainingFaceImgArr[0].width());
faceImgSize.height(trainingFaceImgArr[0].height());
eigenVectArr = new IplImage[nEigens];
for (i = 0; i < nEigens; i++) {
eigenVectArr[i] = cvCreateImage(
faceImgSize, // size
IPL_DEPTH_32F, // depth
1); // channels
}
// allocate the eigenvalue array
eigenValMat = cvCreateMat(
1, // rows
nEigens, // cols
CV_32FC1); // type, 32-bit float, 1 channel
// allocate the averaged image
pAvgTrainImg = cvCreateImage(
faceImgSize, // size
IPL_DEPTH_32F, // depth
1); // channels
// set the PCA termination criterion
calcLimit = cvTermCriteria(
CV_TERMCRIT_ITER, // type
nEigens, // max_iter
1); // epsilon
LOGGER.info("computing average image, eigenvalues and eigenvectors");
// compute average image, eigenvalues, and eigenvectors
cvCalcEigenObjects(
nTrainFaces, // nObjects
trainingFaceImgArr, // input
eigenVectArr, // output
CV_EIGOBJ_NO_CALLBACK, // ioFlags
0, // ioBufSize
null, // userData
calcLimit,
pAvgTrainImg, // avg
eigenValMat.data_fl()); // eigVals
LOGGER.info("normalizing the eigenvectors");
cvNormalize(
eigenValMat, // src (CvArr)
eigenValMat, // dst (CvArr)
1, // a
0, // b
CV_L1, // norm_type
null); // mask
}
private void storeTrainingData() {
CvFileStorage fileStorage;
int i;
LOGGER.info("writing data/facedata.xml");
// create a file-storage interface
fileStorage = cvOpenFileStorage(
"data\\facedata.xml", // filename
null, // memstorage
CV_STORAGE_WRITE, // flags
null); // encoding
// Store the person names. Added by Shervin.
cvWriteInt(
fileStorage, // fs
"nPersons", // name
nPersons); // value
for (i = 0; i < nPersons; i++) {
String varname = "personName_" + (i + 1);
cvWriteString(
fileStorage, // fs
varname, // name
personNames.get(i), // string
0); // quote
}
// store all the data
cvWriteInt(
fileStorage, // fs
"nEigens", // name
nEigens); // value
cvWriteInt(
fileStorage, // fs
"nTrainFaces", // name
nTrainFaces); // value
cvWrite(
fileStorage, // fs
"trainPersonNumMat", // name
personNumTruthMat); // value
cvWrite(
fileStorage, // fs
"eigenValMat", // name
eigenValMat); // value
cvWrite(
fileStorage, // fs
"projectedTrainFaceMat", // name
projectedTrainFaceMat);
cvWrite(fileStorage, // fs
"avgTrainImg", // name
pAvgTrainImg); // value
for (i = 0; i < nEigens; i++) {
String varname = "eigenVect_" + i;
cvWrite(
fileStorage, // fs
varname, // name
eigenVectArr[i]); // value
}
// release the file-storage interface
cvReleaseFileStorage(fileStorage);
}
private CvMat loadTrainingData() {
LOGGER.info("loading training data");
CvMat pTrainPersonNumMat = null; // the person numbers during training
CvFileStorage fileStorage;
int i;
// create a file-storage interface
fileStorage = cvOpenFileStorage(
"data\\facedata.xml", // filename
null, // memstorage
CV_STORAGE_READ, // flags
null); // encoding
if (fileStorage == null) {
LOGGER.severe("Can't open training database file 'data/facedata.xml'.");
return null;
}
// Load the person names.
personNames.clear(); // Make sure it starts as empty.
nPersons = cvReadIntByName(
fileStorage, // fs
null, // map
"nPersons", // name
0); // default_value
if (nPersons == 0) {
LOGGER.severe("No people found in the training database 'data/facedata.xml'.");
return null;
} else {
LOGGER.info(nPersons + " persons read from the training database");
}
// Load each person's name.
for (i = 0; i < nPersons; i++) {
String sPersonName;
String varname = "personName_" + (i + 1);
sPersonName = cvReadStringByName(
fileStorage, // fs
null, // map
varname,
"");
personNames.add(sPersonName);
}
LOGGER.info("person names: " + personNames);
// Load the data
nEigens = cvReadIntByName(
fileStorage, // fs
null, // map
"nEigens",
0); // default_value
nTrainFaces = cvReadIntByName(
fileStorage,
null, // map
"nTrainFaces",
0); // default_value
Pointer pointer = cvReadByName(
fileStorage, // fs
null, // map
"trainPersonNumMat"); // name
pTrainPersonNumMat = new CvMat(pointer);
pointer = cvReadByName(
fileStorage, // fs
null, // map
"eigenValMat"); // name
eigenValMat = new CvMat(pointer);
pointer = cvReadByName(
fileStorage, // fs
null, // map
"projectedTrainFaceMat"); // name
projectedTrainFaceMat = new CvMat(pointer);
pointer = cvReadByName(
fileStorage,
null, // map
"avgTrainImg");
pAvgTrainImg = new IplImage(pointer);
eigenVectArr = new IplImage[nTrainFaces];
for (i = 0; i <= nEigens; i++) {
String varname = "eigenVect_" + i;
pointer = cvReadByName(
fileStorage,
null, // map
varname);
eigenVectArr[i] = new IplImage(pointer);
}
// release the file-storage interface
cvReleaseFileStorage(fileStorage);
LOGGER.info("Training data loaded (" + nTrainFaces + " training images of " + nPersons + " people)");
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("People: ");
if (nPersons > 0) {
stringBuilder.append("<").append(personNames.get(0)).append(">");
}
for (i = 1; i < nPersons; i++) {
stringBuilder.append(", <").append(personNames.get(i)).append(">");
}
LOGGER.info(stringBuilder.toString());
return pTrainPersonNumMat;
}
private void storeEigenfaceImages() {
// Store the average image to a file
LOGGER.info("Saving the image of the average face as 'data/out_averageImage.bmp'");
cvSaveImage("img\\out_averageImage.jpg", pAvgTrainImg);
// Create a large image made of many eigenface images.
// Must also convert each eigenface image to a normal 8-bit UCHAR image instead of a 32-bit float image.
LOGGER.info("Saving the " + nEigens + " eigenvector images as 'data/out_eigenfaces.bmp'");
if (nEigens > 0) {
// Put all the eigenfaces next to each other.
int COLUMNS = 8; // Put upto 8 images on a row.
int nCols = Math.min(nEigens, COLUMNS);
int nRows = 1 + (nEigens / COLUMNS); // Put the rest on new rows.
int w = eigenVectArr[0].width();
int h = eigenVectArr[0].height();
CvSize size = cvSize(nCols * w, nRows * h);
final IplImage bigImg = cvCreateImage(
size,
IPL_DEPTH_8U, // depth, 8-bit Greyscale UCHAR image
1); // channels
for (int i = 0; i < nEigens; i++) {
// Get the eigenface image.
IplImage byteImg = convertFloatImageToUcharImage(eigenVectArr[i]);
// Paste it into the correct position.
int x = w * (i % COLUMNS);
int y = h * (i / COLUMNS);
CvRect ROI = cvRect(x, y, w, h);
cvSetImageROI(
bigImg, // image
ROI); // rect
cvCopy(
byteImg, // src
bigImg, // dst
null); // mask
cvResetImageROI(bigImg);
cvReleaseImage(byteImg);
}
cvSaveImage(
"img\\out_eigenfaces.jpg", // filename
bigImg); // image
cvReleaseImage(bigImg);
}
}
private IplImage convertFloatImageToUcharImage(IplImage srcImg) {
IplImage dstImg;
if ((srcImg != null) && (srcImg.width() > 0 && srcImg.height() > 0)) {
// Spread the 32bit floating point pixels to fit within 8bit pixel range.
CvPoint minloc = new CvPoint();
CvPoint maxloc = new CvPoint();
double[] minVal = new double[1];
double[] maxVal = new double[1];
cvMinMaxLoc(srcImg, minVal, maxVal, minloc, maxloc, null);
// Deal with NaN and extreme values, since the DFT seems to give some NaN results.
if (minVal[0] < -1e30) {
minVal[0] = -1e30;
}
if (maxVal[0] > 1e30) {
maxVal[0] = 1e30;
}
if (maxVal[0] - minVal[0] == 0.0f) {
maxVal[0] = minVal[0] + 0.001; // remove potential divide by zero errors.
} // Convert the format
dstImg = cvCreateImage(cvSize(srcImg.width(), srcImg.height()), 8, 1);
cvConvertScale(srcImg, dstImg, 255.0 / (maxVal[0] - minVal[0]), -minVal[0] * 255.0 / (maxVal[0] - minVal[0]));
return dstImg;
}
return null;
}
private int findNearestNeighbor(float projectedTestFace[], FloatPointer pConfidencePointer) {
double leastDistSq = Double.MAX_VALUE;
int i = 0;
int iTrain = 0;
int iNearest = 0;
LOGGER.info("................");
LOGGER.info("find nearest neighbor from " + nTrainFaces + " training faces");
for (iTrain = 0; iTrain < nTrainFaces; iTrain++) {
//LOGGER.info("considering training face " + (iTrain + 1));
double distSq = 0;
for (i = 0; i < nEigens; i++) {
//LOGGER.debug(" projected test face distance from eigenface " + (i + 1) + " is " + projectedTestFace[i]);
float projectedTrainFaceDistance = (float) projectedTrainFaceMat.get(iTrain, i);
float d_i = projectedTestFace[i] - projectedTrainFaceDistance;
distSq += d_i * d_i; // / eigenValMat.data_fl().get(i); // Mahalanobis distance (might give better results than Eucalidean distance)
// if (iTrain < 5) {
// LOGGER.info(" ** projected training face " + (iTrain + 1) + " distance from eigenface " + (i + 1) + " is " + projectedTrainFaceDistance);
// LOGGER.info(" distance between them " + d_i);
// LOGGER.info(" distance squared " + distSq);
// }
}
if (distSq < leastDistSq) {
leastDistSq = distSq;
iNearest = iTrain;
LOGGER.info(" training face " + (iTrain + 1) + " is the new best match, least squared distance: " + leastDistSq);
}
}
// Return the confidence level based on the Euclidean distance,
// so that similar images should give a confidence between 0.5 to 1.0,
// and very different images should give a confidence between 0.0 to 0.5.
float pConfidence = (float) (1.0f - Math.sqrt(leastDistSq / (float) (nTrainFaces * nEigens)) / 255.0f);
pConfidencePointer.put(pConfidence);
LOGGER.info("training face " + (iNearest + 1) + " is the final best match, confidence " + pConfidence);
return iNearest;
}
private String floatArrayToString(final float[] floatArray) {
final StringBuilder stringBuilder = new StringBuilder();
boolean isFirst = true;
stringBuilder.append('[');
for (int i = 0; i < floatArray.length; i++) {
if (isFirst) {
isFirst = false;
}
else {
stringBuilder.append(", ");
}
stringBuilder.append(floatArray[i]);
}
stringBuilder.append(']');
return stringBuilder.toString();
}
private String floatPointerToString(final FloatPointer floatPointer) {
final StringBuilder stringBuilder = new StringBuilder();
boolean isFirst = true;
stringBuilder.append('[');
for (int i = 0; i < floatPointer.capacity(); i++) {
if (isFirst) {
isFirst = false;
} else {
stringBuilder.append(", ");
}
stringBuilder.append(floatPointer.get(i));
}
stringBuilder.append(']');
return stringBuilder.toString();
}
private String oneChannelCvMatToString(final CvMat cvMat) {
//Preconditions
if (cvMat.channels() != 1) {
throw new RuntimeException("illegal argument - CvMat must have one channel");
}
final int type = cvMat.type();
StringBuilder s = new StringBuilder("[ ");
for (int i = 0; i < cvMat.rows(); i++) {
for (int j = 0; j < cvMat.cols(); j++) {
if (type == CV_32FC1 || type == CV_32SC1) {
s.append(cvMat.get(i, j));
} else {
throw new RuntimeException("illegal argument - CvMat must have one channel and type of float or signed integer");
}
if (j < cvMat.cols() - 1) {
s.append(", ");
}
}
if (i < cvMat.rows() - 1) {
s.append("\n ");
}
}
s.append(" ]");
return s.toString();
}
}
高级设计师
by: 小蜜锋 发表于:2014-07-11 14:22:23 顶(0) | 踩(0) 回复
很牛逼的样子!
回复评论