134 lines
4.3 KiB
C++
Executable File
134 lines
4.3 KiB
C++
Executable File
#include "ContourAnalyzer.h"
|
|
#include <cmath>
|
|
#include "../UI.h"
|
|
#include <algorithm>
|
|
|
|
ContourAnalyzer::ContourAnalyzer(UI *ui, int *lastKey) {
|
|
ContourAnalyzer::ui = ui;
|
|
ui->UIListeners.push_back(this);
|
|
this->lastKey = lastKey;
|
|
}
|
|
|
|
void ContourAnalyzer::analyze() {
|
|
preAnalyze();
|
|
|
|
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()), 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);
|
|
|
|
removeRedundancy();
|
|
|
|
if (drawContours) {
|
|
drawContoursOntoMat(*(ui->drawnFrame()));
|
|
cv::putText(*(ui->drawnFrame()), "Showing possible triangles rectangles.",
|
|
cv::Point{5, 30}, cv::FONT_HERSHEY_PLAIN, 0.8, selectColor);
|
|
}
|
|
}
|
|
|
|
void ContourAnalyzer::analyze(cv::Rect rect) {
|
|
preAnalyze();
|
|
cv::Mat frame;
|
|
ui->getOriginalFrame().copyTo(frame);
|
|
|
|
cv::Mat cropped = frame(rect);
|
|
cv::cvtColor(cropped, cropped, cv::COLOR_BGR2GRAY);
|
|
cv::GaussianBlur(cropped, cropped, cv::Size(5, 5), 0);
|
|
cv::threshold(cropped, cropped, binLower, 255, cv::THRESH_BINARY);
|
|
cv::Canny(cropped, cropped, cannyLower, cannyUpper);
|
|
cv::findContours(cropped, contours, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE);
|
|
removeRedundancy();
|
|
}
|
|
|
|
void ContourAnalyzer::removeRedundancy() {
|
|
for (unsigned i = 0; i < contours.size(); i++) {
|
|
if ((cv::contourArea(contours[i]) > minSize) && (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);
|
|
|
|
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);
|
|
|
|
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) {
|
|
prunedContours.insert(prunedContours.begin(), contours[i]);
|
|
}
|
|
} else {
|
|
prunedContours.insert(prunedContours.begin(), contours[i]);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void ContourAnalyzer::preAnalyze() {
|
|
prunedContours.clear();
|
|
if (*lastKey == 99) {
|
|
cannyRec = !cannyRec;
|
|
} else if (*lastKey == 118) {
|
|
drawContours = !drawContours;
|
|
}
|
|
minSize = ui->getWidth()*ui->getHeight()*(minSizeScale/(float)10000);
|
|
|
|
if (cannyRec) {
|
|
cannyUpper = std::min(3*cannyLower, 255);
|
|
cv::setTrackbarPos("Can. Upper", UI::DEBUG_WINDOW, cannyUpper);
|
|
}
|
|
}
|
|
|
|
void ContourAnalyzer::drawContoursOntoMat(cv::Mat &frame) {
|
|
for (unsigned i = 0; i < prunedContours.size(); i++) {
|
|
cv::drawContours(frame, prunedContours, i, selectColor, 1);
|
|
}
|
|
}
|
|
|
|
void ContourAnalyzer::convertContoursToBounds() {
|
|
bounds.clear();
|
|
for (unsigned i = 0; i < prunedContours.size(); i++) {
|
|
bounds.push_back(cv::boundingRect(prunedContours[i]));
|
|
}
|
|
}
|
|
|
|
std::string ContourAnalyzer::contourToString(std::vector<cv::Point> contour) {
|
|
switch (contour.size()) {
|
|
case 4:
|
|
if (cv::isContourConvex(contour)) {
|
|
return "rectangle";
|
|
}
|
|
/* no break */
|
|
default:
|
|
throw std::invalid_argument("Shape too complex!");
|
|
}
|
|
}
|
|
|
|
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);
|
|
cv::createTrackbar("Min. Size", UI::DEBUG_WINDOW, &minSizeScale, 10000);
|
|
}
|
|
ContourAnalyzer::~ContourAnalyzer() {
|
|
ui->UIListeners.erase(std::remove(ui->UIListeners.begin(), ui->UIListeners.end(), this));
|
|
}
|
|
|