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