rectanglecv/src/detection/Shape/ContourAnalyzer.cpp
2018-04-29 01:56:24 -05:00

93 lines
2.5 KiB
C++
Executable File

/*
* ContourAnalyzer.cpp
*
* Created on: Apr 22, 2018
* Author: Yunyang
*/
#include "../Shape/ContourAnalyzer.h"
#include <cmath>
ContourAnalyzer::ContourAnalyzer() {
}
void ContourAnalyzer::setFrame(cv::Mat frame) {
ContourAnalyzer::originFrame = frame;
}
int ContourAnalyzer::analyze() {
prunedContours.clear();
cv::cvtColor(originFrame, stepFrames[0], cv::COLOR_BGR2GRAY);
cv::GaussianBlur(stepFrames[0], stepFrames[1], cv::Size(5, 5), 0);
cv::Canny(stepFrames[1], stepFrames[2], 35, 125);
cv::findContours(stepFrames[2], 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);
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]);
}
}
}
return contours.size();
}
void ContourAnalyzer::drawShapePositions(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);
}
}
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!");
}
}
cv::Mat ContourAnalyzer::getDebugFrame(int step) const {
return stepFrames[step];
}
std::vector<cv::Rect> ContourAnalyzer::getBounds() const {
return bounds;
}
ContourAnalyzer::~ContourAnalyzer() {
}