package com.hygenics.facialrec; import ij3d.ImgLibVolume; import imagetools.FileTypeException; import imagetools.GetEdges; import java.awt.Color; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import javax.imageio.ImageIO; 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.highgui.Highgui; import org.opencv.objdetect.CascadeClassifier; /** * Generates the points on someones face. Finds the most oval object by trying * to fit an oval to someones face. At different angles until the Best Fitting * Oval is Found. The proportion is based on the average width. Discontinuitues * are dealt with by turning the oval into a minimum bounding oval. * * Cascades will need to be set. The default for them is the OpenCV_2_8\openc\source\dat\haarcascades folder * Haar seems to perform better than lbp. * * This is the company's but is also open source. I'm not taking pennies on the dollar for edge-detection, splines,custom haar cascade generation; etc. when those are upper level concepts * and capable of generating good products. This program uses OpenCV which is pre-trained and utilizes math that can be redone in just about any fashion in case * I want to develop something on my own. * * @author aevans * */ public class GetFacialFeatures{ private String mouthcascade="C:\\User/aevan/Document/OpenCV_2_8_/openc/source/dat/haarcascade/haarcascade_mcs_mouth.xml"; private String smilecascade="C:\\User/aevan/Document/OpenCV_2_8_/openc/source/dat/haarcascade/haarcascade_smile.xml"; private String nosecascade="C:\\User/aevan/Document/OpenCV_2_8_/openc/source/dat/haarcascade/haarcascade_mcs_nose.xml"; private String leftearcascade="C:\\User/aevan/Document/OpenCV_2_8_/openc/source/dat/haarcascade/haarcascade_mcs_leftear.xml"; private String rightearcascade="C:\\User/aevan/Document/OpenCV_2_8_/openc/source/dat/haarcascade/haarcascade_mcs_rightear.xml"; private String eyeglasscascade="C:\\User/aevan/Document/OpenCV_2_8_/openc/source/dat/haarcascade/haarcascade_eye_tree_eyeglasses.xml"; private String eyescascade="C:\\User/aevan/Document/OpenCV_2_8_/openc/source/dat/haarcascade/haarcascade_eye.xml"; private BufferedImage bi; //this is by pixel private int widthoffset=1; private String temporaryfpath="C:\\Users\\aevans\\Pictures\\FaceImages\\testimage.jpg"; private ArrayList<ObjectRect> objects=new ArrayList<ObjectRect>(); private boolean mouth=false; private boolean ears=false; private boolean eyes=false; private boolean nose=false; private boolean glasses=false; private boolean smile=false; private boolean markoriginal=false; private boolean addOtherFeatures=false; public GetFacialFeatures() { } public boolean isMarkoriginal() { return markoriginal; } public void setMarkoriginal(boolean markoriginal) { this.markoriginal = markoriginal; } public boolean isSmile() { return smile; } public void setSmile(boolean smile) { this.smile = smile; } public boolean isMouth() { return mouth; } public void setMouth(boolean mouth) { this.mouth = mouth; } public boolean isEars() { return ears; } public void setEars(boolean ears) { this.ears = ears; } public boolean isEyes() { return eyes; } public void setEyes(boolean eyes) { this.eyes = eyes; } public boolean isNose() { return nose; } public void setNose(boolean nose) { this.nose = nose; } public boolean isGlasses() { return glasses; } public void setGlasses(boolean glasses) { this.glasses = glasses; } public boolean isAddOtherFeatures() { return addOtherFeatures; } public void setAddOtherFeatures(boolean addOtherFeatures) { this.addOtherFeatures = addOtherFeatures; } public int getWidthoffset() { return widthoffset; } public void setWidthoffset(int widthoffset) { this.widthoffset = widthoffset; } public String getMouthcascade() { return mouthcascade; } public void setMouthcascade(String mouthcascade) { this.mouthcascade = mouthcascade; } public String getSmilecascade() { return smilecascade; } public void setSmilecascade(String smilecascade) { this.smilecascade = smilecascade; } public String getNosecascade() { return nosecascade; } public void setNosecascade(String nosecascade) { this.nosecascade = nosecascade; } public String getLeftearcascade() { return leftearcascade; } public void setLeftearcascade(String leftearcascade) { this.leftearcascade = leftearcascade; } public String getRightearcascade() { return rightearcascade; } public void setRightearcascade(String rightearcascade) { this.rightearcascade = rightearcascade; } public String getEyeglasscascade() { return eyeglasscascade; } public void setEyeglasscascade(String eyeglasscascade) { this.eyeglasscascade = eyeglasscascade; } public String getEyescascade() { return eyescascade; } public void setEyescascade(String eyescascade) { this.eyescascade = eyescascade; } public BufferedImage getBi() { return bi; } public void setBi(BufferedImage bi) { this.bi = bi; } /** * Finds features for mapping splines */ private void findFeatures() { //TODO get the eyes, eyeglasses, nose, mouth, and ears from the image and get them as a marked //box, the points will be obtained in the form of a starting x,y and width and returned //as an object //cascade array ArrayList<String> cascades=new ArrayList<String>(); if(mouth){ cascades.add(mouthcascade); } if(smile){ cascades.add(smilecascade); } if(nose){ cascades.add(nosecascade); } if(ears){ cascades.add(leftearcascade); cascades.add(rightearcascade); } if(glasses){ cascades.add(eyeglasscascade); } if(eyes){ cascades.add(eyescascade); } //load library System.loadLibrary(Core.NATIVE_LIBRARY_NAME); //save image if it has not been saved try { ImageIO.write(bi,".jpg", new File(temporaryfpath)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } //perform detection for each part of the cascade for(String cascade : cascades) { if(cascade.toLowerCase().contains(".xml")==true) { CascadeClassifier faceDetector = new CascadeClassifier(cascade); if( faceDetector.empty()==false) { //read image if cascade found Mat image = Highgui.imread(temporaryfpath); //face detect if(image.empty()==false) { System.out.println("Finding Faces"); MatOfRect faceDetections = new MatOfRect(); faceDetector.detectMultiScale(image, faceDetections); System.out.println("Found "+faceDetections.toArray().length+" objects."); //get each rectangle and set as an object with appropriate height, width, x, and y, positions for(Rect rect : faceDetections.toArray()) { //set the appropriate boolean if(cascade.compareTo(leftearcascade)==0|cascade.compareTo(rightearcascade)==0) { //ears ears=true; } else if(cascade.compareTo(mouthcascade)==0) { //mouth (not smile) mouth=true; } else if(cascade.compareTo(smilecascade)==0){ //smile only smile=true; } else if(cascade.compareTo(nosecascade)==0) { //nose nose=true; } else if(cascade.compareTo(eyescascade)==0) { //eyes eyes=true; } else if(cascade.compareTo(eyeglasscascade)==0) { //eyeglasses glasses=true; } //create the appropriate found object ObjectRect or=new ObjectRect(); or.setX(rect.x); or.setY(rect.y); or.setHeight(rect.height); or.setWidth(rect.width); //set the object in the array objects.add(or); if(markoriginal){ //TODO Mark a green rectange ON THE ORIGINAL IMAGE //if a request is made to mark the original, mark the detected feature (this would be useful for testing) //the color can be changed but bright green works well (opencv does something similar, its nice and ugly) //mark the horizontal bars for(int x=rect.x;x<(rect.x+rect.width);x++){ bi.setRGB(x, rect.y, new Color(0,255,0).getRGB()); bi.setRGB(x, (rect.y+rect.height), new Color(0,255,0).getRGB()); } //mark the vertical bars for(int y=rect.y; y<(rect.y+rect.height);y++){ bi.setRGB(rect.x, y, new Color(0,255,0).getRGB()); bi.setRGB((rect.x+rect.width), y, new Color(0,255,0).getRGB()); } } } } else{ try{ throw new NullPointerException("No Image Found"); }catch(NullPointerException e) { e.printStackTrace(); } } } else { try{ throw new FileTypeException("Cascade Must be of TYpe XML"); }catch(FileTypeException e){ e.printStackTrace(); } } } } } /** * Find prominent features from an image which are usedin the formation of points */ private void findOtherFeatures(){ //TODO find large chunks of noise from the image //use a laplace filter to grab drastic changes in the image (the map of noise points in denoise) //find the noisy points //find clusters of points that may represent prominent features } /** * Get an edge detected image * * @return */ private BufferedImage getEdges(){ //TODO Get the Edge Detected Image //get edges and add points to them GetEdges edges=new GetEdges(); edges.setImage(bi); //get cleaner and less edges edges.edge_detect(false); //get the image which is prepped for return edges.getImage(); } /** * Run facial point generator */ public void run() { //get the features findFeatures(); if(addOtherFeatures){ //at this point, this is mainly for silhuoette detection since different poses will seriously effect the outcome findOtherFeatures(); } } }