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
20 changed files with 262 additions and 241 deletions

2
.gitignore vendored
View File

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

View File

View File

View File

@@ -151,9 +151,16 @@ namespace computervision
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);
amount_of_fingers = filtered_finger_points.size();
return contours_image;
}
int FingerCount::getAmountOfFingers()
{
return amount_of_fingers;
}
double FingerCount::findPointsDistance(Point a, Point b) {
Point difference = a - b;
return sqrt(difference.ddot(difference));

View File

@@ -24,6 +24,13 @@ namespace computervision
*/
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:
// colors to use
Scalar color_blue;
@@ -34,6 +41,8 @@ namespace computervision
Scalar color_yellow;
Scalar color_purple;
int amount_of_fingers;
/**
* @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 "BackgroundRemover.h"
#include "SkinDetector.h"
@@ -11,37 +15,49 @@ namespace computervision
cv::Mat img, imgGray, img2, img2Gray, img3, img4;
int handMaskStartXPos, handMaskStartYPos, handMaskWidth, handMaskHeight;
bool handMaskGenerated = false;
Mat frame, frameOut, handMask, foreground, fingerCountDebug;
BackgroundRemover backgroundRemover;
SkinDetector skinDetector;
FaceDetector faceDetector;
FingerCount fingerCount;
ObjectDetection::ObjectDetection()
{
}
bool ObjectDetection::setup()
{
if (!cap.isOpened()) {
cout << "Can't find camera!" << endl;
return false;
cv::Mat ObjectDetection::readCamera() {
cap.read(img);
return img;
}
cap.read(frame);
frameOut = frame.clone();
bool ObjectDetection::detectHand(Mat cameraFrame)
{
Mat inputFrame = generateHandMaskSquare(cameraFrame);
frameOut = inputFrame.clone();
// detect skin color
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);
// count the amount of fingers and put the info on the matrix
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("foreground", foreground);
@@ -50,12 +66,12 @@ namespace computervision
int key = waitKey(1);
if (key == 98) // b
backgroundRemover.calibrate(frame);
else if (key == 115) // s
skinDetector.calibrate(frame);
if (key == 98) // b, calibrate the background
backgroundRemover.calibrate(inputFrame);
else if (key == 115) // s, calibrate the skin color
skinDetector.calibrate(inputFrame);
return true;
return fingers_amount > 0;
}
void ObjectDetection::calculateDifference()
@@ -72,14 +88,32 @@ namespace computervision
imshow("threshold", img4);
}
void ObjectDetection::detect()
{
int key = waitKey(1);
if (key == 98) // b
backgroundRemover.calibrate(frame);
else if (key == 115) // s
skinDetector.calibrate(frame);
cv::Mat ObjectDetection::generateHandMaskSquare(cv::Mat img)
{
handMaskStartXPos = 20;
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()

View File

@@ -22,13 +22,7 @@ namespace computervision
*
*/
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
*
@@ -40,11 +34,36 @@ namespace computervision
*
*/
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) {
int frameWidth = input.size().width, frameHeight = input.size().height;
int rectangleSize = 20;
int rectangleSize = 25;
Scalar rectangleColor = Scalar(255, 0, 255);
skinColorSamplerRectangle1 = Rect(frameWidth / 5, frameHeight / 2, rectangleSize, rectangleSize);

View File

@@ -4,7 +4,9 @@
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include <ostream>
#include <map>
#include <stdlib.h>
#include <iostream>
#include <Windows.h>
#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
@@ -17,10 +19,7 @@
#include "shaders/static_shader.h"
#include "toolbox/toolbox.h"
#include "scenes/scene.h"
#include "scenes/startupScene.h"
#include "scenes/inGameScene.h"
#include "computervision/MenuTest.h"
#include "computervision/ObjectDetection.h"
#pragma comment(lib, "glfw3.lib")
@@ -30,15 +29,11 @@
static double UpdateDelta();
static GLFWwindow* window;
//Scene management variables
std::map<Scenes, Scene*> scenes;
Scene* current_scene = nullptr;
int chosen_item = 0;
int main(void)
{
#pragma region OPENGL_SETTINGS
#pragma region OPENGL_SETTINGS
if (!glfwInit())
throw "Could not inditialize glwf";
window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGT, "SDBA", NULL, NULL);
@@ -50,17 +45,14 @@ int main(void)
glfwMakeContextCurrent(window);
glewInit();
glGetError();
#pragma endregion
#pragma endregion
glfwSetKeyCallback(window, [](GLFWwindow* window, int key, int scancode, int action, int mods)
{
current_scene->onKey(key, scancode, action, mods);
if (key == GLFW_KEY_ESCAPE)
glfwSetWindowShouldClose(window, true);
});
scenes[Scenes::STARTUP] = new StartupScene();
scenes[Scenes::INGAME] = new InGameScene();
models::RawModel raw_model = LoadObjModel("res/Tree.obj");
models::ModelTexture texture = { render_engine::loader::LoadTexture("res/TreeTexture.png") };
@@ -79,8 +71,8 @@ int main(void)
// set up object detection
//objDetect.setup();
cv::Mat cameraFrame;
current_scene->start();
// Main game loop
while (!glfwWindowShouldClose(window))
{
@@ -88,17 +80,64 @@ int main(void)
const double delta = UpdateDelta();
entity.IncreaseRotation(glm::vec3(0, 1, 0));
camera.Move(window);
current_scene->update(window);
// Render
render_engine::renderer::Prepare();
shader.Start();
shader.LoadViewMatrix(camera);
current_scene->render();
render_engine::renderer::Render(entity, shader);
//objDetect.setup();
objDetect.calculateDifference();
cameraFrame = objDetect.readCamera();
////////////////////////// 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
shader.Stop();
@@ -109,7 +148,6 @@ int main(void)
// Clean up
shader.CleanUp();
render_engine::loader::CleanUp();
current_scene->stop();
glfwTerminate();
return 0;
}

View File

@@ -18,7 +18,7 @@ namespace render_engine
void Init(shaders::StaticShader& shader)
{
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.LoadProjectionMatrix(projectionMatrix);

View File

@@ -1,30 +0,0 @@
#include "inGameScene.h"
#include <GLFW/glfw3.h>
void start()
{
}
void stop()
{
}
void render()
{
}
void update(GLFWwindow* window)
{
}
void onKey(int key, int scancode, int action, int mods)
{
/**
* misschien iets van als niet in settings dan hoeft alleen escape een knop zijn als reserve optie. Als wel in settings, dan heb je hetzelfde hoe je in het in het begin scherm hebt.
**/
}

View File

@@ -1,15 +0,0 @@
#pragma once
#include "scene.h"
class InGameScene : public Scene
{
private:
public:
virtual void start() override;
virtual void stop() override;
virtual void render() override;
virtual void update(GLFWwindow* window) override;
virtual void onKey(int key, int scancode, int action, int mods) override;
};

View File

@@ -1 +0,0 @@
#include "scene.h"

View File

@@ -1,23 +0,0 @@
#pragma once
#include <GLFW/glfw3.h>
class Scene
{
public:
virtual void start() = 0;
virtual void stop() = 0;
virtual void render() = 0;
virtual void update(GLFWwindow* window) = 0;
virtual void onKey(int key, int scancode, int action, int mods) {};
};
enum class Scenes
{
STARTUP,
INGAME,
GAMEOVER,
SETTINGS,
CALIBRATION
};

View File

@@ -1,31 +0,0 @@
#include "startupScene.h"
#include <GLFW/glfw3.h>
void start()
{
}
void stop()
{
}
void render()
{
}
void update(GLFWwindow* window)
{
}
void onKey(int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_DOWN && action == GLFW_RELEASE)
{
//ideetje voor het scrollen door het menu heen
menuIndex = (menuIndex + 1) % 4;
}
}

View File

@@ -1,15 +0,0 @@
#pragma once
#include "scene.h"
class StartupScene : public Scene
{
private:
int menuIndex;
public:
virtual void start() override;
virtual void stop() override;
virtual void render() override;
virtual void update(GLFWwindow* window) override;
virtual void onKey(int key, int scancode, int action, int mods) override;
};

View File

@@ -19,9 +19,8 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\scenes\inGameScene.cpp" />
<ClCompile Include="src\scenes\scene.cpp" />
<ClCompile Include="src\computervision\FaceDetector.cpp" />
<ClCompile Include="src\computervision\MenuTest.cpp" />
<ClCompile Include="src\computervision\ObjectDetection.cpp" />
<ClCompile Include="src\computervision\SkinDetector.cpp" />
<ClCompile Include="src\computervision\FingerCount.cpp" />
@@ -35,14 +34,12 @@
<ClCompile Include="src\shaders\shader_program.cpp" />
<ClCompile Include="src\shaders\static_shader.cpp" />
<ClCompile Include="src\toolbox\toolbox.cpp" />
<ClCompile Include="src\scenes\startupScene.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\scenes\inGameScene.h" />
<ClInclude Include="src\scenes\scene.h" />
<ClInclude Include="src\computervision\FaceDetector.h" />
<ClInclude Include="src\computervision\FingerCount.h" />
<ClInclude Include="src\computervision\BackgroundRemover.h" />
<ClInclude Include="src\computervision\MenuTest.h" />
<ClInclude Include="src\computervision\SkinDetector.h" />
<ClInclude Include="src\computervision\ObjectDetection.h" />
<ClInclude Include="src\entities\camera.h" />
@@ -55,7 +52,6 @@
<ClInclude Include="src\shaders\static_shader.h" />
<ClInclude Include="src\stb_image.h" />
<ClInclude Include="src\toolbox\toolbox.h" />
<ClInclude Include="src\scenes\startupScene.h" />
</ItemGroup>
<ItemGroup>
<Xml Include="res\haarcascade_frontalface_alt.xml" />

View File

@@ -57,13 +57,7 @@
<ClCompile Include="src\computervision\BackgroundRemover.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\scenes\scene.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\scenes\startupScene.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\scenes\inGameScene.cpp">
<ClCompile Include="src\computervision\MenuTest.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
@@ -113,13 +107,7 @@
<ClInclude Include="src\computervision\BackgroundRemover.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\scenes\scene.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\scenes\startupScene.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\scenes\inGameScene.h">
<ClInclude Include="src\computervision\MenuTest.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>