diff --git a/src/findEyeCorner.cpp b/src/findEyeCorner.cpp index b8d71aa..c69aa3e 100755 --- a/src/findEyeCorner.cpp +++ b/src/findEyeCorner.cpp @@ -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] = { @@ -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 ®ion, bool left, bool left2) { +cv::Mat eyeCornerMap(const cv::Mat ®ion, bool left, bool left2) +{ cv::Mat cornerMap; cv::Size sizeRegion = region.size(); @@ -45,12 +41,13 @@ cv::Mat eyeCornerMap(const cv::Mat ®ion, 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; @@ -58,50 +55,14 @@ cv::Point2f findEyeCorner(cv::Mat region, bool left, bool left2) { cv::Point2f maxP2; maxP2 = findSubpixelEyeCorner(cornerMap, maxP); - // GFTT -// std::vector 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); diff --git a/src/main.cpp b/src/main.cpp index 00980f5..b3eba9e 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,93 +1,114 @@ #include #include #include - +#include #include #include -#include -#include +#include #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 rgbChannels(3); + cv::split(frame, rgbChannels); + cv::Mat frame_gray = rgbChannels[2]; + std::vector 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; @@ -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; @@ -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); @@ -187,30 +207,3 @@ cv::Mat findSkin(cv::Mat &frame) { return output; } -/** - * @function detectAndDisplay - */ -void detectAndDisplay(cv::Mat frame) { - std::vector faces; - //cv::Mat frame_gray; - - std::vector 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]); - } -}