Compare commits

7 Commits

Author SHA1 Message Date
Kim
623003a4f7 [ADD] gitignore change 2021-06-01 14:40:26 +02:00
Kim
27e99dd2eb [ADD] Looping through array depending on open or closed hand 2021-06-01 14:37:57 +02:00
Sem van der Hoeven
f1f1aac93d [ADD] comments 2021-05-25 15:54:02 +02:00
Sem van der Hoeven
563f465e2c [EDIT] remove unused methods 2021-05-25 15:46:53 +02:00
Sem van der Hoeven
05ae8ee019 [FEATURE] finished hand open/closed recognition 2021-05-25 14:49:04 +02:00
Sem van der Hoeven
3696e2eb30 [EDIT] improve hand detection with mask 2021-05-25 14:19:18 +02:00
Sem van der Hoeven
276aa1a449 [ADD] mask methods 2021-05-25 13:31:25 +02:00
12 changed files with 266 additions and 91 deletions

2
.gitignore vendored
View File

@@ -428,4 +428,6 @@ FodyWeavers.xsd
**/docs/* **/docs/*
**/doc/* **/doc/*
**/pose_iter_160000.caffemodel
# End of https://www.toptal.com/developers/gitignore/api/c++,visualstudio,visualstudiocode,opencv # End of https://www.toptal.com/developers/gitignore/api/c++,visualstudio,visualstudiocode,opencv

View File

@@ -151,9 +151,16 @@ namespace computervision
drawVectorPoints(frame, filtered_finger_points, color_yellow, false); drawVectorPoints(frame, filtered_finger_points, color_yellow, false);
putText(frame, to_string(filtered_finger_points.size()), center_bounding_rect, FONT_HERSHEY_PLAIN, 3, color_purple); putText(frame, to_string(filtered_finger_points.size()), center_bounding_rect, FONT_HERSHEY_PLAIN, 3, color_purple);
amount_of_fingers = filtered_finger_points.size();
return contours_image; return contours_image;
} }
int FingerCount::getAmountOfFingers()
{
return amount_of_fingers;
}
double FingerCount::findPointsDistance(Point a, Point b) { double FingerCount::findPointsDistance(Point a, Point b) {
Point difference = a - b; Point difference = a - b;
return sqrt(difference.ddot(difference)); return sqrt(difference.ddot(difference));

View File

@@ -24,6 +24,13 @@ namespace computervision
*/ */
Mat findFingersCount(Mat input_image, Mat frame); Mat findFingersCount(Mat input_image, Mat frame);
/**
* @brief gets the currently held-up finger count.
*
* @return the currently held-up finger count
*/
int getAmountOfFingers();
private: private:
// colors to use // colors to use
Scalar color_blue; Scalar color_blue;
@@ -34,6 +41,8 @@ namespace computervision
Scalar color_yellow; Scalar color_yellow;
Scalar color_purple; Scalar color_purple;
int amount_of_fingers;
/** /**
* @brief finds the distance between 2 points. * @brief finds the distance between 2 points.
* *

View File

@@ -0,0 +1,25 @@
#include "MenuTest.h"
#include <iostream>
namespace computervision
{
int menu_item_array[4] = { 1, 2, 3, 4 };
float item_number = 0;
MenuTest::MenuTest(void) {
}
int MenuTest::GetMenuItem(bool hand_state) {
item_number += 0.20f;
int temp_item_number = item_number;
//If temp_item_number is equal to the size of the array, set item_number bac to zero to loop through the array again
if (temp_item_number == sizeof(menu_item_array) / sizeof(menu_item_array[0])) {
item_number = 0;
}
return menu_item_array[temp_item_number];
}
}

View File

@@ -0,0 +1,18 @@
namespace computervision
{
class MenuTest {
public:
/**
* @brief Constructor for the class MenuTest, loads in array with menu items
*
*/
MenuTest(void);
/**
* @brief Returns the itemnumber in an array
*
* @param input_bool is either true or false, depending on the recognized hand gesture
*/
int GetMenuItem(bool input_bool);
};
}

View File

@@ -1,4 +1,8 @@
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/video.hpp>
#include "ObjectDetection.h" #include "ObjectDetection.h"
#include "BackgroundRemover.h" #include "BackgroundRemover.h"
#include "SkinDetector.h" #include "SkinDetector.h"
@@ -11,37 +15,49 @@ namespace computervision
cv::Mat img, imgGray, img2, img2Gray, img3, img4; cv::Mat img, imgGray, img2, img2Gray, img3, img4;
int handMaskStartXPos, handMaskStartYPos, handMaskWidth, handMaskHeight;
bool handMaskGenerated = false;
Mat frame, frameOut, handMask, foreground, fingerCountDebug; Mat frame, frameOut, handMask, foreground, fingerCountDebug;
BackgroundRemover backgroundRemover; BackgroundRemover backgroundRemover;
SkinDetector skinDetector; SkinDetector skinDetector;
FaceDetector faceDetector; FaceDetector faceDetector;
FingerCount fingerCount; FingerCount fingerCount;
ObjectDetection::ObjectDetection() ObjectDetection::ObjectDetection()
{ {
} }
bool ObjectDetection::setup() cv::Mat ObjectDetection::readCamera() {
{ cap.read(img);
if (!cap.isOpened()) { return img;
cout << "Can't find camera!" << endl;
return false;
} }
cap.read(frame); bool ObjectDetection::detectHand(Mat cameraFrame)
frameOut = frame.clone(); {
Mat inputFrame = generateHandMaskSquare(cameraFrame);
frameOut = inputFrame.clone();
// detect skin color
skinDetector.drawSkinColorSampler(frameOut); skinDetector.drawSkinColorSampler(frameOut);
foreground = backgroundRemover.getForeground(frame); // remove background from image
foreground = backgroundRemover.getForeground(inputFrame);
faceDetector.removeFaces(frame, foreground); // detect the hand contours
handMask = skinDetector.getSkinMask(foreground); handMask = skinDetector.getSkinMask(foreground);
// count the amount of fingers and put the info on the matrix
fingerCountDebug = fingerCount.findFingersCount(handMask, frameOut); fingerCountDebug = fingerCount.findFingersCount(handMask, frameOut);
//backgroundRemover.calibrate(frame); // get the amount of fingers
int fingers_amount = fingerCount.getAmountOfFingers();
// draw the hand rectangle on the camera input, and draw text showing if the hand is open or closed.
drawHandMaskRect(&cameraFrame);
string hand_text = fingers_amount > 0 ? "open" : "closed";
putText(cameraFrame,hand_text, Point(10, 75), FONT_HERSHEY_PLAIN, 2.0, Scalar(255, 0, 255),3);
imshow("camera", cameraFrame);
imshow("output", frameOut); imshow("output", frameOut);
imshow("foreground", foreground); imshow("foreground", foreground);
@@ -50,12 +66,12 @@ namespace computervision
int key = waitKey(1); int key = waitKey(1);
if (key == 98) // b if (key == 98) // b, calibrate the background
backgroundRemover.calibrate(frame); backgroundRemover.calibrate(inputFrame);
else if (key == 115) // s else if (key == 115) // s, calibrate the skin color
skinDetector.calibrate(frame); skinDetector.calibrate(inputFrame);
return true; return fingers_amount > 0;
} }
void ObjectDetection::calculateDifference() void ObjectDetection::calculateDifference()
@@ -72,14 +88,32 @@ namespace computervision
imshow("threshold", img4); imshow("threshold", img4);
} }
void ObjectDetection::detect()
{
int key = waitKey(1);
if (key == 98) // b cv::Mat ObjectDetection::generateHandMaskSquare(cv::Mat img)
backgroundRemover.calibrate(frame); {
else if (key == 115) // s handMaskStartXPos = 20;
skinDetector.calibrate(frame); handMaskStartYPos = img.rows / 5;
handMaskWidth = img.cols / 3;
handMaskHeight = img.cols / 3;
cv::Mat mask = cv::Mat::zeros(img.size(), img.type());
cv::Mat dstImg = cv::Mat::zeros(img.size(), img.type());
cv::rectangle(mask, Rect(handMaskStartXPos, handMaskStartYPos, handMaskWidth, handMaskHeight), Scalar(255, 255, 255), -1);
img.copyTo(dstImg, mask);
handMaskGenerated = true;
return dstImg;
}
bool ObjectDetection::drawHandMaskRect(cv::Mat* input)
{
if (!handMaskGenerated) return false;
rectangle(*input, Rect(handMaskStartXPos, handMaskStartYPos, handMaskWidth, handMaskHeight), Scalar(255, 255, 255));
return true;
} }
void ObjectDetection::showWebcam() void ObjectDetection::showWebcam()

View File

@@ -22,13 +22,7 @@ namespace computervision
* *
*/ */
ObjectDetection(); ObjectDetection();
/**
* @brief Initializes the object detection, captures a frame and modifies it
* so it is ready to use for object detection
*
* @return return true if webcam is connected, returns false if it isn't
*/
bool setup();
/** /**
* @brief Displays an image of the current webcam-footage * @brief Displays an image of the current webcam-footage
* *
@@ -40,11 +34,36 @@ namespace computervision
* *
*/ */
void calculateDifference(); void calculateDifference();
/** /**
* @brief Listens for keypresses and handles them * @brief generates the square that will hold the mask in which the hand will be detected.
* *
* @param img the current camear frame
* @return a matrix containing the mask
*/ */
void detect(); cv::Mat generateHandMaskSquare(cv::Mat img);
/**
* @brief reads the camera and returns it in a matrix.
*
* @return the camera frame in a matrix
*/
cv::Mat readCamera();
/**
* @brief detects a hand based on the given hand mask input frame.
*
* @param inputFrame the input frame from the camera
* @return true if hand is open, false if hand is closed
*/
bool detectHand(cv::Mat cameraFrame);
/**
* @brief draws the hand mask rectangle on the given input matrix.
*
* @param input the input matrix to draw the rectangle on
*/
bool drawHandMaskRect(cv::Mat *input);
}; };

View File

@@ -22,7 +22,7 @@ namespace computervision
void SkinDetector::drawSkinColorSampler(Mat input) { void SkinDetector::drawSkinColorSampler(Mat input) {
int frameWidth = input.size().width, frameHeight = input.size().height; int frameWidth = input.size().width, frameHeight = input.size().height;
int rectangleSize = 20; int rectangleSize = 25;
Scalar rectangleColor = Scalar(255, 0, 255); Scalar rectangleColor = Scalar(255, 0, 255);
skinColorSamplerRectangle1 = Rect(frameWidth / 5, frameHeight / 2, rectangleSize, rectangleSize); skinColorSamplerRectangle1 = Rect(frameWidth / 5, frameHeight / 2, rectangleSize, rectangleSize);

View File

@@ -4,6 +4,9 @@
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h" #include "stb_image.h"
#include <ostream> #include <ostream>
#include <stdlib.h>
#include <iostream>
#include <Windows.h>
#include <opencv2/core.hpp> #include <opencv2/core.hpp>
#include <opencv2/videoio.hpp> #include <opencv2/videoio.hpp>
@@ -16,6 +19,7 @@
#include "shaders/static_shader.h" #include "shaders/static_shader.h"
#include "toolbox/toolbox.h" #include "toolbox/toolbox.h"
#include "computervision/MenuTest.h"
#include "computervision/ObjectDetection.h" #include "computervision/ObjectDetection.h"
#pragma comment(lib, "glfw3.lib") #pragma comment(lib, "glfw3.lib")
@@ -25,11 +29,11 @@
static double UpdateDelta(); static double UpdateDelta();
static GLFWwindow* window; static GLFWwindow* window;
int chosen_item = 0;
int main(void) int main(void)
{ {
#pragma region OPENGL_SETTINGS #pragma region OPENGL_SETTINGS
if (!glfwInit()) if (!glfwInit())
throw "Could not inditialize glwf"; throw "Could not inditialize glwf";
window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGT, "SDBA", NULL, NULL); window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGT, "SDBA", NULL, NULL);
@@ -41,7 +45,7 @@ int main(void)
glfwMakeContextCurrent(window); glfwMakeContextCurrent(window);
glewInit(); glewInit();
glGetError(); glGetError();
#pragma endregion #pragma endregion
glfwSetKeyCallback(window, [](GLFWwindow* window, int key, int scancode, int action, int mods) glfwSetKeyCallback(window, [](GLFWwindow* window, int key, int scancode, int action, int mods)
{ {
@@ -67,6 +71,7 @@ int main(void)
// set up object detection // set up object detection
//objDetect.setup(); //objDetect.setup();
cv::Mat cameraFrame;
// Main game loop // Main game loop
while (!glfwWindowShouldClose(window)) while (!glfwWindowShouldClose(window))
@@ -81,10 +86,58 @@ int main(void)
shader.Start(); shader.Start();
shader.LoadViewMatrix(camera); shader.LoadViewMatrix(camera);
render_engine::renderer::Render(entity, shader); render_engine::renderer::Render(entity, shader);
//objDetect.setup(); cameraFrame = objDetect.readCamera();
objDetect.calculateDifference();
////////////////////////// KIMS SHIT ////////////////////////////////////
computervision::MenuTest menu_test;
//Get hand state from camera
bool hand_detection = objDetect.detectHand(cameraFrame);
if (hand_detection)
{
std::cout << "hand is opened" << std::endl;
//Loop through menu items
chosen_item = menu_test.GetMenuItem(true);
//For debug only, to see if chosen item is selected properly when hand is opened
std::cout << "chosen item: " << chosen_item << std::endl;
}
else if (!hand_detection)
{
//for debug only, to see if the chosen item is selected properly when hand is closed
std::cout << "hand is closed" << std::endl;
//std::cout << "item to start: " << chosen_item << std::endl;
//TODO link chosen item to the correct game states
switch (chosen_item)
{
case 1:
//Game state 0
std::cout << "in case: " << chosen_item << std::endl;
break;
case 2:
//Game state 1
std::cout << "in case: " << chosen_item << std::endl;
break;
case 3:
//Game state 2
std::cout << "in case: " << chosen_item << std::endl;
break;
case 4:
//Game state 3
std::cout << "in case: " << chosen_item << std::endl;
default:
break;
}
}
///////////////////////// END OF KIMS SHIT ///////////////////////////////
// Finish up // Finish up
shader.Stop(); shader.Stop();

View File

@@ -18,7 +18,7 @@ namespace render_engine
void Init(shaders::StaticShader& shader) void Init(shaders::StaticShader& shader)
{ {
const glm::mat4 projectionMatrix = const glm::mat4 projectionMatrix =
glm::perspective(glm::radians(FOV), (WINDOW_WIDTH / WINDOW_HEIGT), NEAR_PLANE, FAR_PLANE); glm::perspective(glm::radians(FOV), (float)(WINDOW_WIDTH / WINDOW_HEIGT), NEAR_PLANE, FAR_PLANE);
shader.Start(); shader.Start();
shader.LoadProjectionMatrix(projectionMatrix); shader.LoadProjectionMatrix(projectionMatrix);

View File

@@ -20,6 +20,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\computervision\FaceDetector.cpp" /> <ClCompile Include="src\computervision\FaceDetector.cpp" />
<ClCompile Include="src\computervision\MenuTest.cpp" />
<ClCompile Include="src\computervision\ObjectDetection.cpp" /> <ClCompile Include="src\computervision\ObjectDetection.cpp" />
<ClCompile Include="src\computervision\SkinDetector.cpp" /> <ClCompile Include="src\computervision\SkinDetector.cpp" />
<ClCompile Include="src\computervision\FingerCount.cpp" /> <ClCompile Include="src\computervision\FingerCount.cpp" />
@@ -38,6 +39,7 @@
<ClInclude Include="src\computervision\FaceDetector.h" /> <ClInclude Include="src\computervision\FaceDetector.h" />
<ClInclude Include="src\computervision\FingerCount.h" /> <ClInclude Include="src\computervision\FingerCount.h" />
<ClInclude Include="src\computervision\BackgroundRemover.h" /> <ClInclude Include="src\computervision\BackgroundRemover.h" />
<ClInclude Include="src\computervision\MenuTest.h" />
<ClInclude Include="src\computervision\SkinDetector.h" /> <ClInclude Include="src\computervision\SkinDetector.h" />
<ClInclude Include="src\computervision\ObjectDetection.h" /> <ClInclude Include="src\computervision\ObjectDetection.h" />
<ClInclude Include="src\entities\camera.h" /> <ClInclude Include="src\entities\camera.h" />

View File

@@ -57,6 +57,9 @@
<ClCompile Include="src\computervision\BackgroundRemover.cpp"> <ClCompile Include="src\computervision\BackgroundRemover.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\computervision\MenuTest.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="src\entities\Camera.h"> <ClInclude Include="src\entities\Camera.h">
@@ -104,6 +107,9 @@
<ClInclude Include="src\computervision\BackgroundRemover.h"> <ClInclude Include="src\computervision\BackgroundRemover.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\computervision\MenuTest.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Xml Include="res\haarcascade_frontalface_alt.xml" /> <Xml Include="res\haarcascade_frontalface_alt.xml" />