Compare commits
18 Commits
main
...
feature/re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5939f7702 | ||
|
|
2cec8e9a62 | ||
|
|
820c5a2eb0 | ||
|
|
942ddf24d8 | ||
|
|
1f2258bc01 | ||
|
|
ad4075a826 | ||
|
|
e50cd92a35 | ||
|
|
ff79c1525c | ||
|
|
a7597c8d4f | ||
|
|
5b4d9b624f | ||
|
|
27aca98ea4 | ||
|
|
ca591dd427 | ||
|
|
8720e50ba8 | ||
|
|
acf24cab36 | ||
|
|
1811bf51a4 | ||
|
|
27a09aeca4 | ||
|
|
e39cb1a761 | ||
|
|
ab3b0c296a |
0
gameoverScene.cpp
Normal file
0
gameoverScene.cpp
Normal file
0
gameoverScene.h
Normal file
0
gameoverScene.h
Normal file
24350
res/haarcascade_frontalface_alt.xml
Normal file
24350
res/haarcascade_frontalface_alt.xml
Normal file
File diff suppressed because it is too large
Load Diff
59
src/computervision/BackgroundRemover.cpp
Normal file
59
src/computervision/BackgroundRemover.cpp
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#include "BackgroundRemover.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Author: Pierfrancesco Soffritti https://github.com/PierfrancescoSoffritti
|
||||||
|
*/
|
||||||
|
namespace computervision
|
||||||
|
{
|
||||||
|
BackgroundRemover::BackgroundRemover(void) {
|
||||||
|
background;
|
||||||
|
calibrated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BackgroundRemover::calibrate(Mat input) {
|
||||||
|
cvtColor(input, background, CV_BGR2GRAY);
|
||||||
|
calibrated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat BackgroundRemover::getForeground(Mat input) {
|
||||||
|
Mat foregroundMask = getForegroundMask(input);
|
||||||
|
|
||||||
|
//imshow("foregroundMask", foregroundMask);
|
||||||
|
|
||||||
|
Mat foreground;
|
||||||
|
input.copyTo(foreground, foregroundMask);
|
||||||
|
|
||||||
|
return foreground;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat BackgroundRemover::getForegroundMask(Mat input) {
|
||||||
|
Mat foregroundMask;
|
||||||
|
|
||||||
|
if (!calibrated) {
|
||||||
|
foregroundMask = Mat::zeros(input.size(), CV_8UC1);
|
||||||
|
return foregroundMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
cvtColor(input, foregroundMask, CV_BGR2GRAY);
|
||||||
|
|
||||||
|
removeBackground(foregroundMask, background);
|
||||||
|
|
||||||
|
return foregroundMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BackgroundRemover::removeBackground(Mat input, Mat background) {
|
||||||
|
int thresholdOffset = 25;
|
||||||
|
|
||||||
|
for (int i = 0; i < input.rows; i++) {
|
||||||
|
for (int j = 0; j < input.cols; j++) {
|
||||||
|
uchar framePixel = input.at<uchar>(i, j);
|
||||||
|
uchar bgPixel = background.at<uchar>(i, j);
|
||||||
|
|
||||||
|
if (framePixel >= bgPixel - thresholdOffset && framePixel <= bgPixel + thresholdOffset)
|
||||||
|
input.at<uchar>(i, j) = 0;
|
||||||
|
else
|
||||||
|
input.at<uchar>(i, j) = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
58
src/computervision/BackgroundRemover.h
Normal file
58
src/computervision/BackgroundRemover.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#pragma once
|
||||||
|
#include"opencv2\opencv.hpp"
|
||||||
|
#include <opencv2/imgproc\types_c.h>
|
||||||
|
/*
|
||||||
|
Author: Pierfrancesco Soffritti https://github.com/PierfrancescoSoffritti
|
||||||
|
*/
|
||||||
|
namespace computervision
|
||||||
|
{
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class BackgroundRemover {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief constructor,
|
||||||
|
* create background variable and set calibrated to faslse
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BackgroundRemover(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief sets the input image to a grayscale image
|
||||||
|
* sets calibrated to true
|
||||||
|
*
|
||||||
|
* @param input input the image that has to be calibrated
|
||||||
|
*/
|
||||||
|
void calibrate(Mat input);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the mask of the foregorund of the input image
|
||||||
|
* and copies it to another image
|
||||||
|
*
|
||||||
|
* @param input The image from which the forground needs to be picked
|
||||||
|
* @return The image on which te foregroundmask is copied
|
||||||
|
*/
|
||||||
|
Mat getForeground(Mat input);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Mat background;
|
||||||
|
bool calibrated = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the image to grayscale and removes the background
|
||||||
|
*
|
||||||
|
* @param input The image from which the forground needs to be picked
|
||||||
|
* @return The mask of the foreground of the image
|
||||||
|
*/
|
||||||
|
Mat getForegroundMask(Mat input);
|
||||||
|
/**
|
||||||
|
* @brief makes everything on the background black
|
||||||
|
*
|
||||||
|
* @param input the image from which the background needs to be removed
|
||||||
|
* @param background the background of the image
|
||||||
|
*/
|
||||||
|
void removeBackground(Mat input, Mat background);
|
||||||
|
};
|
||||||
|
}
|
||||||
291
src/computervision/FingerCount.cpp
Normal file
291
src/computervision/FingerCount.cpp
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
#include "FingerCount.h"
|
||||||
|
|
||||||
|
#include "opencv2/imgproc.hpp"
|
||||||
|
#include "opencv2/highgui.hpp"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Author: Nicol<6F> Castellazzi https://github.com/nicast
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LIMIT_ANGLE_SUP 60
|
||||||
|
#define LIMIT_ANGLE_INF 5
|
||||||
|
#define BOUNDING_RECT_FINGER_SIZE_SCALING 0.3
|
||||||
|
#define BOUNDING_RECT_NEIGHBOR_DISTANCE_SCALING 0.05
|
||||||
|
|
||||||
|
namespace computervision
|
||||||
|
{
|
||||||
|
FingerCount::FingerCount(void) {
|
||||||
|
color_blue = Scalar(255, 0, 0);
|
||||||
|
color_green = Scalar(0, 255, 0);
|
||||||
|
color_red = Scalar(0, 0, 255);
|
||||||
|
color_black = Scalar(0, 0, 0);
|
||||||
|
color_white = Scalar(255, 255, 255);
|
||||||
|
color_yellow = Scalar(0, 255, 255);
|
||||||
|
color_purple = Scalar(255, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat FingerCount::findFingersCount(Mat input_image, Mat frame) {
|
||||||
|
Mat contours_image = Mat::zeros(input_image.size(), CV_8UC3);
|
||||||
|
|
||||||
|
// check if the source image is good
|
||||||
|
if (input_image.empty())
|
||||||
|
return contours_image;
|
||||||
|
|
||||||
|
// we work only on the 1 channel result, since this function is called inside a loop we are not sure that this is always the case
|
||||||
|
if (input_image.channels() != 1)
|
||||||
|
return contours_image;
|
||||||
|
|
||||||
|
vector<vector<Point>> contours;
|
||||||
|
vector<Vec4i> hierarchy;
|
||||||
|
|
||||||
|
findContours(input_image, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
|
||||||
|
|
||||||
|
// we need at least one contour to work
|
||||||
|
if (contours.size() <= 0)
|
||||||
|
return contours_image;
|
||||||
|
|
||||||
|
// find the biggest contour (let's suppose it's our hand)
|
||||||
|
int biggest_contour_index = -1;
|
||||||
|
double biggest_area = 0.0;
|
||||||
|
|
||||||
|
for (int i = 0; i < contours.size(); i++) {
|
||||||
|
double area = contourArea(contours[i], false);
|
||||||
|
if (area > biggest_area) {
|
||||||
|
biggest_area = area;
|
||||||
|
biggest_contour_index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (biggest_contour_index < 0)
|
||||||
|
return contours_image;
|
||||||
|
|
||||||
|
// find the convex hull object for each contour and the defects, two different data structure are needed by the OpenCV api
|
||||||
|
vector<Point> hull_points;
|
||||||
|
vector<int> hull_ints;
|
||||||
|
|
||||||
|
// for drawing the convex hull and for finding the bounding rectangle
|
||||||
|
convexHull(Mat(contours[biggest_contour_index]), hull_points, true);
|
||||||
|
|
||||||
|
// for finding the defects
|
||||||
|
convexHull(Mat(contours[biggest_contour_index]), hull_ints, false);
|
||||||
|
|
||||||
|
// we need at least 3 points to find the defects
|
||||||
|
vector<Vec4i> defects;
|
||||||
|
if (hull_ints.size() > 3)
|
||||||
|
convexityDefects(Mat(contours[biggest_contour_index]), hull_ints, defects);
|
||||||
|
else
|
||||||
|
return contours_image;
|
||||||
|
|
||||||
|
// we bound the convex hull
|
||||||
|
Rect bounding_rectangle = boundingRect(Mat(hull_points));
|
||||||
|
|
||||||
|
// we find the center of the bounding rectangle, this should approximately also be the center of the hand
|
||||||
|
Point center_bounding_rect(
|
||||||
|
(bounding_rectangle.tl().x + bounding_rectangle.br().x) / 2,
|
||||||
|
(bounding_rectangle.tl().y + bounding_rectangle.br().y) / 2
|
||||||
|
);
|
||||||
|
|
||||||
|
// we separate the defects keeping only the ones of intrest
|
||||||
|
vector<Point> start_points;
|
||||||
|
vector<Point> far_points;
|
||||||
|
|
||||||
|
for (int i = 0; i < defects.size(); i++) {
|
||||||
|
start_points.push_back(contours[biggest_contour_index][defects[i].val[0]]);
|
||||||
|
|
||||||
|
// filtering the far point based on the distance from the center of the bounding rectangle
|
||||||
|
if (findPointsDistance(contours[biggest_contour_index][defects[i].val[2]], center_bounding_rect) < bounding_rectangle.height * BOUNDING_RECT_FINGER_SIZE_SCALING)
|
||||||
|
far_points.push_back(contours[biggest_contour_index][defects[i].val[2]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we compact them on their medians
|
||||||
|
vector<Point> filtered_start_points = compactOnNeighborhoodMedian(start_points, bounding_rectangle.height * BOUNDING_RECT_NEIGHBOR_DISTANCE_SCALING);
|
||||||
|
vector<Point> filtered_far_points = compactOnNeighborhoodMedian(far_points, bounding_rectangle.height * BOUNDING_RECT_NEIGHBOR_DISTANCE_SCALING);
|
||||||
|
|
||||||
|
// now we try to find the fingers
|
||||||
|
vector<Point> filtered_finger_points;
|
||||||
|
|
||||||
|
if (filtered_far_points.size() > 1) {
|
||||||
|
vector<Point> finger_points;
|
||||||
|
|
||||||
|
for (int i = 0; i < filtered_start_points.size(); i++) {
|
||||||
|
vector<Point> closest_points = findClosestOnX(filtered_far_points, filtered_start_points[i]);
|
||||||
|
|
||||||
|
if (isFinger(closest_points[0], filtered_start_points[i], closest_points[1], LIMIT_ANGLE_INF, LIMIT_ANGLE_SUP, center_bounding_rect, bounding_rectangle.height * BOUNDING_RECT_FINGER_SIZE_SCALING))
|
||||||
|
finger_points.push_back(filtered_start_points[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finger_points.size() > 0) {
|
||||||
|
|
||||||
|
// we have at most five fingers usually :)
|
||||||
|
while (finger_points.size() > 5)
|
||||||
|
finger_points.pop_back();
|
||||||
|
|
||||||
|
// filter out the points too close to each other
|
||||||
|
for (int i = 0; i < finger_points.size() - 1; i++) {
|
||||||
|
if (findPointsDistanceOnX(finger_points[i], finger_points[i + 1]) > bounding_rectangle.height * BOUNDING_RECT_NEIGHBOR_DISTANCE_SCALING * 1.5)
|
||||||
|
filtered_finger_points.push_back(finger_points[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finger_points.size() > 2) {
|
||||||
|
if (findPointsDistanceOnX(finger_points[0], finger_points[finger_points.size() - 1]) > bounding_rectangle.height * BOUNDING_RECT_NEIGHBOR_DISTANCE_SCALING * 1.5)
|
||||||
|
filtered_finger_points.push_back(finger_points[finger_points.size() - 1]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
filtered_finger_points.push_back(finger_points[finger_points.size() - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we draw what found on the returned image
|
||||||
|
drawContours(contours_image, contours, biggest_contour_index, color_green, 2, 8, hierarchy);
|
||||||
|
polylines(contours_image, hull_points, true, color_blue);
|
||||||
|
rectangle(contours_image, bounding_rectangle.tl(), bounding_rectangle.br(), color_red, 2, 8, 0);
|
||||||
|
circle(contours_image, center_bounding_rect, 5, color_purple, 2, 8);
|
||||||
|
drawVectorPoints(contours_image, filtered_start_points, color_blue, true);
|
||||||
|
drawVectorPoints(contours_image, filtered_far_points, color_red, true);
|
||||||
|
drawVectorPoints(contours_image, filtered_finger_points, color_yellow, false);
|
||||||
|
putText(contours_image, to_string(filtered_finger_points.size()), center_bounding_rect, FONT_HERSHEY_PLAIN, 3, color_purple);
|
||||||
|
|
||||||
|
// and on the starting frame
|
||||||
|
drawContours(frame, contours, biggest_contour_index, color_green, 2, 8, hierarchy);
|
||||||
|
circle(frame, center_bounding_rect, 5, color_purple, 2, 8);
|
||||||
|
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);
|
||||||
|
|
||||||
|
return contours_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
double FingerCount::findPointsDistance(Point a, Point b) {
|
||||||
|
Point difference = a - b;
|
||||||
|
return sqrt(difference.ddot(difference));
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<Point> FingerCount::compactOnNeighborhoodMedian(vector<Point> points, double max_neighbor_distance) {
|
||||||
|
vector<Point> median_points;
|
||||||
|
|
||||||
|
if (points.size() == 0)
|
||||||
|
return median_points;
|
||||||
|
|
||||||
|
if (max_neighbor_distance <= 0)
|
||||||
|
return median_points;
|
||||||
|
|
||||||
|
// we start with the first point
|
||||||
|
Point reference = points[0];
|
||||||
|
Point median = points[0];
|
||||||
|
|
||||||
|
for (int i = 1; i < points.size(); i++) {
|
||||||
|
if (findPointsDistance(reference, points[i]) > max_neighbor_distance) {
|
||||||
|
|
||||||
|
// the point is not in range, we save the median
|
||||||
|
median_points.push_back(median);
|
||||||
|
|
||||||
|
// we swap the reference
|
||||||
|
reference = points[i];
|
||||||
|
median = points[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
median = (points[i] + median) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// last median
|
||||||
|
median_points.push_back(median);
|
||||||
|
|
||||||
|
return median_points;
|
||||||
|
}
|
||||||
|
|
||||||
|
double FingerCount::findAngle(Point a, Point b, Point c) {
|
||||||
|
double ab = findPointsDistance(a, b);
|
||||||
|
double bc = findPointsDistance(b, c);
|
||||||
|
double ac = findPointsDistance(a, c);
|
||||||
|
return acos((ab * ab + bc * bc - ac * ac) / (2 * ab * bc)) * 180 / CV_PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FingerCount::isFinger(Point a, Point b, Point c, double limit_angle_inf, double limit_angle_sup, Point palm_center, double min_distance_from_palm) {
|
||||||
|
double angle = findAngle(a, b, c);
|
||||||
|
if (angle > limit_angle_sup || angle < limit_angle_inf)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// the finger point sohould not be under the two far points
|
||||||
|
int delta_y_1 = b.y - a.y;
|
||||||
|
int delta_y_2 = b.y - c.y;
|
||||||
|
if (delta_y_1 > 0 && delta_y_2 > 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// the two far points should not be both under the center of the hand
|
||||||
|
int delta_y_3 = palm_center.y - a.y;
|
||||||
|
int delta_y_4 = palm_center.y - c.y;
|
||||||
|
if (delta_y_3 < 0 && delta_y_4 < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
double distance_from_palm = findPointsDistance(b, palm_center);
|
||||||
|
if (distance_from_palm < min_distance_from_palm)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// this should be the case when no fingers are up
|
||||||
|
double distance_from_palm_far_1 = findPointsDistance(a, palm_center);
|
||||||
|
double distance_from_palm_far_2 = findPointsDistance(c, palm_center);
|
||||||
|
if (distance_from_palm_far_1 < min_distance_from_palm / 4 || distance_from_palm_far_2 < min_distance_from_palm / 4)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<Point> FingerCount::findClosestOnX(vector<Point> points, Point pivot) {
|
||||||
|
vector<Point> to_return(2);
|
||||||
|
|
||||||
|
if (points.size() == 0)
|
||||||
|
return to_return;
|
||||||
|
|
||||||
|
double distance_x_1 = DBL_MAX;
|
||||||
|
double distance_1 = DBL_MAX;
|
||||||
|
double distance_x_2 = DBL_MAX;
|
||||||
|
double distance_2 = DBL_MAX;
|
||||||
|
int index_found = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < points.size(); i++) {
|
||||||
|
double distance_x = findPointsDistanceOnX(pivot, points[i]);
|
||||||
|
double distance = findPointsDistance(pivot, points[i]);
|
||||||
|
|
||||||
|
if (distance_x < distance_x_1 && distance_x != 0 && distance <= distance_1) {
|
||||||
|
distance_x_1 = distance_x;
|
||||||
|
distance_1 = distance;
|
||||||
|
index_found = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
to_return[0] = points[index_found];
|
||||||
|
|
||||||
|
for (int i = 0; i < points.size(); i++) {
|
||||||
|
double distance_x = findPointsDistanceOnX(pivot, points[i]);
|
||||||
|
double distance = findPointsDistance(pivot, points[i]);
|
||||||
|
|
||||||
|
if (distance_x < distance_x_2 && distance_x != 0 && distance <= distance_2 && distance_x != distance_x_1) {
|
||||||
|
distance_x_2 = distance_x;
|
||||||
|
distance_2 = distance;
|
||||||
|
index_found = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
to_return[1] = points[index_found];
|
||||||
|
|
||||||
|
return to_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double FingerCount::findPointsDistanceOnX(Point a, Point b) {
|
||||||
|
double to_return = 0.0;
|
||||||
|
|
||||||
|
if (a.x > b.x)
|
||||||
|
to_return = a.x - b.x;
|
||||||
|
else
|
||||||
|
to_return = b.x - a.x;
|
||||||
|
|
||||||
|
return to_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FingerCount::drawVectorPoints(Mat image, vector<Point> points, Scalar color, bool with_numbers) {
|
||||||
|
for (int i = 0; i < points.size(); i++) {
|
||||||
|
circle(image, points[i], 5, color, 2, 8);
|
||||||
|
if (with_numbers)
|
||||||
|
putText(image, to_string(i), points[i], FONT_HERSHEY_PLAIN, 3, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
110
src/computervision/FingerCount.h
Normal file
110
src/computervision/FingerCount.h
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "opencv2/core.hpp"
|
||||||
|
#include <opencv2/imgproc/types_c.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Author: Nicol<6F> Castellazzi https://github.com/nicast
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace computervision
|
||||||
|
{
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class FingerCount {
|
||||||
|
public:
|
||||||
|
FingerCount(void);
|
||||||
|
/**
|
||||||
|
* @brief gets the amount of fingers that are held up.
|
||||||
|
*
|
||||||
|
* @param input_image the source image to find the fingers on. It should be a mask of a hand
|
||||||
|
* @param frame the frame to draw the resulting values on (how many fingers are held up etc)
|
||||||
|
* @return a new image with all the data drawn on it.
|
||||||
|
*/
|
||||||
|
Mat findFingersCount(Mat input_image, Mat frame);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// colors to use
|
||||||
|
Scalar color_blue;
|
||||||
|
Scalar color_green;
|
||||||
|
Scalar color_red;
|
||||||
|
Scalar color_black;
|
||||||
|
Scalar color_white;
|
||||||
|
Scalar color_yellow;
|
||||||
|
Scalar color_purple;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief finds the distance between 2 points.
|
||||||
|
*
|
||||||
|
* @param a the first point
|
||||||
|
* @param b the second point
|
||||||
|
* @return a double representing the distance
|
||||||
|
*/
|
||||||
|
double findPointsDistance(Point a, Point b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief compacts the given points on their medians.
|
||||||
|
* what it does is for each point, it checks if the distance to it's neighbour is greater than the
|
||||||
|
* max distance. If so, it just adds it to the list that is returned. If not, it calculates the
|
||||||
|
* median and adds it to the returned list
|
||||||
|
*
|
||||||
|
* @param points the points to compact
|
||||||
|
* @param max_neighbor_distance the maximum distance between points
|
||||||
|
* @return a vector with the points now compacted.
|
||||||
|
*/
|
||||||
|
vector<Point> compactOnNeighborhoodMedian(vector<Point> points, double max_neighbor_distance);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief finds the angle between 3 different points.
|
||||||
|
*
|
||||||
|
* @param a the first point
|
||||||
|
* @param b the second point
|
||||||
|
* @param c the third point
|
||||||
|
* @return the angle between the 3 points
|
||||||
|
*/
|
||||||
|
double findAngle(Point a, Point b, Point c);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief checks if the given points make up a finger.
|
||||||
|
*
|
||||||
|
* @param a the first point to check for
|
||||||
|
* @param b the second point to check for
|
||||||
|
* @param c the third point to check for
|
||||||
|
* @param limit_angle_inf the limit of the angle between 2 fingers
|
||||||
|
* @param limit_angle_sup the limit of the angle between a finger and a convex point
|
||||||
|
* @param palm_center the center of the palm
|
||||||
|
* @param distance_from_palm_tollerance the distance from the palm tolerance
|
||||||
|
* @return true if the points are a finger, false if not.
|
||||||
|
*/
|
||||||
|
bool isFinger(Point a, Point b, Point c, double limit_angle_inf, double limit_angle_sup, cv::Point palm_center, double distance_from_palm_tollerance);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief finds the closest point to the given point that is in the given list.
|
||||||
|
*
|
||||||
|
* @param points the points to check for
|
||||||
|
* @param pivot the pivot to check against
|
||||||
|
* @return a vector containing the point that is closest
|
||||||
|
*/
|
||||||
|
vector<Point> findClosestOnX(vector<Point> points, Point pivot);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief finds the distance between the x coords of the points.
|
||||||
|
*
|
||||||
|
* @param a the first point
|
||||||
|
* @param b the second point
|
||||||
|
* @return the distance between the x values
|
||||||
|
*/
|
||||||
|
double findPointsDistanceOnX(Point a, Point b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief draws the points on the image.
|
||||||
|
*
|
||||||
|
* @param image the image to draw on
|
||||||
|
* @param points the points to draw
|
||||||
|
* @param color the color to draw them with
|
||||||
|
* @param with_numbers if the numbers should be drawn with the points
|
||||||
|
*/
|
||||||
|
void drawVectorPoints(Mat image, vector<Point> points, Scalar color, bool with_numbers);
|
||||||
|
};
|
||||||
|
}
|
||||||
87
src/computervision/ObjectDetection.cpp
Normal file
87
src/computervision/ObjectDetection.cpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
|
||||||
|
#include "ObjectDetection.h"
|
||||||
|
#include "BackgroundRemover.h"
|
||||||
|
#include "SkinDetector.h"
|
||||||
|
#include "FingerCount.h"
|
||||||
|
|
||||||
|
namespace computervision
|
||||||
|
{
|
||||||
|
cv::VideoCapture cap(0);
|
||||||
|
|
||||||
|
cv::Mat img, imgGray, img2, img2Gray, img3, img4;
|
||||||
|
|
||||||
|
Mat frame, frameOut, handMask, foreground, fingerCountDebug;
|
||||||
|
BackgroundRemover backgroundRemover;
|
||||||
|
SkinDetector skinDetector;
|
||||||
|
FingerCount fingerCount;
|
||||||
|
|
||||||
|
|
||||||
|
ObjectDetection::ObjectDetection()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectDetection::setup()
|
||||||
|
{
|
||||||
|
if (!cap.isOpened()) {
|
||||||
|
cout << "Can't find camera!" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cap.read(frame);
|
||||||
|
frameOut = frame.clone();
|
||||||
|
|
||||||
|
skinDetector.drawSkinColorSampler(frameOut);
|
||||||
|
|
||||||
|
foreground = backgroundRemover.getForeground(frame);
|
||||||
|
handMask = skinDetector.getSkinMask(foreground);
|
||||||
|
fingerCountDebug = fingerCount.findFingersCount(handMask, frameOut);
|
||||||
|
|
||||||
|
//backgroundRemover.calibrate(frame);
|
||||||
|
|
||||||
|
|
||||||
|
imshow("output", frameOut);
|
||||||
|
imshow("foreground", foreground);
|
||||||
|
imshow("handMask", handMask);
|
||||||
|
imshow("handDetection", fingerCountDebug);
|
||||||
|
|
||||||
|
int key = waitKey(1);
|
||||||
|
|
||||||
|
if (key == 98) // b
|
||||||
|
backgroundRemover.calibrate(frame);
|
||||||
|
else if (key == 115) // s
|
||||||
|
skinDetector.calibrate(frame);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectDetection::calculateDifference()
|
||||||
|
{
|
||||||
|
cap.read(img);
|
||||||
|
cap.read(img2);
|
||||||
|
|
||||||
|
cv::cvtColor(img, imgGray, cv::COLOR_RGBA2GRAY);
|
||||||
|
cv::cvtColor(img2, img2Gray, cv::COLOR_RGBA2GRAY);
|
||||||
|
|
||||||
|
cv::absdiff(imgGray, img2Gray, img3);
|
||||||
|
cv::threshold(img3, img4, 50, 170, cv::THRESH_BINARY);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectDetection::showWebcam()
|
||||||
|
{
|
||||||
|
imshow("Webcam image", img);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
53
src/computervision/ObjectDetection.h
Normal file
53
src/computervision/ObjectDetection.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <opencv2/imgcodecs.hpp>
|
||||||
|
#include <opencv2/highgui.hpp>
|
||||||
|
#include <opencv2/imgproc.hpp>
|
||||||
|
#include <opencv2/objdetect.hpp>
|
||||||
|
#include <opencv2/videoio.hpp>
|
||||||
|
#include <opencv2/core.hpp>
|
||||||
|
#include <opencv2/imgproc/imgproc.hpp>
|
||||||
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace computervision
|
||||||
|
{
|
||||||
|
class ObjectDetection
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief default constructor of 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void showWebcam();
|
||||||
|
/**
|
||||||
|
* @brief Calculates the difference between two images
|
||||||
|
* and outputs an image that only shows the difference
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void calculateDifference();
|
||||||
|
/**
|
||||||
|
* @brief Listens for keypresses and handles them
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void detect();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
105
src/computervision/SkinDetector.cpp
Normal file
105
src/computervision/SkinDetector.cpp
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
#include "SkinDetector.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Author: Pierfrancesco Soffritti https://github.com/PierfrancescoSoffritti
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace computervision
|
||||||
|
{
|
||||||
|
SkinDetector::SkinDetector(void) {
|
||||||
|
hLowThreshold = 0;
|
||||||
|
hHighThreshold = 0;
|
||||||
|
sLowThreshold = 0;
|
||||||
|
sHighThreshold = 0;
|
||||||
|
vLowThreshold = 0;
|
||||||
|
vHighThreshold = 0;
|
||||||
|
|
||||||
|
calibrated = false;
|
||||||
|
|
||||||
|
skinColorSamplerRectangle1, skinColorSamplerRectangle2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkinDetector::drawSkinColorSampler(Mat input) {
|
||||||
|
int frameWidth = input.size().width, frameHeight = input.size().height;
|
||||||
|
|
||||||
|
int rectangleSize = 20;
|
||||||
|
Scalar rectangleColor = Scalar(255, 0, 255);
|
||||||
|
|
||||||
|
skinColorSamplerRectangle1 = Rect(frameWidth / 5, frameHeight / 2, rectangleSize, rectangleSize);
|
||||||
|
skinColorSamplerRectangle2 = Rect(frameWidth / 5, frameHeight / 3, rectangleSize, rectangleSize);
|
||||||
|
|
||||||
|
rectangle(
|
||||||
|
input,
|
||||||
|
skinColorSamplerRectangle1,
|
||||||
|
rectangleColor
|
||||||
|
);
|
||||||
|
|
||||||
|
rectangle(
|
||||||
|
input,
|
||||||
|
skinColorSamplerRectangle2,
|
||||||
|
rectangleColor
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkinDetector::calibrate(Mat input) {
|
||||||
|
|
||||||
|
Mat hsvInput;
|
||||||
|
cvtColor(input, hsvInput, CV_BGR2HSV);
|
||||||
|
|
||||||
|
Mat sample1 = Mat(hsvInput, skinColorSamplerRectangle1);
|
||||||
|
Mat sample2 = Mat(hsvInput, skinColorSamplerRectangle2);
|
||||||
|
|
||||||
|
calculateThresholds(sample1, sample2);
|
||||||
|
|
||||||
|
calibrated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkinDetector::calculateThresholds(Mat sample1, Mat sample2) {
|
||||||
|
int offsetLowThreshold = 80;
|
||||||
|
int offsetHighThreshold = 30;
|
||||||
|
|
||||||
|
Scalar hsvMeansSample1 = mean(sample1);
|
||||||
|
Scalar hsvMeansSample2 = mean(sample2);
|
||||||
|
|
||||||
|
hLowThreshold = min(hsvMeansSample1[0], hsvMeansSample2[0]) - offsetLowThreshold;
|
||||||
|
hHighThreshold = max(hsvMeansSample1[0], hsvMeansSample2[0]) + offsetHighThreshold;
|
||||||
|
|
||||||
|
sLowThreshold = min(hsvMeansSample1[1], hsvMeansSample2[1]) - offsetLowThreshold;
|
||||||
|
sHighThreshold = max(hsvMeansSample1[1], hsvMeansSample2[1]) + offsetHighThreshold;
|
||||||
|
|
||||||
|
// the V channel shouldn't be used. By ignorint it, shadows on the hand wouldn't interfire with segmentation.
|
||||||
|
// Unfortunately there's a bug somewhere and not using the V channel causes some problem. This shouldn't be too hard to fix.
|
||||||
|
vLowThreshold = min(hsvMeansSample1[2], hsvMeansSample2[2]) - offsetLowThreshold;
|
||||||
|
vHighThreshold = max(hsvMeansSample1[2], hsvMeansSample2[2]) + offsetHighThreshold;
|
||||||
|
//vLowThreshold = 0;
|
||||||
|
//vHighThreshold = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat SkinDetector::getSkinMask(Mat input) {
|
||||||
|
Mat skinMask;
|
||||||
|
|
||||||
|
if (!calibrated) {
|
||||||
|
skinMask = Mat::zeros(input.size(), CV_8UC1);
|
||||||
|
return skinMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat hsvInput;
|
||||||
|
cvtColor(input, hsvInput, CV_BGR2HSV);
|
||||||
|
|
||||||
|
inRange(
|
||||||
|
hsvInput,
|
||||||
|
Scalar(hLowThreshold, sLowThreshold, vLowThreshold),
|
||||||
|
Scalar(hHighThreshold, sHighThreshold, vHighThreshold),
|
||||||
|
skinMask);
|
||||||
|
|
||||||
|
performOpening(skinMask, MORPH_ELLIPSE, { 3, 3 });
|
||||||
|
dilate(skinMask, skinMask, Mat(), Point(-1, -1), 3);
|
||||||
|
|
||||||
|
return skinMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkinDetector::performOpening(Mat binaryImage, int kernelShape, Point kernelSize) {
|
||||||
|
Mat structuringElement = getStructuringElement(kernelShape, kernelSize);
|
||||||
|
morphologyEx(binaryImage, binaryImage, MORPH_OPEN, structuringElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
76
src/computervision/SkinDetector.h
Normal file
76
src/computervision/SkinDetector.h
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <opencv2\core.hpp>
|
||||||
|
#include <opencv2/imgcodecs.hpp>
|
||||||
|
#include <opencv2/imgproc.hpp>
|
||||||
|
#include <opencv2/imgproc/types_c.h>
|
||||||
|
/*
|
||||||
|
Author: Pierfrancesco Soffritti https://github.com/PierfrancescoSoffritti
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace computervision
|
||||||
|
{
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class SkinDetector {
|
||||||
|
public:
|
||||||
|
SkinDetector(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief draws the positions in where the skin color will be sampled.
|
||||||
|
*
|
||||||
|
* @param input the input matrix to sample the skin color from
|
||||||
|
*/
|
||||||
|
void drawSkinColorSampler(Mat input);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief calibrates the skin color detector with the given input frame
|
||||||
|
*
|
||||||
|
* @param input the input frame to calibrate from
|
||||||
|
*/
|
||||||
|
void calibrate(Mat input);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief gets the mask for the hand
|
||||||
|
*
|
||||||
|
* @param input the input matrix to get the skin mask from
|
||||||
|
* @returns the skin mask in a new matrix
|
||||||
|
*/
|
||||||
|
Mat getSkinMask(Mat input);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// thresholds for hsv calculation
|
||||||
|
int hLowThreshold = 0;
|
||||||
|
int hHighThreshold = 0;
|
||||||
|
int sLowThreshold = 0;
|
||||||
|
int sHighThreshold = 0;
|
||||||
|
int vLowThreshold = 0;
|
||||||
|
int vHighThreshold = 0;
|
||||||
|
|
||||||
|
// wether or not the skindetector has calibrated yet.
|
||||||
|
bool calibrated = false;
|
||||||
|
|
||||||
|
// rectangles that get drawn to show where the skin color will be sampled
|
||||||
|
Rect skinColorSamplerRectangle1, skinColorSamplerRectangle2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief calculates the skin tresholds for the given samples
|
||||||
|
*
|
||||||
|
* @param sample1 the first sample
|
||||||
|
* @param sample2 the second sample
|
||||||
|
*/
|
||||||
|
void calculateThresholds(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.
|
||||||
|
*
|
||||||
|
* @param binaryImage the matrix to perform the opening on. This needs to be a binary image, so consisting of only 1's and 0's.
|
||||||
|
* @param structuralElementShape the shape to use for the kernel that is used with generating the structuring element
|
||||||
|
* @param structuralElementSize the size of the kernel that will be used with generating the structuring element.
|
||||||
|
*/
|
||||||
|
void performOpening(Mat binaryImage, int structuralElementShape, Point structuralElementSize);
|
||||||
|
};
|
||||||
|
}
|
||||||
25
src/main.cpp
25
src/main.cpp
@@ -6,8 +6,11 @@
|
|||||||
|
|
||||||
#include "stb_image.h"
|
#include "stb_image.h"
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <opencv2/core.hpp>
|
#include <opencv2/core.hpp>
|
||||||
|
#include <opencv2/videoio.hpp>
|
||||||
|
#include <opencv2/video.hpp>
|
||||||
|
|
||||||
#include "gui/gui_interactable.h"
|
#include "gui/gui_interactable.h"
|
||||||
#include "models/model.h"
|
#include "models/model.h"
|
||||||
@@ -17,6 +20,12 @@
|
|||||||
#include "shaders/entity_shader.h"
|
#include "shaders/entity_shader.h"
|
||||||
#include "toolbox/toolbox.h"
|
#include "toolbox/toolbox.h"
|
||||||
|
|
||||||
|
#include "scenes/scene.h"
|
||||||
|
#include "scenes/startupScene.h"
|
||||||
|
#include "scenes/inGameScene.h"
|
||||||
|
|
||||||
|
#include "computervision/ObjectDetection.h"
|
||||||
|
|
||||||
#pragma comment(lib, "glfw3.lib")
|
#pragma comment(lib, "glfw3.lib")
|
||||||
#pragma comment(lib, "glew32s.lib")
|
#pragma comment(lib, "glew32s.lib")
|
||||||
#pragma comment(lib, "opengl32.lib")
|
#pragma comment(lib, "opengl32.lib")
|
||||||
@@ -25,6 +34,10 @@ static double UpdateDelta();
|
|||||||
|
|
||||||
static GLFWwindow* window;
|
static GLFWwindow* window;
|
||||||
|
|
||||||
|
//Scene management variables
|
||||||
|
std::map<Scenes, Scene*> scenes;
|
||||||
|
Scene* current_scene = nullptr;
|
||||||
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
@@ -43,11 +56,14 @@ int main(void)
|
|||||||
#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)
|
||||||
{
|
{
|
||||||
if (key == GLFW_KEY_ESCAPE)
|
current_scene->onKey(key, scancode, action, mods);
|
||||||
glfwSetWindowShouldClose(window, true);
|
if (key == GLFW_KEY_ESCAPE)
|
||||||
});
|
glfwSetWindowShouldClose(window, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
scenes[Scenes::STARTUP] = new StartupScene();
|
||||||
|
scenes[Scenes::INGAME] = new InGameScene();
|
||||||
|
|
||||||
models::RawModel raw_model = render_engine::LoadObjModel("res/House.obj");
|
models::RawModel raw_model = render_engine::LoadObjModel("res/House.obj");
|
||||||
models::ModelTexture texture = { render_engine::loader::LoadTexture("res/Texture.png") };
|
models::ModelTexture texture = { render_engine::loader::LoadTexture("res/Texture.png") };
|
||||||
@@ -131,6 +147,7 @@ int main(void)
|
|||||||
shader.CleanUp();
|
shader.CleanUp();
|
||||||
gui_shader.CleanUp();
|
gui_shader.CleanUp();
|
||||||
render_engine::loader::CleanUp();
|
render_engine::loader::CleanUp();
|
||||||
|
current_scene->stop();
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
29
src/scenes/inGameScene.cpp
Normal file
29
src/scenes/inGameScene.cpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include "inGameScene.h"
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
void InGameScene::start()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void InGameScene::stop()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void InGameScene::render()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void InGameScene::update(GLFWwindow* window)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void InGameScene::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.
|
||||||
|
**/
|
||||||
|
}
|
||||||
17
src/scenes/inGameScene.h
Normal file
17
src/scenes/inGameScene.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "scene.h"
|
||||||
|
class InGameScene : public Scene
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
void start() override;
|
||||||
|
void stop() override;
|
||||||
|
void render() override;
|
||||||
|
void update(GLFWwindow* window) override;
|
||||||
|
void onKey(int key, int scancode, int action, int mods) override;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
1
src/scenes/scene.cpp
Normal file
1
src/scenes/scene.cpp
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#include "scene.h"
|
||||||
23
src/scenes/scene.h
Normal file
23
src/scenes/scene.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#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
|
||||||
|
};
|
||||||
31
src/scenes/startupScene.cpp
Normal file
31
src/scenes/startupScene.cpp
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#include "startupScene.h"
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
void StartupScene::start()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartupScene::stop()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartupScene::render()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartupScene::update(GLFWwindow* window)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartupScene::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;
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/scenes/startupScene.h
Normal file
15
src/scenes/startupScene.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "scene.h"
|
||||||
|
class StartupScene : public Scene
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int menuIndex;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void start() override;
|
||||||
|
void stop() override;
|
||||||
|
void render() override;
|
||||||
|
void update(GLFWwindow* window) override;
|
||||||
|
void onKey(int key, int scancode, int action, int mods) override;
|
||||||
|
};
|
||||||
|
|
||||||
@@ -19,6 +19,12 @@
|
|||||||
</ProjectConfiguration>
|
</ProjectConfiguration>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="src\scenes\inGameScene.cpp" />
|
||||||
|
<ClCompile Include="src\scenes\scene.cpp" />
|
||||||
|
<ClCompile Include="src\computervision\ObjectDetection.cpp" />
|
||||||
|
<ClCompile Include="src\computervision\SkinDetector.cpp" />
|
||||||
|
<ClCompile Include="src\computervision\FingerCount.cpp" />
|
||||||
|
<ClCompile Include="src\computervision\BackgroundRemover.cpp" />
|
||||||
<ClCompile Include="src\entities\camera.cpp" />
|
<ClCompile Include="src\entities\camera.cpp" />
|
||||||
<ClCompile Include="src\entities\entity.cpp" />
|
<ClCompile Include="src\entities\entity.cpp" />
|
||||||
<ClCompile Include="src\gui\gui_interactable.cpp" />
|
<ClCompile Include="src\gui\gui_interactable.cpp" />
|
||||||
@@ -30,8 +36,15 @@
|
|||||||
<ClCompile Include="src\shaders\shader_program.cpp" />
|
<ClCompile Include="src\shaders\shader_program.cpp" />
|
||||||
<ClCompile Include="src\shaders\entity_shader.cpp" />
|
<ClCompile Include="src\shaders\entity_shader.cpp" />
|
||||||
<ClCompile Include="src\toolbox\toolbox.cpp" />
|
<ClCompile Include="src\toolbox\toolbox.cpp" />
|
||||||
|
<ClCompile Include="src\scenes\startupScene.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="src\scenes\inGameScene.h" />
|
||||||
|
<ClInclude Include="src\scenes\scene.h" />
|
||||||
|
<ClInclude Include="src\computervision\FingerCount.h" />
|
||||||
|
<ClInclude Include="src\computervision\BackgroundRemover.h" />
|
||||||
|
<ClInclude Include="src\computervision\SkinDetector.h" />
|
||||||
|
<ClInclude Include="src\computervision\ObjectDetection.h" />
|
||||||
<ClInclude Include="src\entities\camera.h" />
|
<ClInclude Include="src\entities\camera.h" />
|
||||||
<ClInclude Include="src\entities\entity.h" />
|
<ClInclude Include="src\entities\entity.h" />
|
||||||
<ClInclude Include="src\entities\light.h" />
|
<ClInclude Include="src\entities\light.h" />
|
||||||
@@ -46,6 +59,10 @@
|
|||||||
<ClInclude Include="src\shaders\entity_shader.h" />
|
<ClInclude Include="src\shaders\entity_shader.h" />
|
||||||
<ClInclude Include="src\stb_image.h" />
|
<ClInclude Include="src\stb_image.h" />
|
||||||
<ClInclude Include="src\toolbox\toolbox.h" />
|
<ClInclude Include="src\toolbox\toolbox.h" />
|
||||||
|
<ClInclude Include="src\scenes\startupScene.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Xml Include="res\haarcascade_frontalface_alt.xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<VCProjectVersion>16.0</VCProjectVersion>
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
|
|||||||
@@ -48,6 +48,27 @@
|
|||||||
<ClCompile Include="src\gui\gui_interactable.cpp">
|
<ClCompile Include="src\gui\gui_interactable.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\computervision\ObjectDetection.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\computervision\SkinDetector.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\computervision\FingerCount.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<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">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="src\entities\Camera.h">
|
<ClInclude Include="src\entities\Camera.h">
|
||||||
@@ -92,5 +113,29 @@
|
|||||||
<ClInclude Include="src\gui\gui_interactable.h">
|
<ClInclude Include="src\gui\gui_interactable.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\computervision\ObjectDetection.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\computervision\SkinDetector.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\computervision\FingerCount.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<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">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Xml Include="res\haarcascade_frontalface_alt.xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
Reference in New Issue
Block a user