diff --git a/src/computervision/HandDetectRegion.cpp b/src/computervision/HandDetectRegion.cpp index 0b012db..cf09f07 100644 --- a/src/computervision/HandDetectRegion.cpp +++ b/src/computervision/HandDetectRegion.cpp @@ -1,10 +1,105 @@ #include "HandDetectRegion.h" + namespace computervision { - HandDetectRegion::HandDetectRegion() + + HandDetectRegion::HandDetectRegion(std::string id,int x_pos, int y_pos, int width, int height) { + region_id = id; + start_x_pos = x_pos; + start_y_pos = y_pos; + region_width = width; + region_height = height; + hand_mask_generated = false; + hand_present = false; } + void HandDetectRegion::DetectHand(cv::Mat& camera_frame) + { + Mat input_frame = GenerateHandMaskSquare(camera_frame); + frame_out = input_frame.clone(); + + // detect skin color + skin_detector.drawSkinColorSampler(camera_frame,start_x_pos,start_y_pos,region_width,region_height); + + // remove background from image + foreground = background_remover.getForeground(input_frame); + + // detect the hand contours + handMask = skin_detector.getSkinMask(foreground); + + // count the amount of fingers and put the info on the matrix + //fingerCountDebug = finger_count.findFingersCount(handMask, frame_out); + + //// get the amount of fingers + //int fingers_amount = finger_count.getAmountOfFingers(); + + // draw the hand rectangle on the camera input, and draw text showing if the hand is open or closed. + DrawHandMask(&camera_frame); + + + //hand_calibrator.SetAmountOfFingers(fingers_amount); + //finger_count.DrawHandContours(camera_frame); + //hand_calibrator.DrawHandCalibrationText(camera_frame); + //imshow("camera", camera_frame); + + imshow("output" + region_id, frame_out); + imshow("foreground" + region_id, foreground); + imshow("handMask" + region_id, handMask); + /*imshow("handDetection", fingerCountDebug);*/ + + hand_present = hand_calibrator.CheckIfHandPresent(handMask); + std::string text = (hand_present ? "hand" : "no"); + cv::putText(camera_frame, text, cv::Point(start_x_pos, start_y_pos), cv::FONT_HERSHEY_COMPLEX, 2.0, cv::Scalar(0, 255, 255), 2); + hand_calibrator.SetHandPresent(hand_present); + + } + + cv::Mat HandDetectRegion::GenerateHandMaskSquare(cv::Mat img) + { + cv::Mat mask = cv::Mat::zeros(img.size(), img.type()); + cv::Mat distance_img = cv::Mat::zeros(img.size(), img.type()); + + cv::rectangle(mask, cv::Rect(start_x_pos, start_y_pos, region_width, region_height), cv::Scalar(255, 255, 255), -1); + + img.copyTo(distance_img, mask); + + hand_mask_generated = true; + return distance_img; + } + + bool HandDetectRegion::DrawHandMask(cv::Mat* input) + { + if (!hand_mask_generated) return false; + rectangle(*input, Rect(start_x_pos, start_y_pos, region_width, region_height), Scalar(255, 255, 255)); + return true; + } + + bool HandDetectRegion::IsHandPresent() + { + return hand_present; + } + + void HandDetectRegion::CalibrateBackground() + { + background_remover.calibrate(frame_out); + hand_calibrator.SetBackGroundCalibrated(true); + } + void HandDetectRegion::CalibrateSkin() + { + skin_detector.calibrate(frame_out); + hand_calibrator.SetSkinCalibration(true); + } + + std::vector HandDetectRegion::CalculateSkinTresholds() + { + return skin_detector.calibrateAndReturn(frame_out); + } + + void HandDetectRegion::setSkinTresholds(std::vector& tresholds) + { + skin_detector.setTresholds(tresholds); + } } diff --git a/src/computervision/HandDetectRegion.h b/src/computervision/HandDetectRegion.h index 4bdadf2..3594ff3 100644 --- a/src/computervision/HandDetectRegion.h +++ b/src/computervision/HandDetectRegion.h @@ -1,22 +1,46 @@ #pragma once #include +#include +#include "async/StaticCameraInstance.h" +#include "calibration/HandCalibrator.h" +#include "BackgroundRemover.h" +#include "SkinDetector.h" +#include "FingerCount.h" namespace computervision { class HandDetectRegion { public: - HandDetectRegion(); + HandDetectRegion(std::string id,int x_pos, int y_pos, int width, int height); - cv::Mat GenerateHandMaskSquare(); + cv::Mat GenerateHandMaskSquare(cv::Mat img); - void detectHand(cv::Mat camera_frame); + void DetectHand(cv::Mat& camera_frame); + + bool IsHandPresent(); + + void CalibrateBackground(); + void CalibrateSkin(); + + std::vector CalculateSkinTresholds(); + + void setSkinTresholds(std::vector& tresholds); private: int start_x_pos; int start_y_pos; - int height; - int width; + int region_height; + int region_width; + bool hand_mask_generated; + bool hand_present; + cv::Mat frame, frame_out, handMask, foreground, fingerCountDebug; + BackgroundRemover background_remover; + SkinDetector skin_detector; + handcalibration::HandCalibrator hand_calibrator; + std::string region_id; + + bool DrawHandMask(cv::Mat* input); }; } diff --git a/src/computervision/SkinDetector.cpp b/src/computervision/SkinDetector.cpp index 971ff2a..100f25f 100644 --- a/src/computervision/SkinDetector.cpp +++ b/src/computervision/SkinDetector.cpp @@ -1,4 +1,5 @@ #include "SkinDetector.h" +#include /* Author: Pierfrancesco Soffritti https://github.com/PierfrancescoSoffritti @@ -41,6 +42,29 @@ namespace computervision ); } + void SkinDetector::drawSkinColorSampler(Mat input,int x, int y,int width, int height) { + int frameWidth = width, frameHeight = height; + + int rectangleSize = 25; + Scalar rectangleColor = Scalar(0, 255, 255); + + skinColorSamplerRectangle1 = Rect(frameWidth / 5 + x, frameHeight / 2 + y, rectangleSize, rectangleSize); + skinColorSamplerRectangle2 = Rect(frameWidth / 5 + x, frameHeight / 3 + y, rectangleSize, rectangleSize); + + rectangle( + input, + skinColorSamplerRectangle1, + rectangleColor + ); + + rectangle( + input, + skinColorSamplerRectangle2, + rectangleColor + ); + } + + void SkinDetector::calibrate(Mat input) { Mat hsvInput; @@ -54,6 +78,19 @@ namespace computervision calibrated = true; } + std::vector SkinDetector::calibrateAndReturn(Mat input) + { + Mat hsvInput; + cvtColor(input, hsvInput, CV_BGR2HSV); + + Mat sample1 = Mat(hsvInput, skinColorSamplerRectangle1); + Mat sample2 = Mat(hsvInput, skinColorSamplerRectangle2); + + calibrated = true; + return calculateAndReturnTresholds(sample1, sample2); + + } + void SkinDetector::calculateThresholds(Mat sample1, Mat sample2) { int offsetLowThreshold = 80; int offsetHighThreshold = 30; @@ -75,6 +112,39 @@ namespace computervision //vHighThreshold = 255; } + std::vector SkinDetector::calculateAndReturnTresholds(Mat sample1, Mat sample2) + { + + calculateThresholds(sample1, sample2); + std::vector res; + res.push_back(hLowThreshold); + res.push_back(hHighThreshold); + res.push_back(sLowThreshold); + res.push_back(sHighThreshold); + res.push_back(vLowThreshold); + res.push_back(vHighThreshold); + return res; + } + + void SkinDetector::setTresholds(std::vector& tresholds) + { + if (tresholds.size() != 6) + { + std::cout << "tresholds array not the right size!" << std::endl; + return; + } + + hLowThreshold = tresholds[0]; + hHighThreshold = tresholds[1]; + sLowThreshold = tresholds[2]; + sHighThreshold = tresholds[3]; + vLowThreshold = tresholds[4]; + vHighThreshold = tresholds[5]; + + calibrated = true; + + } + Mat SkinDetector::getSkinMask(Mat input) { Mat skinMask; diff --git a/src/computervision/SkinDetector.h b/src/computervision/SkinDetector.h index c6cf158..02e9dfb 100644 --- a/src/computervision/SkinDetector.h +++ b/src/computervision/SkinDetector.h @@ -24,6 +24,9 @@ namespace computervision */ void drawSkinColorSampler(Mat input); + void drawSkinColorSampler(Mat input, int x, int y, int width, int heigth); + + /* * @brief calibrates the skin color detector with the given input frame * @@ -31,6 +34,10 @@ namespace computervision */ void calibrate(Mat input); + std::vector calibrateAndReturn(Mat input); + + void setTresholds(std::vector& tresholds); + /* * @brief gets the mask for the hand * @@ -63,6 +70,8 @@ namespace computervision */ void calculateThresholds(Mat sample1, Mat sample2); + std::vector calculateAndReturnTresholds(Mat sample1, Mat sample2); + /** * @brief the opening. it generates the structuring element and performs the morphological transformations required to detect the hand. * This needs to be done to get the skin mask. diff --git a/src/scenes/startup_Scene.cpp b/src/scenes/startup_Scene.cpp index e889139..dc9d12c 100644 --- a/src/scenes/startup_Scene.cpp +++ b/src/scenes/startup_Scene.cpp @@ -3,14 +3,20 @@ #include #include "startup_Scene.h" #include "../computervision/ObjectDetection.h" +#include "../computervision/HandDetectRegion.h" #include namespace scene { + std::vector regions; computervision::ObjectDetection objDetect; + computervision::HandDetectRegion reg1("left",20,100,150,150); + computervision::HandDetectRegion reg2("right",200,200,150,150); scene::Scenes scene::Startup_Scene::start(GLFWwindow *window) { + regions.push_back(reg1); + regions.push_back(reg2); while (return_value == scene::Scenes::STARTUP) { render(); @@ -30,9 +36,30 @@ namespace scene void scene::Startup_Scene::update(GLFWwindow* window) { - bool hand_detected = false; - objDetect.DetectHand(objDetect.ReadCamera(),hand_detected); - if (hand_detected) std::cout << "there's a hand!" << std::endl; + cv::Mat camera_frame = objDetect.ReadCamera(); + reg1.DetectHand(camera_frame); + reg2.DetectHand(camera_frame); + + cv::imshow("camera", camera_frame); + + int key = cv::waitKey(1); + + if (key == 98) // b, calibrate the background + { + for (int i = 0; i < regions.size(); i++) + { + regions[i].CalibrateBackground(); + } + } + else if (key == 115) // s, calibrate the skin color + { + std::vector tresholds = regions[0].CalculateSkinTresholds(); + for (int i = 1; i < regions.size(); i++) + { + regions[i].setSkinTresholds(tresholds); + } + + } } diff --git a/wk2_fps.vcxproj b/wk2_fps.vcxproj index 9658b78..4d0fabf 100644 --- a/wk2_fps.vcxproj +++ b/wk2_fps.vcxproj @@ -21,6 +21,7 @@ + @@ -46,6 +47,7 @@ + diff --git a/wk2_fps.vcxproj.filters b/wk2_fps.vcxproj.filters index de921ef..3e9201f 100644 --- a/wk2_fps.vcxproj.filters +++ b/wk2_fps.vcxproj.filters @@ -23,6 +23,7 @@ + @@ -54,6 +55,7 @@ +