init
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
.cache/
|
||||||
|
build/
|
||||||
17
CMakeLists.txt
Normal file
17
CMakeLists.txt
Normal 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
74
MarkerTracking.cpp
Normal 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
75
src/Detector.cpp
Normal 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
14
src/Detector.hpp
Normal 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);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user