package test; 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.Exception; import com.googlecode.javacv.OpenCVFrameGrabber; 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; 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; } @SuppressWarnings("unused") 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; } @SuppressWarnings("unused") 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(); } }
最近下载更多
tdcq123 LV14
3月22日
c15042361021 LV4
2022年11月8日
陆羽 LV5
2022年9月27日
yanxiaojie LV3
2021年9月29日
whfuai LV14
2021年8月19日
rruizy LV3
2021年6月30日
你是傻子 LV9
2021年5月24日
iRichard1314 LV6
2021年5月16日
liu3987741 LV8
2021年4月6日
秦峯123456 LV4
2021年3月24日