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