This commit is contained in:
2023-05-11 14:29:48 +02:00
commit 86cebd3e6c
5 changed files with 182 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.cache/
build/

17
CMakeLists.txt Normal file
View File

@@ -0,0 +1,17 @@
cmake_minimum_required(VERSION 3.26)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "") # works
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules)
find_package(OpenCV REQUIRED)
project(MarkerTracking)
include_directories( ${OpenCV_INCLUDE_DIRS} )
set(SOURCES
MarkerTracking.cpp
src/Detector.hpp
src/Detector.cpp)
add_executable(MarkerTracking ${SOURCES})
target_link_libraries (MarkerTracking ${OpenCV_LIBS})

74
MarkerTracking.cpp Normal file
View File

@@ -0,0 +1,74 @@
#include <iostream>
#include <opencv2/opencv.hpp>
#include "src/Detector.hpp"
using namespace cv;
using namespace std;
// List of points
typedef vector<Point> contour_t;
// List of contours
typedef vector<contour_t> contour_vector_t;
Mat videoStreamFrameGray;
Mat videoStreamFrameOutput;
// Pos is from UI, dereferencing of the pointer
static void on_trackbar(/* ??? */) {
//*((???*)???) = ???;
}
int main() {
Mat frame;
VideoCapture cap(0);
if (!cap.isOpened()) {
cout << "No webcam, using video file" << endl;
cap.open("MarkerMovie.MP4");
if (cap.isOpened() == false) {
cout << "No video!" << endl;
exit(0);
}
}
const string contoursWindow = "Contours";
const string thresholdWindow = "Threshold";
namedWindow(contoursWindow, WINDOW_FREERATIO);
namedWindow(thresholdWindow, WINDOW_FREERATIO);
const string UI = "Threshold";
int threshold = 65;
createTrackbar(UI, thresholdWindow, &threshold, 255);
Mat imgFiltered;
Detector detector;
while (cap.read(frame)) {
// --- Process Frame ---
Mat grayScale;
imgFiltered = frame.clone();
cvtColor(imgFiltered,grayScale, COLOR_BGR2GRAY);
// Threshold to reduce the noise
adaptiveThreshold(grayScale, grayScale, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 45, 15);
cv::threshold(grayScale, videoStreamFrameGray, threshold, 255, THRESH_OTSU);
detector.detect(videoStreamFrameGray, imgFiltered);
imshow(contoursWindow, imgFiltered);
imshow(thresholdWindow, videoStreamFrameGray);
if (waitKey(10) == 27) {
break;
}
}
destroyWindow(contoursWindow);
return (0);
}

75
src/Detector.cpp Normal file
View File

@@ -0,0 +1,75 @@
#include "Detector.hpp"
using namespace cv;
void Detector::detect(Mat thresholdFrame, Mat &output){
/* TASK: Try to understand this data structure! */
contour_vector_t contours;
/* TASK: Research the different parameters it takes and play around with them */
findContours(thresholdFrame, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
//DEBUG
//drawContours(imgFiltered, contours, -1, Scalar(0, 255, 0), 4);
// size is always positive, so unsigned int -> size_t; if you have not
// initialized the vector it is -1, hence crash
for (size_t k = 0; k < contours.size(); k++) {
contour_t approx_contour;
approxPolyDP(contours[k], approx_contour, arcLength(contours[k], true) * 0.02, true);
// Convert to a usable rectangle
Rect r = boundingRect(approx_contour);
// TASK: 4 Corners -> How to color them in the frame?
if(approx_contour.size() != 4){
continue;
}
// --- Filter tiny ones --- If the found contour is too small (20 ->
// pixels, frame.cols - 10 to prevent extreme big contours)
if (r.width < 20 || r.height < 20 || r.width > output.cols - 10 || r.height > output.cols - 10) {
continue;
}
//DEBUG
//rectangle(filteredFrame, r, Scalar(0,0,255),4);
drawRectangle(output, approx_contour);
}
}
void Detector::drawRectangle(Mat &output, contour_t contour){
// -> Cleaning done!
// 1 -> 1 contour, we have a closed contour, true -> closed , 4 ->
// thickness
polylines(output, contour, true, Scalar(0,0,255), THICKNESS_VALUE);
// -----------------------------
// --- Process Corners ---
for (size_t i = 0; i < 4; i++) {
// Render the corners, 3 -> Radius, -1 filled circle
circle(output, contour[i], 3, CV_RGB(0, 255, 0), -1);
// Euclidic distance, 7 -> parts, both directions dx and dy
/* TASK: How to achieve that? */
double dx = (double)(contour[(i+1)%4].x - contour[i].x) / 7;
double dy = (double)(contour[(i+1)%4].y - contour[i].y) / 7;
// First point already rendered, now the other 6 points
for (size_t j = 1; j < 7; j++) {
// Position calculation
double px = dx * j + contour[i].x;
double py = dy * j + contour[i].y;
Point p;
p.x = (int)px;
p.y = (int)py;
circle(output, p, 3, CV_RGB(0, 0, 255), -1);
}
}
}

14
src/Detector.hpp Normal file
View File

@@ -0,0 +1,14 @@
#include <opencv2/opencv.hpp>
#define THICKNESS_VALUE 4
class Detector{
public:
void detect(cv::Mat thresholdFrame, cv::Mat &output);
private:
// List of points
typedef std::vector<cv::Point> contour_t;
// List of contours
typedef std::vector<contour_t> contour_vector_t;
void drawRectangle(cv::Mat &output, contour_t contour);
};