ui and rectangle detection now works
This commit is contained in:
parent
5323f225d8
commit
c8bcbe21e8
@ -1,64 +1,69 @@
|
|||||||
/*
|
|
||||||
* ContourAnalyzer.cpp
|
|
||||||
*
|
|
||||||
* Created on: Apr 22, 2018
|
|
||||||
* Author: Yunyang
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ContourAnalyzer.h"
|
#include "ContourAnalyzer.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include "../../UI.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
ContourAnalyzer::ContourAnalyzer(UI *ui) {
|
ContourAnalyzer::ContourAnalyzer(UI *ui, int *lastKey) {
|
||||||
ContourAnalyzer::ui = ui;
|
ContourAnalyzer::ui = ui;
|
||||||
|
ui->UIListeners.push_back(this);
|
||||||
|
this->lastKey = lastKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ContourAnalyzer::analyze() {
|
void ContourAnalyzer::analyze() {
|
||||||
prunedContours.clear();
|
prunedContours.clear();
|
||||||
|
|
||||||
|
if (*lastKey == 99) {
|
||||||
|
cannyRec = !cannyRec;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cannyRec) {
|
||||||
|
cannyUpper = std::min(3*cannyLower, 255);
|
||||||
|
cv::setTrackbarPos("Can. Upper", UI::DEBUG_WINDOW, cannyUpper);
|
||||||
|
}
|
||||||
|
|
||||||
cv::cvtColor(*(ui->currentFrame(-1)), *(ui->nextFrame()), cv::COLOR_BGR2GRAY);
|
cv::cvtColor(*(ui->currentFrame(-1)), *(ui->nextFrame()), cv::COLOR_BGR2GRAY);
|
||||||
cv::GaussianBlur(*(ui->currentFrame(-1)), *(ui->nextFrame()), cv::Size(5, 5), 0);
|
cv::GaussianBlur(*(ui->currentFrame(-1)), *(ui->nextFrame()), cv::Size(5, 5), 0);
|
||||||
cv::threshold(*(ui->currentFrame(-1)), *(ui->nextFrame()), 123, 255, cv::THRESH_BINARY);
|
cv::threshold(*(ui->currentFrame(-1)), *(ui->nextFrame()), binLower, 255, cv::THRESH_BINARY);
|
||||||
cv::Canny(*(ui->currentFrame(-1)), *(ui->nextFrame()), 35, 125);
|
cv::Canny(*(ui->currentFrame(-1)), *(ui->nextFrame()), cannyLower, cannyUpper);
|
||||||
cv::findContours(*(ui->currentFrame(-1)), contours, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE);
|
cv::findContours(*(ui->currentFrame()), contours, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE);
|
||||||
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < contours.size(); i++) {
|
for (unsigned i = 0; i < contours.size(); i++) {
|
||||||
double perimeter = cv::arcLength(contours[i], true);
|
if ((cv::contourArea(contours[i]) > 225) && (cv::contourArea(contours[i]) < (ui->currentFrame(0)->cols * ui->currentFrame(0)->rows) -25)) {
|
||||||
cv::approxPolyDP(contours[i], contours[i], 0.04*perimeter, true);
|
double perimeter = cv::arcLength(contours[i], true);
|
||||||
if ((contours[i].size() == 4) && (cv::contourArea(contours[i]) > 81) && (cv::isContourConvex(contours[i]))) {
|
cv::approxPolyDP(contours[i], contours[i], (epsilon/(float)1000)*perimeter, true);
|
||||||
if (prunedContours.size() != 0) {
|
|
||||||
bool different = true;
|
|
||||||
for (unsigned comparedTo = 0; comparedTo < prunedContours.size(); comparedTo++) {
|
|
||||||
cv::Moments m1 = cv::moments(prunedContours[comparedTo]);
|
|
||||||
int cx1 = (m1.m10/m1.m00);
|
|
||||||
int cy1 = (m1.m01/m1.m00);
|
|
||||||
|
|
||||||
cv::Moments m2 = cv::moments(contours[i]);
|
if ((contours[i].size() == 4) && (cv::isContourConvex(contours[i]))) {
|
||||||
int cx2 = (m2.m10/m2.m00);
|
if (prunedContours.size() != 0) {
|
||||||
int cy2 = (m2.m01/m2.m00);
|
bool different = true;
|
||||||
|
for (unsigned comparedTo = 0; comparedTo < prunedContours.size(); comparedTo++) {
|
||||||
|
cv::Moments m1 = cv::moments(prunedContours[comparedTo]);
|
||||||
|
int cx1 = (m1.m10/m1.m00);
|
||||||
|
int cy1 = (m1.m01/m1.m00);
|
||||||
|
|
||||||
if ((std::abs(cx1 - cx2) < 3) && (std::abs(cy1 - cy2) < 3)) {
|
cv::Moments m2 = cv::moments(contours[i]);
|
||||||
different = false;
|
int cx2 = (m2.m10/m2.m00);
|
||||||
break;
|
int cy2 = (m2.m01/m2.m00);
|
||||||
|
|
||||||
|
if ((std::abs(cx1 - cx2) < 3) && (std::abs(cy1 - cy2) < 3)) {
|
||||||
|
different = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if (different) {
|
||||||
if (different) {
|
prunedContours.insert(prunedContours.begin(), contours[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
prunedContours.insert(prunedContours.begin(), contours[i]);
|
prunedContours.insert(prunedContours.begin(), contours[i]);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
prunedContours.insert(prunedContours.begin(), contours[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return contours.size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContourAnalyzer::drawShapePositions(cv::Mat &frame) {
|
void ContourAnalyzer::drawContoursOntoMat(std::vector<std::vector<cv::Point>> &contours, cv::Mat &frame) {
|
||||||
for (unsigned i = 0; i < prunedContours.size(); i++) {
|
for (unsigned i = 0; i < prunedContours.size(); i++) {
|
||||||
cv::Moments m = cv::moments(prunedContours[i]);
|
|
||||||
int cx = (m.m10/m.m00);
|
|
||||||
int cy = (m.m01/m.m00);
|
|
||||||
cv::putText(frame, "rectangle", cv::Point{cx, cy}, cv::FONT_HERSHEY_PLAIN, 1, fontColor, 2);
|
|
||||||
cv::drawContours(frame, prunedContours, i, selectColor, 1);
|
cv::drawContours(frame, prunedContours, i, selectColor, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,6 +91,13 @@ std::vector<cv::Rect> ContourAnalyzer::getBounds() const {
|
|||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ContourAnalyzer::componentSetup() {
|
||||||
|
cv::createTrackbar("Bin. Lower", UI::DEBUG_WINDOW, &binLower , 255);
|
||||||
|
cv::createTrackbar("Can. Lower", UI::DEBUG_WINDOW, &cannyLower , 255);
|
||||||
|
cv::createTrackbar("Can. Upper", UI::DEBUG_WINDOW, &cannyUpper , 255);
|
||||||
|
cv::createTrackbar("Epsilon", UI::DEBUG_WINDOW, &epsilon , 1000);
|
||||||
|
}
|
||||||
ContourAnalyzer::~ContourAnalyzer() {
|
ContourAnalyzer::~ContourAnalyzer() {
|
||||||
|
ui->UIListeners.erase(std::remove(ui->UIListeners.begin(), ui->UIListeners.end(), this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,30 +10,37 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <opencv2/opencv.hpp>
|
#include <opencv2/opencv.hpp>
|
||||||
#include "../../UI.h"
|
#include "../../UI.h"
|
||||||
|
#include "../../UIListener.hpp"
|
||||||
|
|
||||||
class ContourAnalyzer {
|
class ContourAnalyzer: public UIListener {
|
||||||
|
int *lastKey;
|
||||||
|
bool cannyRec = false;
|
||||||
UI *ui;
|
UI *ui;
|
||||||
std::vector<std::vector<cv::Point>> contours;
|
std::vector<std::vector<cv::Point>> contours;
|
||||||
|
std::vector<std::vector<cv::Point>> inconsistentContours;
|
||||||
|
std::vector<std::vector<cv::Point>> consistentContours;
|
||||||
std::vector<std::vector<cv::Point>> prunedContours;
|
std::vector<std::vector<cv::Point>> prunedContours;
|
||||||
std::vector<cv::Rect> bounds;
|
std::vector<cv::Rect> bounds;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int binLowerThresh = 123;
|
int binLower = 60;
|
||||||
int binUpperThresh = 255;
|
|
||||||
|
|
||||||
ContourAnalyzer(UI* ui);
|
int cannyLower = 35;
|
||||||
|
int cannyUpper = 105;
|
||||||
|
|
||||||
|
int epsilon = 48;
|
||||||
|
|
||||||
|
ContourAnalyzer(UI* ui, int *lastKey);
|
||||||
virtual ~ContourAnalyzer();
|
virtual ~ContourAnalyzer();
|
||||||
|
|
||||||
cv::Scalar selectColor { 0, 255, 0 };
|
cv::Scalar selectColor { 0, 255, 0 };
|
||||||
cv::Scalar fontColor { 0, 0, 255 };
|
cv::Scalar fontColor { 0, 0, 255 };
|
||||||
|
void analyze();
|
||||||
int analyze();
|
void drawContoursOntoMat(std::vector<std::vector<cv::Point>> &contours, cv::Mat &frame);
|
||||||
void drawShapePositions(cv::Mat &frame);
|
|
||||||
std::string contourToString(std::vector<cv::Point>);
|
std::string contourToString(std::vector<cv::Point>);
|
||||||
void convertContoursToBounds();
|
void convertContoursToBounds();
|
||||||
|
|
||||||
std::vector<cv::Rect> getBounds() const;
|
std::vector<cv::Rect> getBounds() const;
|
||||||
|
|
||||||
|
void componentSetup();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* RECTANGLE_DETECTION_CONTOURANALYZER_H_ */
|
#endif /* RECTANGLE_DETECTION_CONTOURANALYZER_H_ */
|
||||||
|
25
src/UI.cpp
25
src/UI.cpp
@ -4,25 +4,28 @@ UI::UI(int *lastKey) {
|
|||||||
this->lastKey = lastKey;
|
this->lastKey = lastKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string UI::NORMAL_WINDOW = "Normal";
|
||||||
|
const std::string UI::DEBUG_WINDOW = "Debug";
|
||||||
|
|
||||||
void UI::render() {
|
void UI::render() {
|
||||||
if (state < frames.size()) {
|
if (state < frames.size()) {
|
||||||
frames.resize(state+1);
|
frames.resize(state + 1);
|
||||||
}
|
}
|
||||||
state = 0;
|
state = 0;
|
||||||
cv::imshow("Normal", frames[0]);
|
cv::imshow(UI::NORMAL_WINDOW, frames[0]);
|
||||||
if (debug) {
|
if (debug) {
|
||||||
cv::imshow("debug", frames[debugFrame]);
|
cv::imshow(UI::DEBUG_WINDOW, frames[debugFrame]);
|
||||||
if (showSlider) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*lastKey == 100) {
|
if (*lastKey == 100) {
|
||||||
debug = !debug;
|
debug = !debug;
|
||||||
if (debug == true) {
|
if (debug == true) {
|
||||||
|
cv::imshow(UI::DEBUG_WINDOW, frames[debugFrame]);
|
||||||
for (unsigned i = 0; i < UIListeners.size(); i++) {
|
for (unsigned i = 0; i < UIListeners.size(); i++) {
|
||||||
UIListeners[i]->componentSetup();
|
UIListeners[i]->componentSetup();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
cv::destroyWindow(UI::DEBUG_WINDOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,8 +38,8 @@ void UI::render() {
|
|||||||
|
|
||||||
cv::Mat* UI::nextFrame() {
|
cv::Mat* UI::nextFrame() {
|
||||||
state++;
|
state++;
|
||||||
if (state+1 > frames.size()) {
|
if (state + 1 > frames.size()) {
|
||||||
frames.push_back(cv::Mat{});
|
frames.push_back(cv::Mat { });
|
||||||
}
|
}
|
||||||
return &(frames[state]);
|
return &(frames[state]);
|
||||||
}
|
}
|
||||||
@ -47,7 +50,7 @@ cv::Mat* UI::currentFrame(int offset) {
|
|||||||
|
|
||||||
void UI::nextDebugFrame() {
|
void UI::nextDebugFrame() {
|
||||||
debugFrame++;
|
debugFrame++;
|
||||||
if (debugFrame > frames.size()-1) {
|
if (debugFrame > frames.size() - 1) {
|
||||||
debugFrame = 0;
|
debugFrame = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,5 +59,9 @@ void UI::setOriginalFrame(cv::Mat frame) {
|
|||||||
frames[0] = frame;
|
frames[0] = frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cv::Mat UI::getOriginalFrame() const {
|
||||||
|
return frames[0];
|
||||||
|
}
|
||||||
|
|
||||||
UI::~UI() {
|
UI::~UI() {
|
||||||
}
|
}
|
||||||
|
8
src/UI.h
8
src/UI.h
@ -9,6 +9,7 @@
|
|||||||
#define UI_H_
|
#define UI_H_
|
||||||
#include <opencv2/opencv.hpp>
|
#include <opencv2/opencv.hpp>
|
||||||
#include "UIListener.hpp"
|
#include "UIListener.hpp"
|
||||||
|
#include "string"
|
||||||
|
|
||||||
class UI {
|
class UI {
|
||||||
bool debug = false, showSlider = false;
|
bool debug = false, showSlider = false;
|
||||||
@ -16,15 +17,20 @@ class UI {
|
|||||||
int *lastKey;
|
int *lastKey;
|
||||||
unsigned state = 0;
|
unsigned state = 0;
|
||||||
std::vector<cv::Mat> frames = {cv::Mat()};
|
std::vector<cv::Mat> frames = {cv::Mat()};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static const std::string NORMAL_WINDOW;
|
||||||
|
static const std::string DEBUG_WINDOW;
|
||||||
|
|
||||||
std::vector<UIListener *> UIListeners;
|
std::vector<UIListener *> UIListeners;
|
||||||
UI(int *lastKey);
|
UI(int *lastKey);
|
||||||
void render();
|
void render();
|
||||||
void nextDebugFrame();
|
void nextDebugFrame();
|
||||||
cv::Mat* nextFrame();
|
cv::Mat* nextFrame();
|
||||||
cv::Mat* currentFrame(int offset);
|
cv::Mat* currentFrame(int offset = 0);
|
||||||
|
|
||||||
void setOriginalFrame(cv::Mat frame);
|
void setOriginalFrame(cv::Mat frame);
|
||||||
|
cv::Mat getOriginalFrame() const;
|
||||||
|
|
||||||
virtual ~UI();
|
virtual ~UI();
|
||||||
};
|
};
|
||||||
|
@ -4,9 +4,8 @@
|
|||||||
|
|
||||||
class UIListener {
|
class UIListener {
|
||||||
public:
|
public:
|
||||||
virtual UIListener();
|
|
||||||
virtual void componentSetup() = 0;
|
virtual void componentSetup() = 0;
|
||||||
virtual ~UIListener();
|
virtual ~UIListener() {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,13 +8,12 @@ int main(int argc, char** argv) {
|
|||||||
Webcam webcam = 0;
|
Webcam webcam = 0;
|
||||||
int *lastKey = new int(0);
|
int *lastKey = new int(0);
|
||||||
UI *ui = new UI(lastKey);
|
UI *ui = new UI(lastKey);
|
||||||
ContourAnalyzer ca{ui};
|
ContourAnalyzer ca{ui, lastKey};
|
||||||
while (true) {
|
while (true) {
|
||||||
webcam.update();
|
webcam.update();
|
||||||
cv::Mat frame = webcam.getFrame();
|
cv::Mat frame = webcam.getFrame();
|
||||||
ui->setOriginalFrame(frame);
|
ui->setOriginalFrame(frame);
|
||||||
ca.analyze();
|
|
||||||
ca.drawShapePositions(frame);
|
|
||||||
|
|
||||||
*lastKey = cv::waitKey(33);
|
*lastKey = cv::waitKey(33);
|
||||||
if (*lastKey != 255) {
|
if (*lastKey != 255) {
|
||||||
@ -23,6 +22,9 @@ int main(int argc, char** argv) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ca.analyze();
|
||||||
ui->render();
|
ui->render();
|
||||||
|
|
||||||
*lastKey = 255;
|
*lastKey = 255;
|
||||||
|
Loading…
Reference in New Issue
Block a user