new tracking system
This commit is contained in:
parent
b595e557be
commit
4f98c2187a
40
src/Rectangle/BoundTracker.cpp
Executable file
40
src/Rectangle/BoundTracker.cpp
Executable file
@ -0,0 +1,40 @@
|
||||
#include "BoundTracker.h"
|
||||
|
||||
BoundTracker::BoundTracker(int *lastKey, UI *ui) {
|
||||
BoundTracker::lastKey = lastKey;
|
||||
BoundTracker::ui = ui;
|
||||
}
|
||||
|
||||
void BoundTracker::init(cv::Rect2d roi) {
|
||||
BoundTracker::roi = roi;
|
||||
tracker->init(ui->getOriginalFrame(), BoundTracker::roi);
|
||||
}
|
||||
|
||||
bool BoundTracker::track() {
|
||||
tracker->update(ui->getOriginalFrame(), roi);
|
||||
|
||||
if ((roi.x < 0) || (roi.x + roi.width > ui->getWidth()) || (roi.y < 0) || (roi.y + roi.height > ui->getHeight())) {
|
||||
return false;
|
||||
} else {
|
||||
for (unsigned i = 0; i < deadConsistency.size(); i++) {
|
||||
if ((roi & deadConsistency.back()).area() != roi.area() || deadConsistency.size() < queueSize) {
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
deadConsistency.push_back(roi);
|
||||
if (deadConsistency.size() > queueSize) {
|
||||
deadConsistency.pop_front();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
cv::Rect2d BoundTracker::getROI() const {
|
||||
return roi;
|
||||
}
|
||||
|
||||
BoundTracker::~BoundTracker() {
|
||||
}
|
||||
|
24
src/Rectangle/BoundTracker.h
Executable file
24
src/Rectangle/BoundTracker.h
Executable file
@ -0,0 +1,24 @@
|
||||
#ifndef RECTANGLE_BOUNDTRACKER_H_
|
||||
#define RECTANGLE_BOUNDTRACKER_H_
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <opencv2/tracking.hpp>
|
||||
#include "../UI.h"
|
||||
|
||||
class BoundTracker {
|
||||
int *lastKey;
|
||||
UI *ui;
|
||||
cv::Rect2d roi;
|
||||
unsigned queueSize = 20;
|
||||
std::deque<cv::Rect2d> deadConsistency;
|
||||
|
||||
cv::Ptr<cv::Tracker> tracker = cv::TrackerKCF::create();;
|
||||
|
||||
public:
|
||||
BoundTracker(int *lastKey, UI *ui);
|
||||
void init(cv::Rect2d roi);
|
||||
bool track();
|
||||
cv::Rect2d getROI() const;
|
||||
virtual ~BoundTracker();
|
||||
};
|
||||
|
||||
#endif /* RECTANGLE_BOUNDTRACKER_H_ */
|
@ -6,7 +6,7 @@ Confidence::Confidence(int *lastKey, UI *ui, unsigned validityLength) {
|
||||
Confidence::ui = ui;
|
||||
}
|
||||
|
||||
bool Confidence::check(std::vector<cv::Rect> contours) {
|
||||
bool Confidence::check(std::vector<cv::Rect> bounds) {
|
||||
bool consistent;
|
||||
confident.clear();
|
||||
|
||||
@ -14,9 +14,13 @@ bool Confidence::check(std::vector<cv::Rect> contours) {
|
||||
drawBounds = !drawBounds;
|
||||
}
|
||||
|
||||
for (unsigned rectangleID = 0; rectangleID < contours.size(); rectangleID++) {
|
||||
for (unsigned rectangleID = 0; rectangleID < bounds.size(); rectangleID++) {
|
||||
consistent = true;
|
||||
cv::Rect current = contours[rectangleID];
|
||||
|
||||
if (confidenceQueue.size() < queueLength) {
|
||||
consistent = false;
|
||||
}
|
||||
cv::Rect current = bounds[rectangleID];
|
||||
|
||||
for (unsigned frameID = 0; frameID < confidenceQueue.size(); frameID++) {
|
||||
if (confidenceQueue[frameID].size() == 0) {
|
||||
@ -25,27 +29,28 @@ bool Confidence::check(std::vector<cv::Rect> contours) {
|
||||
}
|
||||
for (unsigned frameRectID = 0; frameRectID < confidenceQueue[frameID].size(); frameRectID++) {
|
||||
cv::Rect previous = confidenceQueue[frameID][frameRectID];
|
||||
if ((current & previous).area() < 0.78*(current.area())) {
|
||||
if ((current & previous).area() < minimumDifference*(current.area())) {
|
||||
consistent = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (consistent) {
|
||||
confident.push_back(contours[rectangleID]);
|
||||
confident.push_back(bounds[rectangleID]);
|
||||
}
|
||||
}
|
||||
|
||||
confidenceQueue.push_front(contours);
|
||||
confidenceQueue.push_front(bounds);
|
||||
if (confidenceQueue.size() > queueLength) {
|
||||
confidenceQueue.pop_back();
|
||||
}
|
||||
|
||||
if (drawBounds) {
|
||||
drawBoundsOnMat(*(ui->originalFrame()));
|
||||
drawBoundsOnMat(*(ui->drawnFrame()));
|
||||
}
|
||||
|
||||
return confident.size() != 0;
|
||||
// std::cout << confident.size() << std::endl;
|
||||
return (confident.size() > 0);
|
||||
}
|
||||
|
||||
std::vector<cv::Rect> Confidence::rectangleBounds() const {
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "../UI.h"
|
||||
|
||||
class Confidence {
|
||||
float minimumDifference = 0.76;
|
||||
unsigned queueLength = 0;
|
||||
int *lastKey;
|
||||
UI *ui;
|
||||
|
@ -16,7 +16,7 @@ void ContourAnalyzer::analyze() {
|
||||
} else if (*lastKey == 118) {
|
||||
drawContours = !drawContours;
|
||||
}
|
||||
minSize = ((ui->originalFrame()->cols)*(ui->originalFrame()->rows))*(minSizeScale/(float)10000);
|
||||
minSize = ui->getWidth()*ui->getHeight()*(minSizeScale/(float)10000);
|
||||
|
||||
if (cannyRec) {
|
||||
cannyUpper = std::min(3*cannyLower, 255);
|
||||
@ -64,7 +64,7 @@ void ContourAnalyzer::analyze() {
|
||||
}
|
||||
|
||||
if (drawContours) {
|
||||
drawContoursOntoMat(*(ui->originalFrame()));
|
||||
drawContoursOntoMat(*(ui->drawnFrame()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,11 +26,11 @@ public:
|
||||
int binLower = 52;
|
||||
|
||||
int minSize = 0;
|
||||
int minSizeScale = 15;
|
||||
int minSizeScale = 18;
|
||||
int cannyLower = 57;
|
||||
int cannyUpper = 3*cannyLower;
|
||||
|
||||
int epsilon = 53;
|
||||
int epsilon = 57;
|
||||
|
||||
ContourAnalyzer(UI* ui, int *lastKey);
|
||||
virtual ~ContourAnalyzer();
|
||||
|
21
src/UI.cpp
21
src/UI.cpp
@ -12,7 +12,7 @@ void UI::render() {
|
||||
frames.resize(state + 1);
|
||||
}
|
||||
state = 0;
|
||||
cv::imshow(UI::NORMAL_WINDOW, frames[0]);
|
||||
cv::imshow(UI::NORMAL_WINDOW, frame);
|
||||
if (debug) {
|
||||
cv::imshow(UI::DEBUG_WINDOW, frames[debugFrame]);
|
||||
}
|
||||
@ -56,11 +56,26 @@ void UI::nextDebugFrame() {
|
||||
}
|
||||
|
||||
void UI::setOriginalFrame(cv::Mat frame) {
|
||||
width = frame.cols;
|
||||
height = frame.rows;
|
||||
frames[0] = frame;
|
||||
frames[0].copyTo(UI::frame);
|
||||
}
|
||||
|
||||
cv::Mat* UI::originalFrame() {
|
||||
return &frames[0];
|
||||
cv::Mat* UI::drawnFrame() {
|
||||
return &frame;
|
||||
}
|
||||
|
||||
cv::Mat UI::getOriginalFrame() const {
|
||||
return frames[0];
|
||||
}
|
||||
|
||||
unsigned UI::getWidth() const {
|
||||
return width;
|
||||
}
|
||||
|
||||
unsigned UI::getHeight() const {
|
||||
return height;
|
||||
}
|
||||
|
||||
UI::~UI() {
|
||||
|
7
src/UI.h
7
src/UI.h
@ -15,8 +15,10 @@ class UI {
|
||||
bool debug = false, showSlider = false;
|
||||
unsigned debugFrame = 0;
|
||||
int *lastKey;
|
||||
unsigned width = 0, height = 0;
|
||||
unsigned state = 0;
|
||||
std::vector<cv::Mat> frames = {cv::Mat()};
|
||||
cv::Mat frame;
|
||||
|
||||
public:
|
||||
static const std::string NORMAL_WINDOW;
|
||||
@ -30,8 +32,11 @@ public:
|
||||
cv::Mat* currentFrame(int offset = 0);
|
||||
|
||||
void setOriginalFrame(cv::Mat frame);
|
||||
cv::Mat* originalFrame();
|
||||
cv::Mat* drawnFrame();
|
||||
cv::Mat getOriginalFrame() const;
|
||||
|
||||
unsigned getWidth() const;
|
||||
unsigned getHeight() const;
|
||||
virtual ~UI();
|
||||
};
|
||||
|
||||
|
97
src/main.cpp
97
src/main.cpp
@ -4,35 +4,100 @@
|
||||
#include "webcam/Webcam.h"
|
||||
#include "UI.h"
|
||||
#include "Rectangle/Confidence.h"
|
||||
#include "Rectangle/BoundTracker.h"
|
||||
|
||||
enum State {
|
||||
detection, track, cross_check
|
||||
};
|
||||
|
||||
State state = detection;
|
||||
Webcam webcam = 0;
|
||||
int *lastKey = new int(0);
|
||||
UI *ui = new UI(lastKey);
|
||||
ContourAnalyzer ca { ui, lastKey };
|
||||
Confidence conf { lastKey, ui, 5};
|
||||
BoundTracker tracker {lastKey, ui};
|
||||
cv::Point statusTextPos{5, 25};
|
||||
cv::Scalar textFontColor{35, 125, 35};
|
||||
cv::Scalar rectangleBoundColor{255, 0, 0};
|
||||
|
||||
unsigned frameCount = 0;
|
||||
void run() {
|
||||
switch (state) {
|
||||
case detection:
|
||||
cv::putText(*(ui->drawnFrame()), "Looking for rectangle...", statusTextPos, cv::FONT_HERSHEY_PLAIN, 0.7, 35);
|
||||
ca.analyze();
|
||||
ca.convertContoursToBounds();
|
||||
if (conf.check(ca.getBounds())) {
|
||||
cv::Rect largest;
|
||||
std::vector<cv::Rect> rects = conf.rectangleBounds();
|
||||
for (unsigned i = 0; i < rects.size(); i++) {
|
||||
if (rects[i].area() > largest.area()) {
|
||||
largest = rects[i];
|
||||
}
|
||||
}
|
||||
|
||||
tracker.init(largest);
|
||||
|
||||
state = track;
|
||||
}
|
||||
break;
|
||||
|
||||
case track:
|
||||
cv::putText(*(ui->drawnFrame()), "Tracking...", statusTextPos, cv::FONT_HERSHEY_PLAIN, 0.7, 35);
|
||||
if (!tracker.track()) {
|
||||
state = cross_check;
|
||||
}
|
||||
cv::rectangle(*(ui->drawnFrame()), tracker.getROI(), cv::Scalar{255, 0, 0}, 2);
|
||||
break;
|
||||
|
||||
case cross_check:
|
||||
cv::putText(*(ui->drawnFrame()), "Cross checking...", statusTextPos, cv::FONT_HERSHEY_PLAIN, 0.7, 35);
|
||||
ca.analyze();
|
||||
ca.convertContoursToBounds();
|
||||
cv::Rect2d largest;
|
||||
std::vector<cv::Rect> rects = ca.getBounds();
|
||||
for (unsigned i = 0; i < rects.size(); i++) {
|
||||
if (rects[i].area() > largest.area()) {
|
||||
largest = rects[i];
|
||||
}
|
||||
}
|
||||
|
||||
tracker.track();
|
||||
|
||||
unsigned largestArea = tracker.getROI().area() > largest.area() ? tracker.getROI().area() : largest.area();
|
||||
if (largest.area() != 0 && (tracker.getROI() & largest).area() >= largestArea*(0.75)) {
|
||||
state = track;
|
||||
} else {
|
||||
frameCount++;
|
||||
if (frameCount > 15) {
|
||||
state = detection;
|
||||
frameCount = 0;
|
||||
}
|
||||
}
|
||||
cv::rectangle(*(ui->drawnFrame()), tracker.getROI(), cv::Scalar{255, 0, 0}, 2);
|
||||
cv::rectangle(*(ui->drawnFrame()), largest, cv::Scalar{255, 30, 30}, 1);
|
||||
|
||||
break;
|
||||
}
|
||||
ui->render();
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Webcam webcam = 0;
|
||||
int *lastKey = new int(0);
|
||||
UI *ui = new UI(lastKey);
|
||||
ContourAnalyzer ca{ui, lastKey};
|
||||
Confidence conf{lastKey, ui, 6};
|
||||
|
||||
while (true) {
|
||||
webcam.update();
|
||||
cv::Mat frame = webcam.getFrame();
|
||||
ui->setOriginalFrame(frame);
|
||||
|
||||
|
||||
*lastKey = cv::waitKey(33);
|
||||
if (*lastKey != 255) {
|
||||
if (*lastKey > 0) {
|
||||
std::cout << "key pressed: " << *lastKey << std::endl;
|
||||
if (*lastKey == 27) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ca.analyze();
|
||||
ca.convertContoursToBounds();
|
||||
conf.check(ca.getBounds());
|
||||
ui->render();
|
||||
|
||||
*lastKey = 255;
|
||||
run();
|
||||
*lastKey = -1;
|
||||
}
|
||||
|
||||
delete ui;
|
||||
|
Loading…
Reference in New Issue
Block a user