Skip to content

Commit

Permalink
Clean up source
Browse files Browse the repository at this point in the history
  • Loading branch information
Gabriel Huang committed Oct 14, 2014
1 parent 84d4cfc commit eb15e89
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 155 deletions.
65 changes: 13 additions & 52 deletions src/findEyeCorner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

#include "findEyeCorner.h"

cv::Mat *leftCornerKernel;
cv::Mat *rightCornerKernel;
cv::Mat leftCornerKernel;
cv::Mat rightCornerKernel;

// not constant because stupid opencv type signatures
float kEyeCornerKernel[4][6] = {
Expand All @@ -23,19 +23,15 @@ float kEyeCornerKernel[4][6] = {
};

void createCornerKernels() {
rightCornerKernel = new cv::Mat(4,6,CV_32F,kEyeCornerKernel);
leftCornerKernel = new cv::Mat(4,6,CV_32F);
rightCornerKernel = cv::Mat(4,6,CV_32F,kEyeCornerKernel);
leftCornerKernel = cv::Mat(4,6,CV_32F);
// flip horizontally
cv::flip(*rightCornerKernel, *leftCornerKernel, 1);
cv::flip(rightCornerKernel, leftCornerKernel, 1);
}

void releaseCornerKernels() {
delete leftCornerKernel;
delete rightCornerKernel;
}

// TODO implement these
cv::Mat eyeCornerMap(const cv::Mat &region, bool left, bool left2) {
cv::Mat eyeCornerMap(const cv::Mat &region, bool left, bool left2)
{
cv::Mat cornerMap;

cv::Size sizeRegion = region.size();
Expand All @@ -45,63 +41,28 @@ cv::Mat eyeCornerMap(const cv::Mat &region, bool left, bool left2) {
cv::Mat miRegion(region, rowRange, colRange);

cv::filter2D(miRegion, cornerMap, CV_32F,
(left && !left2) || (!left && !left2) ? *leftCornerKernel : *rightCornerKernel);
(left && !left2) || (!left && !left2) ? leftCornerKernel : rightCornerKernel);

return cornerMap;
}

cv::Point2f findEyeCorner(cv::Mat region, bool left, bool left2) {
cv::Point2f findEyeCorner(cv::Mat region, bool left, bool left2)
{
cv::Mat cornerMap = eyeCornerMap(region, left, left2);

cv::Point maxP;
cv::minMaxLoc(cornerMap,NULL,NULL,NULL,&maxP);

cv::Point2f maxP2;
maxP2 = findSubpixelEyeCorner(cornerMap, maxP);
// GFTT
// std::vector<cv::Point2f> corners;
// cv::goodFeaturesToTrack(region, corners, 500, 0.005, 20);
// for (int i = 0; i < corners.size(); ++i) {
// cv::circle(region, corners[i], 2, 200);
// }
// imshow("Corners",region);

return maxP2;
}
cv::Point2f findSubpixelEyeCorner(cv::Mat region, cv::Point maxP) {

cv::Size sizeRegion = region.size();

// Matrix dichotomy
// Not useful, matrix becomes too small

/*int offsetX = 0;
if(maxP.x - sizeRegion.width / 4 <= 0) {
offsetX = 0;
} else if(maxP.x + sizeRegion.width / 4 >= sizeRegion.width) {
offsetX = sizeRegion.width / 2 - 1;
} else {
offsetX = maxP.x - sizeRegion.width / 4;
}
int offsetY = 0;
if(maxP.y - sizeRegion.height / 4 <= 0) {
offsetY = 0;
} else if(maxP.y + sizeRegion.height / 4 >= sizeRegion.height) {
offsetY = sizeRegion.height / 2 - 1;
} else {
offsetY = maxP.y - sizeRegion.height / 4;
}
cv::Range colRange(offsetX, offsetX + sizeRegion.width / 2);
cv::Range rowRange(offsetY, offsetY + sizeRegion.height / 2);
cv::Point2f findSubpixelEyeCorner(cv::Mat region, cv::Point maxP)
{

cv::Mat miRegion(region, rowRange, colRange);
if(left){
imshow("aa",miRegion);
} else {
imshow("aaa",miRegion);
}*/
cv::Size sizeRegion = region.size();

cv::Mat cornerMap(sizeRegion.height * 10, sizeRegion.width * 10, CV_32F);

Expand Down
199 changes: 96 additions & 103 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,93 +1,114 @@
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <opencv2/video/video.hpp>
#include <iostream>
#include <queue>
#include <stdio.h>
#include <math.h>
#include <cmath>

#include "constants.h"
#include "findEyeCenter.h"
#include "findEyeCorner.h"

using namespace std;

void findEyes(cv::Mat frame_gray, cv::Rect face);

struct Detect
{
cv::KalmanFilter kf;
cv::CascadeClassifier* classifier;
cv::Rect current_face;
cv::Rect filtered_face;
unsigned max_w;
unsigned max_h;
bool detected;

Detect(cv::CascadeClassifier* classifier)
: kf(2, 2, 0)
, max_w(150)
, max_h(150)
, classifier(classifier)
{
}

/** Constants **/


/** Function Headers */
void detectAndDisplay(cv::Mat frame);

/** Global variables */
//-- Note, either copy these two files from opencv/data/haarscascades to your current folder, or change these locations
cv::String face_cascade_name = "../../res/haarcascade_frontalface_alt.xml";
cv::CascadeClassifier face_cascade;
std::string main_window_name = "Capture - Face detection";
std::string face_window_name = "Capture - Face";
cv::RNG rng(12345);
cv::Mat debugImage;
cv::Mat skinCrCbHist = cv::Mat::zeros(cv::Size(256, 256), CV_8UC1);

/**
* @function main
*/
int main(int argc, const char** argv) {
cv::Mat frame;

// Load the cascades
if (!face_cascade.load(face_cascade_name)){ printf("--(!)Error loading face cascade, please change face_cascade_name in source code.\n"); return -1; };

cv::namedWindow(main_window_name, CV_WINDOW_NORMAL);
cv::moveWindow(main_window_name, 400, 100);
cv::namedWindow(face_window_name, CV_WINDOW_NORMAL);
cv::moveWindow(face_window_name, 10, 100);
cv::namedWindow("Right Eye", CV_WINDOW_NORMAL);
cv::moveWindow("Right Eye", 10, 600);
cv::namedWindow("Left Eye", CV_WINDOW_NORMAL);
cv::moveWindow("Left Eye", 10, 800);
cv::namedWindow("aa", CV_WINDOW_NORMAL);
cv::moveWindow("aa", 10, 800);
cv::namedWindow("aaa", CV_WINDOW_NORMAL);
cv::moveWindow("aaa", 10, 800);

createCornerKernels();
ellipse(skinCrCbHist, cv::Point(113, 155.6), cv::Size(23.4, 15.2),
43.0, 0.0, 360.0, cv::Scalar(255, 255, 255), -1);

// Read the video stream
cv::VideoCapture capture(0);
while (true) {
capture >> frame;

// mirror it
cv::flip(frame, frame, 1);
frame.copyTo(debugImage);

// Apply the classifier to the frame
if (!frame.empty()) {
detectAndDisplay(frame);
bool operator()(const cv::Mat& frame, cv::Mat& debugImage = cv::Mat())
{
std::vector<cv::Mat> rgbChannels(3);
cv::split(frame, rgbChannels);
cv::Mat frame_gray = rgbChannels[2];
std::vector<cv::Rect> faces;
classifier->detectMultiScale(frame_gray, faces, 1.1, 2,
0 | CV_HAAR_SCALE_IMAGE | CV_HAAR_FIND_BIGGEST_OBJECT, cv::Size(max_w, max_h));

if (detected = !faces.empty())
{
current_face = faces.front();
filtered_face = current_face;
cv::rectangle(debugImage, current_face, 1234);
findEyes(frame_gray, current_face);
}
else {
printf(" --(!) No captured frame -- Break!");
break;

return detected;
}
};


int main(int argc, const char** argv)
{
std::string face_cascade_name = "../../res/haarcascade_frontalface_alt.xml";
std::string main_window_name = "Capture - Face detection";
std::string face_window_name = "Capture - Face";
cv::RNG rng(12345);
cv::Mat skinCrCbHist = cv::Mat::zeros(cv::Size(256, 256), CV_8UC1);

try
{
cv::CascadeClassifier face_cascade;
if (!face_cascade.load(face_cascade_name))
{
throw std::runtime_error("Cannot find face cascade" + face_cascade_name);
};

createCornerKernels();
cv::ellipse(skinCrCbHist, cv::Point(113, 155.6), cv::Size(23.4, 15.2),
43.0, 0.0, 360.0, cv::Scalar(255, 255, 255), -1);

// Read the video stream
cv::VideoCapture capture(0);
if (!capture.isOpened())
{
throw std::runtime_error("Open VideoCapture");
}

imshow(main_window_name, debugImage);
cv::Mat frame, debugImage;
char key = 0;
Detect detect(&face_cascade);
while ((key = cv::waitKey(10)) != 27) // ESC
{
capture >> frame;
if (frame.empty())
{
throw std::runtime_error("Empty frame");
}
cv::flip(frame, frame, 1);
debugImage = frame.clone();
detect(frame, debugImage);

int c = cv::waitKey(10);
if ((char)c == 'c') { break; }
if ((char)c == 'f') {
imwrite("frame.png", frame);
cv::imshow("Debug", debugImage);
}
}

releaseCornerKernels();
std::cout << "done" << std::endl;
std::cin.get();
catch (const std::runtime_error& e)
{
std::cout << "Exception : " << e.what() << std::endl;
std::cin.get();
}

return 0;
}

void findEyes(cv::Mat frame_gray, cv::Rect face) {
void findEyes(cv::Mat frame_gray, cv::Rect face)
{
cv::Mat faceROI = frame_gray(face);
cv::Mat debugFace = faceROI;

Expand Down Expand Up @@ -140,7 +161,8 @@ void findEyes(cv::Mat frame_gray, cv::Rect face) {
circle(debugFace, leftPupil, 3, 1234);

//-- Find Eye Corners
if (kEnableEyeCorner) {
if (kEnableEyeCorner)
{
cv::Point2f leftRightCorner = findEyeCorner(faceROI(leftRightCornerRegion), true, false);
leftRightCorner.x += leftRightCornerRegion.x;
leftRightCorner.y += leftRightCornerRegion.y;
Expand All @@ -159,14 +181,12 @@ void findEyes(cv::Mat frame_gray, cv::Rect face) {
circle(faceROI, rightRightCorner, 3, 200);
}

imshow(face_window_name, faceROI);
// cv::Rect roi( cv::Point( 0, 0 ), faceROI.size());
// cv::Mat destinationROI = debugImage( roi );
// faceROI.copyTo( destinationROI );
cv::imshow("Face", faceROI);
}


cv::Mat findSkin(cv::Mat &frame) {
cv::Mat findSkin(cv::Mat& frame, const cv::Mat& skinCrCbHist)
{
cv::Mat input;
cv::Mat output = cv::Mat(frame.rows, frame.cols, CV_8U);

Expand All @@ -187,30 +207,3 @@ cv::Mat findSkin(cv::Mat &frame) {
return output;
}

/**
* @function detectAndDisplay
*/
void detectAndDisplay(cv::Mat frame) {
std::vector<cv::Rect> faces;
//cv::Mat frame_gray;

std::vector<cv::Mat> rgbChannels(3);
cv::split(frame, rgbChannels);
cv::Mat frame_gray = rgbChannels[2];

//cvtColor( frame, frame_gray, CV_BGR2GRAY );
//equalizeHist( frame_gray, frame_gray );
//cv::pow(frame_gray, CV_64F, frame_gray);
//-- Detect faces
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE | CV_HAAR_FIND_BIGGEST_OBJECT, cv::Size(150, 150));
// findSkin(debugImage);

for (int i = 0; i < faces.size(); i++)
{
rectangle(debugImage, faces[i], 1234);
}
//-- Show what you got
if (faces.size() > 0) {
findEyes(frame_gray, faces[0]);
}
}

0 comments on commit eb15e89

Please sign in to comment.