ui and rectangle detection now works

This commit is contained in:
Harrison Deng 2018-05-07 03:30:20 -05:00
parent 5323f225d8
commit c8bcbe21e8
6 changed files with 95 additions and 62 deletions

View File

@ -1,30 +1,39 @@
/*
* 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++) {
if ((cv::contourArea(contours[i]) > 225) && (cv::contourArea(contours[i]) < (ui->currentFrame(0)->cols * ui->currentFrame(0)->rows) -25)) {
double perimeter = cv::arcLength(contours[i], true); double perimeter = cv::arcLength(contours[i], true);
cv::approxPolyDP(contours[i], contours[i], 0.04*perimeter, true); cv::approxPolyDP(contours[i], contours[i], (epsilon/(float)1000)*perimeter, true);
if ((contours[i].size() == 4) && (cv::contourArea(contours[i]) > 81) && (cv::isContourConvex(contours[i]))) {
if ((contours[i].size() == 4) && (cv::isContourConvex(contours[i]))) {
if (prunedContours.size() != 0) { if (prunedContours.size() != 0) {
bool different = true; bool different = true;
for (unsigned comparedTo = 0; comparedTo < prunedContours.size(); comparedTo++) { for (unsigned comparedTo = 0; comparedTo < prunedContours.size(); comparedTo++) {
@ -48,17 +57,13 @@ int ContourAnalyzer::analyze() {
prunedContours.insert(prunedContours.begin(), contours[i]); prunedContours.insert(prunedContours.begin(), contours[i]);
} }
} }
}
}
} }
return contours.size(); void ContourAnalyzer::drawContoursOntoMat(std::vector<std::vector<cv::Point>> &contours, cv::Mat &frame) {
}
void ContourAnalyzer::drawShapePositions(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));
} }

View File

@ -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_ */

View File

@ -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);
} }
} }
@ -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() {
} }

View File

@ -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();
}; };

View File

@ -4,9 +4,8 @@
class UIListener { class UIListener {
public: public:
virtual UIListener();
virtual void componentSetup() = 0; virtual void componentSetup() = 0;
virtual ~UIListener(); virtual ~UIListener() {};
}; };

View File

@ -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;