Skip to content
Snippets Groups Projects
FacialRec.cpp 7.38 KiB
Newer Older
//This is our project
johni's avatar
johni committed

#include <iostream>
#include <string>
Noah Eigenfeld's avatar
Noah Eigenfeld committed
#include <fstream>
#include <sstream>

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/core/core.hpp"
johni's avatar
johni committed
#include "opencv2/contrib/contrib.hpp"
johni's avatar
johni committed
using namespace std;
Mat picture, picture_grayscale, face, face_grayscale;
char key;
int picture_height;
int picture_width;
int face_x, face_y, face_width, face_height;
Rect face_dims;
vector<Mat> images;
vector<int> labels;
Noah Eigenfeld's avatar
Noah Eigenfeld committed
vector<string> users;
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;


/*
*	Currently loads any images from the directory "myfaces"
*	Subdirectories and images assumed to be labeled as an int, starting from 0, without breaks
*/
void read_images() {
Noah Eigenfeld's avatar
Noah Eigenfeld committed
	//empty the existing images and labels
	while (!images.empty()) {
		images.pop_back();
	}
	while (!labels.empty()) {
		labels.pop_back();
	}

	Mat load_image, load_image_grayscale;
	string filename = "";
	string directory = "./myfaces/";
	string subdirectory = "";
	int j = 0;
	while (true) {
		subdirectory = to_string(j) + "/";
		int i = 0;
		while (true) {
			filename = to_string(i);
			string path = directory + subdirectory + filename + ".png";
			load_image = imread(path, 1);

			if (!load_image.data) { //No image data found - moving to next subdirectory
Noah Eigenfeld's avatar
Noah Eigenfeld committed
				cout << " No image data" << endl;

			//Convert loaded images to grayscale
			load_image_grayscale = load_image.clone();
			cvtColor(load_image, load_image_grayscale, CV_BGR2GRAY);

			//Add image to vector, along with the label for this subdirectory
			images.push_back(load_image_grayscale);
			labels.push_back(j);
			i++;
		}

		if (i == 0) {	//No images in subdirectory/subdirectory does not exist
			num_subdirectories = j;
			break;
		} else {		//Move to the next subdirectory
			j++;
		}
	}

	//Resize all images to first image size
	for (int i=0; i < images.size(); i++) {
		resize(images[i],images[i],images[0].size(),0,0, INTER_NEAREST );
	}
Noah Eigenfeld's avatar
Noah Eigenfeld committed
void read_users() {
	string pathname = "./users.txt";
	int user_label = 0;
	ifstream file(pathname.c_str(), ifstream::in);
    if (!file) {
        string error_message = "File pathname not valid.";
        CV_Error(CV_StsBadArg, error_message);
    }
    string line, name, classlabel;
    while (getline(file, line)) {
        stringstream liness(line);
        getline(liness, name);
        users.push_back(name);
        cout << "user " << user_label << ": " << name << endl;
        user_label++;
    }
}

int main() {
	//Starting the video
	VideoCapture videoCapture(0);

	if (!videoCapture.isOpened()) {
		cout << "Unable to open video file." << endl;
		return 1;
	}

	if (!face_cascade.load("haarcascade_frontalface_alt.xml")) {
		cout << "Error loading face cascade classifier." << endl;
		return -1;
	}
	if (!eyes_cascade.load("haarcascade_eye_tree_eyeglasses.xml")) {
		cout << "Error loading eye cascade classifier." << endl;
		return -1;
	}
johni's avatar
johni committed

	while(true) {
		Mat frame;
		videoCapture.retrieve(frame);
		bool success = videoCapture.read(frame);
		if (!success) {
			cout << "Could not read from video file" << endl;
			return 1;
		}
johni's avatar
johni committed

		//Get webcam image dimensions
		picture_width = frame.cols;
		picture_height = frame.rows;

		face_x = picture_width/3;
		face_y = picture_height/5;
		face_width = picture_width/3;
		face_height = 3 * face_y;

		Rect face_dims(face_x, face_y, face_width, face_height);
		face = frame(face_dims);

		//show some instructional text
		Mat frame_with_text = frame.clone();
		putText(frame_with_text, "Press Spacebar to take a picture", Point2f(110,100), FONT_HERSHEY_SIMPLEX, 2.0,  Scalar(255,0,0,0), 3);
		putText(frame_with_text, "Press ESC to close the application", Point2f(90,700), FONT_HERSHEY_SIMPLEX, 2.0,  Scalar(0,0,255,255), 3);

Noah Eigenfeld's avatar
Noah Eigenfeld committed
		//Draw a rectangle where the picture will be taken
		Point a(face_x, face_y);
		Point b(face_x, face_y + face_height);
		Point c(face_x + face_width, face_y + face_height);
		Point d(face_x + face_width, face_y);

		line( frame_with_text, a, b, Scalar( 0, 0, 0 ),2, 8);
        line( frame_with_text, b, c, Scalar( 0, 0, 0 ),2, 8);
        line( frame_with_text, c, d, Scalar( 0, 0, 0 ),2, 8);
        line( frame_with_text, d, a, Scalar( 0, 0, 0 ),2, 8);
		imshow("Webcam", frame_with_text);
johni's avatar
johni committed

		key = waitKey(30);

		if (key == 27) { //escape key pressed: stop program
			cout << "ESC pressed. Program closing..." << endl;
			break;
		}
		else if (key == ' ') { //spacebar pressed: take a picture

			picture = frame;
			key = -1;

			//Convert to grayscale
			picture_grayscale = picture.clone();
			cvtColor(picture, picture_grayscale, CV_BGR2GRAY);
			face_grayscale = face.clone();
			cvtColor(face, face_grayscale, CV_BGR2GRAY);
			//Read saved images in myfaces
			read_images();

Noah Eigenfeld's avatar
Noah Eigenfeld committed
			//Read users
			read_users();

			//Check that images were read correctly
			cout << "Images read: " << images.size() << endl;
Noah Eigenfeld's avatar
Noah Eigenfeld committed
			cout << "Subdirectories: " << num_subdirectories << endl;

			//Resize to fit loaded images
			resize(face_grayscale, face_grayscale,images[0].size(),0,0, INTER_NEAREST );

			//Generate FaceRecognizer - using FisherFace 
			Ptr<FaceRecognizer> fisher_model = createFisherFaceRecognizer();
Noah Eigenfeld's avatar
Noah Eigenfeld committed
			Ptr<FaceRecognizer> eigen_model = createEigenFaceRecognizer(); //using this FaceRecognizer to determine identity
			Ptr<FaceRecognizer> lbph_model = createLBPHFaceRecognizer();
			//Feed FaceRecognizer with images and labels
			fisher_model->train(images, labels);
			eigen_model->train(images, labels);
			lbph_model->train(images, labels);
			cout << "Face Recognizer created" << endl;

			//Output predicted label - this will be the matched subject of the picture
			int fisher_predictedLabel = fisher_model->predict(face_grayscale);
			int eigen_predictedLabel = eigen_model->predict(face_grayscale);
			int lbph_predictedLabel = lbph_model->predict(face_grayscale);
			cout << "Fisher predicted label: " << fisher_predictedLabel << endl;
Noah Eigenfeld's avatar
Noah Eigenfeld committed
			cout << "Eigen predicted label: " << eigen_predictedLabel << " - " << users[eigen_predictedLabel] << endl;
			cout << "LBPH predicted label: " << lbph_predictedLabel << endl;
				//Add instructions to the screen
				Mat picture_with_text = picture.clone();
				putText(picture_with_text, "Press 's' to save", Point2f(375,100), FONT_HERSHEY_SIMPLEX, 2.0,  Scalar(255,0,0,0), 3);
				putText(picture_with_text, "Predicted User: " + users[eigen_predictedLabel], Point2f(275,600), FONT_HERSHEY_SIMPLEX, 2.0,  Scalar(255,0,0,0), 3);
				putText(picture_with_text, "Press ESC/Spacebar to return", Point2f(160,670), FONT_HERSHEY_SIMPLEX, 2.0,  Scalar(0,0,255), 3);

				imshow("Webcam", picture_with_text);

				key = waitKey(30);

				if (key == 27 || key == 32) {	//spacebar or ESC pressed
					cout << "ESC or SPACE pressed. Returning to video..." << endl;
					break;
				} else if (key == 115) {		//"s" pressed - saving image
		          	cout << "Please select a name for the image." << endl;
		          	getline(cin, name);
		          	directory.append(name);
		          	directory.append(".png");
		          	Point org;
		          	org.x = 15;
		          	org.y = 100;
		          	putText(picture_with_text, name, org, FONT_HERSHEY_SIMPLEX, 2, Scalar(0, 0, 255), 3);
					bool maybe = imwrite(directory, face);
					cout << "s was pressed. saving image, success: " << maybe << endl;
				}
			}
		}

	}

	return 0;
johni's avatar
johni committed
}