diff --git a/CMakeLists.txt b/CMakeLists.txt index 4fae2c3..9c16fa4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ source_group("" FILES ${INCLUDE} ${SOURCES} ${HEADERS}) source_group("Source Files" FILES "src/main.cpp") # OpenCV package -find_package(OpenCV 4.0 REQUIRED core highgui imgproc imgcodecs PATHS "$ENV{OPENCVDIR}/build") +find_package(OpenCV 4.0 REQUIRED core highgui imgproc imgcodecs PATHS "$ENV{OPENCV_DIR}/build") # Turn on the ability to create folders to organize projects (.vcproj) # It creates "CMakePredefinedTargets" folder by default and adds CMake defined projects like INSTALL.vcproj and ZERO_CHECK.vcproj diff --git a/README.md b/README.md index 7a3577f..297ac14 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **Dealine**: 27.09.2021 Please put your name here: -**Name:** ....... +**Name:** Clichici Calin ## Problem 1.1 ### Calculate Frames-per-Second (FPS) (Points 30) 1. Fork the current repository @@ -13,6 +13,10 @@ Please put your name here: ### Note MacOS users may need to launch the application with the administrator rights, to grant access to the web-camera. +**Solution:** +The FPS varies from 17 FPS to 25 FPS during runtime, with a total average of 24.54 FPS at the end. + + ## Problem 1.2 ### Face detection (Points 70) 1. Read the OpenCV documentation about Viola-Jones face detector: [Cascade Classifier](https://docs.opencv.org/4.2.0/db/d28/tutorial_cascade_classifier.html) @@ -21,6 +25,9 @@ MacOS users may need to launch the application with the administrator rights, to ### Note Please do not copy-paste the example code from the OpenCV documentation, but try to understand the example code and implement the solution to the problem by yourself. +**Solution:** +The implemented face detection algorithm as explained by the OpenCV documentation resulted in a heavy decline in FPS, now averaging between 1 FPS and 3 FPS during runtime, with a total average of 2.49 FPS at the end. Overall, it is a 90% reduction in performance. + ## Submission Please submit the assignment by making a pull request. **Important** : Please make sure that diff --git a/src/main.cpp b/src/main.cpp index 7b2d524..3080e22 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,20 +1,144 @@ #include "types.h" +#include > +#include -int main() { +Mat detect(Mat img); + +using namespace cv; + +CascadeClassifier face_cascade; +CascadeClassifier eyes_cascade; + +int main(int argc, const char** argv) { + + // Set up parser + CommandLineParser parser(argc, argv, + "{help h||}" + "{face_cascade|data/haarcascades/haarcascade_frontalface_alt.xml|Path to face cascade.}" + "{eyes_cascade|data/haarcascades/haarcascade_eye_tree_eyeglasses.xml|Path to eyes cascade.}" + "{camera|0|Camera device number.}"); + + parser.about("\nThis program demonstrates using the cv::CascadeClassifier class to detect objects (Face + eyes) in a video stream.\n" + "You can use Haar or LBP features.\n\n"); + parser.printMessage(); + + // Set up cascades + String face_cascade_name = samples::findFile(parser.get("face_cascade")); + String eyes_cascade_name = samples::findFile(parser.get("eyes_cascade")); + + // Load the cascades + if (!face_cascade.load(face_cascade_name)) + { + std::cout << "--(!)Error loading face cascade\n"; + return -1; + }; + if (!eyes_cascade.load(eyes_cascade_name)) + { + std::cout << "--(!)Error loading eyes cascade\n"; + return -1; + }; + + // Check if camera is available VideoCapture camera; if (!camera.open(0)) { printf("Can't find a camera\n"); return 1; }; + // Number of frames to capture + int num_frames = 1; + double fps; + + // Start and end times for FPS estimation + time_t start, end; + + // Start and end timers for elapsed time estiamtion + time_t timerStart, timerEnd; + // Main loop Mat img; - for(;;) { + + // Start timer for elapsed time estimation + timerStart = clock(); + for(;;) + { + // Start clock for FPS estimation + // Happens before image processing begins + start = clock(); + + // Get image from camera camera >> img; + + // Detect face and draw recognition + img = detect(img); + + // Show the image with facial regonition features imshow("Camera", img); + + // End clock for FPS estimation + // Happens after image processing ends + end = clock(); + + // Detect quit key int key = waitKey(5); if (key == 27 || key == 'q') break; + + // Calculate number of seconds elapsed during image processing + double seconds = (double(end) - double(start)) / double(CLOCKS_PER_SEC); + + // Calculate average FPS + fps = double(num_frames) / double(seconds); + + // Take current clock value + timerEnd = clock(); + + // Recalculate number of seconds to estimate elapsed time so far + seconds = (double(timerEnd) - double(timerStart)) / double(CLOCKS_PER_SEC); + + // If elapsed time greater than 2 seconds, print FPS and reset timer + if (seconds >+ 2) + { + timerStart = clock(); + std::cout << "Average FPS: " << fps << "\n"; + } } + camera.release(); return 0; } + +// Function to detect face and eyes +Mat detect(Mat img) +{ + // Initialize blank mat for gray image + Mat img_gray; + cvtColor(img, img_gray, COLOR_BGR2GRAY); + equalizeHist(img_gray, img_gray); + + // Initialize vector for faces + std::vector faces; + face_cascade.detectMultiScale(img_gray, faces); + + // Process and recognize face and eyes + for (size_t i = 0; i < faces.size(); i++) + { + Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2); + ellipse(img, center, Size(faces[i].width / 2, faces[i].height / 2), 0, 0, 360, Scalar(255, 0, 255), 4); + + Mat faceROI = img_gray(faces[i]); + + // In each face, detect eyes + std::vector eyes; + eyes_cascade.detectMultiScale(faceROI, eyes); + + for (size_t j = 0; j < eyes.size(); j++) + { + Point eye_center(faces[i].x + eyes[j].x + eyes[j].width / 2, faces[i].y + eyes[j].y + eyes[j].height / 2); + int radius = cvRound((eyes[j].width + eyes[j].height) * 0.25); + circle(img, eye_center, radius, Scalar(255, 0, 0), 4); + } + } + + // Return image with detection circles + return img; +}