From 31089cf6479109a2eb398e91b0e99141502442c0 Mon Sep 17 00:00:00 2001 From: Zer01HD Date: Tue, 8 May 2018 16:47:47 -0500 Subject: [PATCH] ruler object working --- src/Rectangle/Confidence.cpp | 6 ++-- src/Rectangle/ContourAnalyzer.cpp | 15 ++++++-- src/Rectangle/ContourAnalyzer.h | 10 +++--- src/Rectangle/Ruler.cpp | 46 +++++++++++++----------- src/Rectangle/Ruler.h | 21 +++++------ src/UI.cpp | 15 +++++--- src/UI.h | 1 + src/main.cpp | 58 ++++++++++++++++++++----------- src/webcam/Webcam.cpp | 2 ++ 9 files changed, 108 insertions(+), 66 deletions(-) diff --git a/src/Rectangle/Confidence.cpp b/src/Rectangle/Confidence.cpp index 03a450f..90ad821 100755 --- a/src/Rectangle/Confidence.cpp +++ b/src/Rectangle/Confidence.cpp @@ -2,9 +2,9 @@ Confidence::Confidence(int *lastKey, UI *ui, unsigned validityLength, float similarity) { queueLength = validityLength; - Confidence::lastKey = lastKey; - Confidence::ui = ui; - Confidence::similarity = similarity; + this->lastKey = lastKey; + this->ui = ui; + this->similarity = similarity; } bool Confidence::check(std::vector bounds) { diff --git a/src/Rectangle/ContourAnalyzer.cpp b/src/Rectangle/ContourAnalyzer.cpp index 9a315e6..4381ed9 100755 --- a/src/Rectangle/ContourAnalyzer.cpp +++ b/src/Rectangle/ContourAnalyzer.cpp @@ -4,7 +4,7 @@ #include ContourAnalyzer::ContourAnalyzer(UI *ui, int *lastKey) { - ContourAnalyzer::ui = ui; + this->ui = ui; ui->UIListeners.push_back(this); this->lastKey = lastKey; } @@ -22,7 +22,7 @@ void ContourAnalyzer::analyze() { if (drawContours) { drawContoursOntoMat(*(ui->drawnFrame())); - cv::putText(*(ui->drawnFrame()), "Showing possible triangles rectangles.", + cv::putText(*(ui->drawnFrame()), "Showing possible rectangles.", cv::Point{5, 30}, cv::FONT_HERSHEY_PLAIN, 0.8, selectColor); } } @@ -104,6 +104,13 @@ void ContourAnalyzer::convertContoursToBounds() { } } +void ContourAnalyzer::convertContoursToRotatedBounds() { + rotatedBounds.clear(); + for (unsigned i = 0; i < prunedContours.size(); i++) { + rotatedBounds.push_back(cv::minAreaRect(prunedContours[i])); + } +} + std::string ContourAnalyzer::contourToString(std::vector contour) { switch (contour.size()) { case 4: @@ -120,6 +127,10 @@ std::vector ContourAnalyzer::getBounds() const { return bounds; } +std::vector ContourAnalyzer::getRotatedBounds() const { + return rotatedBounds; +} + void ContourAnalyzer::componentSetup() { cv::createTrackbar("Bin. Lower", UI::DEBUG_WINDOW, &binLower , 255); cv::createTrackbar("Can. Lower", UI::DEBUG_WINDOW, &cannyLower , 255); diff --git a/src/Rectangle/ContourAnalyzer.h b/src/Rectangle/ContourAnalyzer.h index 0372dae..c61c0a2 100755 --- a/src/Rectangle/ContourAnalyzer.h +++ b/src/Rectangle/ContourAnalyzer.h @@ -21,18 +21,19 @@ class ContourAnalyzer: public UIListener { std::vector> consistentContours; std::vector> prunedContours; std::vector bounds; + std::vector rotatedBounds; void removeRedundancy(); void preAnalyze(); public: - int binLower = 58; + int binLower = 54; int minSize = 0; int minSizeScale = 18; - int cannyLower = 57; + int cannyLower = 45; int cannyUpper = 3*cannyLower; - int epsilon = 57; + int epsilon = 56; ContourAnalyzer(UI* ui, int *lastKey); virtual ~ContourAnalyzer(); @@ -43,8 +44,9 @@ public: void drawContoursOntoMat(cv::Mat &frame); std::string contourToString(std::vector); void convertContoursToBounds(); + void convertContoursToRotatedBounds(); std::vector getBounds() const; - + std::vector getRotatedBounds() const; void componentSetup(); }; diff --git a/src/Rectangle/Ruler.cpp b/src/Rectangle/Ruler.cpp index 5fa2b03..0c32c85 100755 --- a/src/Rectangle/Ruler.cpp +++ b/src/Rectangle/Ruler.cpp @@ -1,49 +1,49 @@ -/* - * Ruler.cpp - * - * Created on: May 8, 2018 - * Author: yunya - */ - #include "Ruler.h" #include Ruler::Ruler(UI *ui, int *lastKey) { - Ruler::ui = ui; - Ruler::lastKey = lastKey; - focalLength = estimateFocalLength(HFOV); + this->ui = ui; + this->lastKey = lastKey; } -void Ruler::update(cv::Rect rect) { +void Ruler::update() { focalLength = estimateFocalLength(HFOV); distance = estimateDistance(rect); inputUpdate(); updateUI(); } -float Ruler::estimateFocalLength(int HFOV) { - return (ui->getWidth()/2.0)*(1/(std::tan(HFOV/2.0))); +float Ruler::estimateFocalLength(float HFOV) { + float fl = (ui->getWidth()/2.0) * (cos((HFOV * M_PI)/(180*2.0))/sin(HFOV*M_PI/(180*2.0))); + return fl; } void Ruler::updateUI() { if (inputtingVal) { - cv::putText(*(ui->drawnFrame()), ("Given width: " + std::to_string(widthInCM)), confTextPos, cv::FONT_HERSHEY_DUPLEX, 0.7, textFontColor, 2); + cv::putText(*(ui->drawnFrame()), ("Given width: " + std::to_string(givenWidth)), confTextPos, cv::FONT_HERSHEY_PLAIN, 0.7, textFontColor, 2); } else { - cv::putText(*(ui->drawnFrame()), ("Given width: " + std::to_string(widthInCM)), confTextPos, cv::FONT_HERSHEY_DUPLEX, 0.7, textFontColor); + cv::putText(*(ui->drawnFrame()), ("Given width: " + std::to_string(givenWidth)), confTextPos, cv::FONT_HERSHEY_PLAIN, 0.7, textFontColor); } - cv::putText(*(ui->drawnFrame()), ("distance: " + std::to_string(distance) + "cm"), distanceTextPos, cv::FONT_HERSHEY_DUPLEX, 0.7, textFontColor); + cv::putText(*(ui->drawnFrame()), ("distance: " + std::to_string(distance) + "cm"), distanceTextPos, cv::FONT_HERSHEY_PLAIN, 0.7, textFontColor); + std::cout << "focal length: " + std::to_string(focalLength) << std::endl; } void Ruler::toggleInput() { inputtingVal = !inputtingVal; if (!inputtingVal) { numBuild.clear(); + } else { + givenWidth = 0; } } -int Ruler::estimateDistance(cv::Rect rect) { - return (widthInCM*focalLength) / rect.width; +int Ruler::estimateDistance(cv::RotatedRect rect) { + if (rect.size.area() > 0) { + return (givenWidth*focalLength) / rect.size.width; + } else { + return 0; + } } void Ruler::inputUpdate() { @@ -55,11 +55,17 @@ void Ruler::inputUpdate() { char val = '0' + (*lastKey - 48); numBuild.push_back(val); } - std::string numString{numBuild.begin(), numBuild.end()}; - widthInCM = std::stod(numString); + if (numBuild.size() > 0) { + std::string numString{numBuild.begin(), numBuild.end()}; + givenWidth = std::stof(numString); + } } } +void Ruler::updateRectangle(cv::RotatedRect rect) { + this->rect = rect; +} + void Ruler::componentSetup() { } diff --git a/src/Rectangle/Ruler.h b/src/Rectangle/Ruler.h index ef0a91f..6290a0a 100755 --- a/src/Rectangle/Ruler.h +++ b/src/Rectangle/Ruler.h @@ -1,10 +1,3 @@ -/* - * Ruler.h - * - * Created on: May 8, 2018 - * Author: yunya - */ - #ifndef RECTANGLE_RULER_H_ #define RECTANGLE_RULER_H_ #include "../UI.h" @@ -15,20 +8,22 @@ class Ruler: public UIListener { cv::Point confTextPos {5, 75}; cv::Scalar textFontColor {20, 20, 20}; + cv::RotatedRect rect; UI *ui; int *lastKey; float distance = 0; - float widthInCM = 0; - float focalLength; - int HFOV = 65; + float givenWidth = 0; + float focalLength = 0; + float HFOV = 65; bool inputtingVal = false; std::deque numBuild; public: Ruler(UI *ui, int *lastKey); - float estimateFocalLength(int HFOV); - int estimateDistance(cv::Rect rect); - void update(cv::Rect rect); + float estimateFocalLength(float HFOV); + int estimateDistance(cv::RotatedRect rect); + void update(); + void updateRectangle(cv::RotatedRect rect); void componentSetup(); void updateUI(); void toggleInput(); diff --git a/src/UI.cpp b/src/UI.cpp index 11fb955..0060c73 100755 --- a/src/UI.cpp +++ b/src/UI.cpp @@ -1,17 +1,23 @@ #include "UI.h" +const std::string UI::NORMAL_WINDOW = "Normal"; +const std::string UI::DEBUG_WINDOW = "Debug"; + 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() -1) { frames.resize(state + 1); + lastDebugFrame = debugFrame; debugFrame = std::min(state, debugFrame); } + + if (lastDebugFrame != 0 && lastDebugFrame <= frames.size()-1) { + debugFrame = lastDebugFrame; + lastDebugFrame = 0; + } state = 0; cv::imshow(UI::NORMAL_WINDOW, frame); if (debug) { @@ -40,7 +46,8 @@ void UI::render() { cv::Mat* UI::nextFrame() { state++; if (state + 1 > frames.size()) { - frames.push_back(cv::Mat { }); + frames.push_back(cv::Mat {}); + } return &(frames[state]); } diff --git a/src/UI.h b/src/UI.h index 95d50ae..904717d 100755 --- a/src/UI.h +++ b/src/UI.h @@ -13,6 +13,7 @@ class UI { bool debug = false, showSlider = false; + unsigned lastDebugFrame = 0; unsigned debugFrame = 0; int *lastKey; int width = 0, height = 0; diff --git a/src/main.cpp b/src/main.cpp index ffc63e4..8f341f1 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,7 +5,7 @@ #include "UI.h" #include "Rectangle/Confidence.h" #include "Rectangle/BoundTracker.h" - +#include "Rectangle/Ruler.h" enum State { detection, track, cross_check }; @@ -15,12 +15,14 @@ Webcam webcam = 0; int *lastKey = new int(0); UI *ui = new UI(lastKey); ContourAnalyzer ca { ui, lastKey }; -Confidence conf { lastKey, ui, 6, 0.7}; +Confidence conf { lastKey, ui, 6, 0.78}; BoundTracker tracker { lastKey, ui }; cv::Point statusTextPos {5, 15}; cv::Scalar textFontColor { 20, 20, 20}; cv::Scalar rectangleBoundColor { 255, 0, 0 }; -cv::Rect subject; +Ruler ruler{ui, lastKey}; + +cv::RotatedRect subject; unsigned frameCount = 0; void run() { switch (state) { @@ -45,7 +47,7 @@ void run() { case track: { - int growBy = 20; + int growBy = 30; cv::Rect scaledSearchArea; cv::putText(*(ui->drawnFrame()), "Tracking...", statusTextPos, cv::FONT_HERSHEY_PLAIN, 0.8, textFontColor); if (!tracker.track()) { @@ -65,22 +67,26 @@ void run() { ca.analyze(scaledSearchArea); ca.convertContoursToBounds(); - + ca.convertContoursToRotatedBounds(); if (ca.getBounds().size() > 0) { cv::Rect largest; + unsigned index; for (unsigned i = 0; i < ca.getBounds().size(); i++) { if (ca.getBounds()[i].area() > largest.area()) { largest = ca.getBounds()[i]; + index = i; } } + ruler.updateRectangle(ca.getRotatedBounds()[index]); + largest.x += scaledSearchArea.x; largest.y += scaledSearchArea.y; - tracker.setROI(largest); + tracker.init(largest); } - cv::rectangle(*(ui->drawnFrame()), scaledSearchArea, cv::Scalar {150, 0, 0}, 1); cv::rectangle(*(ui->drawnFrame()), tracker.getROI(), cv::Scalar {255, 0, 0}, 2); + } break; @@ -89,21 +95,31 @@ void run() { cv::FONT_HERSHEY_PLAIN, 0.8, textFontColor); ca.analyze(); ca.convertContoursToBounds(); - cv::Rect2d largest; - std::vector rects = ca.getBounds(); - for (unsigned i = 0; i < rects.size(); i++) { - if (rects[i].area() > largest.area()) { - largest = rects[i]; - } - } - tracker.track(); - unsigned largestArea = tracker.getROI().area() > largest.area() ? tracker.getROI().area() : largest.area(); + std::vector rects = ca.getBounds(); + cv::Rect2d largest; + if (rects.size() > 0) { + for (unsigned i = 0; i < rects.size(); i++) { + if (rects[i].area() > largest.area()) { + largest = rects[i]; + } + } - if (largest.area() != 0 && (tracker.getROI() | largest).area() <= largestArea * (1.2)) { - tracker.setROI(largest); - state = track; + unsigned largestArea = tracker.getROI().area() > largest.area() ? tracker.getROI().area() : largest.area(); + + if ((tracker.getROI() | largest).area() <= largestArea * (1.25)) { + tracker.init(largest); + state = track; + frameCount = 0; + } else { + frameCount++; + if (frameCount > 30) { + state = detection; + frameCount = 0; + } + } + cv::rectangle(*(ui->drawnFrame()), largest, cv::Scalar { 255, 0, 0 }, 1); } else { frameCount++; if (frameCount > 30) { @@ -111,11 +127,13 @@ void run() { frameCount = 0; } } + cv::rectangle(*(ui->drawnFrame()), tracker.getROI(), cv::Scalar { 255, 0, 0 }, 2); - cv::rectangle(*(ui->drawnFrame()), largest, cv::Scalar { 255, 30, 30 }, 1); + break; } + ruler.update(); ui->render(); } diff --git a/src/webcam/Webcam.cpp b/src/webcam/Webcam.cpp index f6a8646..3d32ebe 100755 --- a/src/webcam/Webcam.cpp +++ b/src/webcam/Webcam.cpp @@ -9,6 +9,8 @@ Webcam::Webcam(int webcamID) { stream = new cv::VideoCapture(webcamID); + stream->set(cv::CAP_PROP_FRAME_WIDTH, 1920); + stream->set(cv::CAP_PROP_FRAME_HEIGHT, 1080); } void Webcam::update() {