From 7d0760cc9f466419b7505f4c0659a8f5cba8882a Mon Sep 17 00:00:00 2001 From: Epicalert Date: Wed, 6 Jan 2021 08:10:55 +0800 Subject: [PATCH] clean up main.cpp --- CMakeLists.txt | 2 +- src/cv.cpp | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/cv.hpp | 10 ++++++ src/main.cpp | 76 ++++----------------------------------------- 4 files changed, 100 insertions(+), 71 deletions(-) create mode 100644 src/cv.cpp create mode 100644 src/cv.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0fd0d10..794b2f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,6 @@ find_package( glm REQUIRED ) find_package( FreeGLUT REQUIRED ) include_directories( ${OpenCV_INCLUDE_DIRS} ) include_directories( ${PROJECT_SOURCE_DIR}/src ) -add_executable( fc2d src/main.cpp src/graphics.cpp src/modelpart.cpp ) +add_executable( fc2d src/main.cpp src/graphics.cpp src/modelpart.cpp src/cv.cpp ) target_link_libraries( fc2d ${OpenCV_LIBS} -lOpenGL -lglut -lGLEW ) set( CMAKE_BUILD_TYPE Debug ) diff --git a/src/cv.cpp b/src/cv.cpp new file mode 100644 index 0000000..c4dfe05 --- /dev/null +++ b/src/cv.cpp @@ -0,0 +1,83 @@ +#include +#include + +#include + +cv::Ptr facemark; +cv::CascadeClassifier faceDetector; +cv::VideoCapture vid; +cv::Mat frame, gray, small; + +void initCV() { + //TODO: switch to DNN face detection + faceDetector = cv::CascadeClassifier ("haarcascade_frontalface_alt2.xml"); + + facemark = cv::face::FacemarkLBF::create(); + facemark->loadModel ("lbfmodel.yaml"); + + vid = cv::VideoCapture (0); +} + +//process image and send controls to graphics +void cvFrame() { + vid.read(frame); + + cv::cvtColor (frame, gray, cv::COLOR_BGR2GRAY); + //downsample image for face detection, works too slow on full res + cv::pyrDown (gray, small); + cv::pyrDown (small, small); + + std::vector faces; + faceDetector.detectMultiScale(small, faces); + + //get biggest face + int biggestFace = 0; + int biggestArea = 0; + for (int i = 0; i < faces.size(); i++) { + //convert face region to full res, because we perform facemark on full res + faces[i] = cv::Rect (faces[i].x * 4, faces[i].y * 4, faces[i].width * 4, faces[i].height * 4); + + int iArea = faces[i].area(); + if (iArea > biggestArea) { + biggestFace = i; + biggestArea = iArea; + } + + cv::rectangle (frame, faces[i], cv::Scalar (255, 255, 0)); + } + + std::vector> landmarks; + + if (facemark->fit (frame, faces, landmarks)) { + //for (int i = 0; i < landmarks[biggestFace].size(); i++) { + // cv::circle (frame, landmarks[biggestFace][i], 2, cv::Scalar (255, 255, 255)); + //} + cv::circle(frame, cv::Point2f( + (landmarks[biggestFace][2].x + landmarks[biggestFace][14].x) / 2, + (landmarks[biggestFace][2].y + landmarks[biggestFace][14].y) / 2 + ), 6, cv::Scalar(0, 0, 255)); + cv::circle (frame, landmarks[biggestFace][30], 6, cv::Scalar (0, 255, 255)); + cv::circle (frame, landmarks[biggestFace][66], 3, cv::Scalar (0, 255, 0)); + cv::circle (frame, landmarks[biggestFace][62], 3, cv::Scalar (0, 255, 0)); + + //send control information to graphics + float faceSize = landmarks[biggestFace][14].x - landmarks[biggestFace][2].x; + updateModel(glm::vec2( + (landmarks[biggestFace][2].x + landmarks[biggestFace][14].x) / 2 + * 2 / (float)frame.cols - 1, + (landmarks[biggestFace][2].y + landmarks[biggestFace][14].y) / 2 + * 2 / (float)frame.rows - 1 + ), + glm::vec2( + landmarks[biggestFace][30].x * 2 / (float)frame.cols - 1, + landmarks[biggestFace][30].y * 2 / (float)frame.rows - 1 + ), + faceSize * 6 / (float)frame.cols, + (landmarks[biggestFace][66].y - landmarks[biggestFace][62].y) / faceSize > 0.04f); + } +} + +void cvShowFrame() { + cv::imshow("Video Input", frame); + cv::waitKey(32); +} diff --git a/src/cv.hpp b/src/cv.hpp new file mode 100644 index 0000000..adf1146 --- /dev/null +++ b/src/cv.hpp @@ -0,0 +1,10 @@ +#ifndef CV_HPP +#define CV_HPP + +void initCV(); + +void cvFrame(); + +void cvShowFrame(); + +#endif diff --git a/src/main.cpp b/src/main.cpp index 99691ca..8cf0cf8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,81 +1,17 @@ -#include -#include - #include +#include #include int main () { initGraphics(); + initCV(); - //TODO: switch to DNN face detection - cv::CascadeClassifier faceDetector ("haarcascade_frontalface_alt2.xml"); + while (true) { + cvFrame(); - cv::Ptr facemark = cv::face::FacemarkLBF::create(); - facemark->loadModel ("lbfmodel.yaml"); + graphicsFrame(); - cv::VideoCapture vid (0); - - cv::Mat frame, gray, small; - - while (vid.read(frame)) { - cv::cvtColor (frame, gray, cv::COLOR_BGR2GRAY); - //downsample image for face detection, works too slow on full res - cv::pyrDown (gray, small); - cv::pyrDown (small, small); - - std::vector faces; - faceDetector.detectMultiScale(small, faces); - - //get biggest face - int biggestFace = 0; - int biggestArea = 0; - for (int i = 0; i < faces.size(); i++) { - //convert face region to full res, because we perform facemark on full res - faces[i] = cv::Rect (faces[i].x * 4, faces[i].y * 4, faces[i].width * 4, faces[i].height * 4); - - int iArea = faces[i].area(); - if (iArea > biggestArea) { - biggestFace = i; - biggestArea = iArea; - } - - cv::rectangle (frame, faces[i], cv::Scalar (255, 255, 0)); - } - - std::vector> landmarks; - - if (facemark->fit (frame, faces, landmarks)) { - //for (int i = 0; i < landmarks[biggestFace].size(); i++) { - // cv::circle (frame, landmarks[biggestFace][i], 2, cv::Scalar (255, 255, 255)); - //} - cv::circle(frame, cv::Point2f( - (landmarks[biggestFace][2].x + landmarks[biggestFace][14].x) / 2, - (landmarks[biggestFace][2].y + landmarks[biggestFace][14].y) / 2 - ), 6, cv::Scalar(0, 0, 255)); - cv::circle (frame, landmarks[biggestFace][30], 6, cv::Scalar (0, 255, 255)); - cv::circle (frame, landmarks[biggestFace][66], 3, cv::Scalar (0, 255, 0)); - cv::circle (frame, landmarks[biggestFace][62], 3, cv::Scalar (0, 255, 0)); - - //send control information to graphics - float faceSize = landmarks[biggestFace][14].x - landmarks[biggestFace][2].x; - updateModel(glm::vec2( - (landmarks[biggestFace][2].x + landmarks[biggestFace][14].x) / 2 - * 2 / (float)frame.cols - 1, - (landmarks[biggestFace][2].y + landmarks[biggestFace][14].y) / 2 - * 2 / (float)frame.rows - 1 - ), - glm::vec2( - landmarks[biggestFace][30].x * 2 / (float)frame.cols - 1, - landmarks[biggestFace][30].y * 2 / (float)frame.rows - 1 - ), - faceSize * 6 / (float)frame.cols, - (landmarks[biggestFace][66].y - landmarks[biggestFace][62].y) / faceSize > 0.04f); - } - - graphicsFrame (); - - cv::imshow ("Video Input", frame); - cv::waitKey (33); + cvShowFrame(); } }