So I am still working on my multicam project. I have almost finished the tracking with ofxCv, which is truly incredible. However, I am becoming frustrated by the draw() function for the contourFinder. As I have multiple cameras I am scaling them so that they all fit on the screen. I have been able to scale all of the actual tracking elements, except for the contourFinder.draw() function, which continues to draw at the full 1920x1080 frame size. Does anybody have any tips for quickly scaling down the output of draw for the contours and their rects? I have looked all over and haven't found a solution yet. I am currently experimenting with the example for ofxCv_contoursAdvanced:
All i've done so far that works is add a scale variable that allows me to scale down the tracked outputs.
#include "ofApp.h"
using namespace ofxCv;
using namespace cv;
void ofApp::setup() {
camWidth = 1920;
camHeight = 1080;
ofSetVerticalSync(false);
ofSetFrameRate(120);
cam.setDeviceID(0);
cam.setDesiredFrameRate(15);
cam.initGrabber(camWidth,camHeight);
cam.setUseTexture(true);
contourFinder.setMinAreaRadius(10);
contourFinder.setMaxAreaRadius(150);
//contourFinder.setInvert(true); // find black instead of white
trackingColorMode = TRACK_COLOR_RGB;
scale = 2.0;
}
void ofApp::update() {
cam.update();
if(cam.isFrameNew()) {
threshold = ofMap(mouseX, 0, ofGetWidth()/scale, 0, 255);
contourFinder.setThreshold(threshold);
contourFinder.findContours(cam);
}
}
void ofApp::draw() {
ofSetColor(255);
cam.draw(0, 0, cam.width/scale, cam.height/scale);
ofSetLineWidth(2);
contourFinder.draw();
ofNoFill();
int n = contourFinder.size();
for(int i = 0; i < n; i++) {
// smallest rectangle that fits the contour
ofSetColor(cyanPrint);
ofPolyline minAreRect = toOf(contourFinder.getMinAreaRect(i));
minAreRect.resize(1/scale);
minAreRect.draw();
// ellipse that best fits the contour
ofSetColor(magentaPrint);
cv::RotatedRect ellipse = contourFinder.getFitEllipse(i);
ofPushMatrix();
ofVec2f ellipseCenter = toOf(ellipse.center);
ofVec2f ellipseSize = toOf(ellipse.size);
ofTranslate(ellipseCenter.x/scale, ellipseCenter.y/scale);
ofRotate(ellipse.angle);
ofEllipse(0, 0, ellipseSize.x/scale, ellipseSize.y/scale);
ofPopMatrix();
// minimum area circle that encloses the contour
ofSetColor(cyanPrint);
float circleRadius;
ofVec2f circleCenter = toOf(contourFinder.getMinEnclosingCircle(i, circleRadius));
ofCircle(circleCenter/scale, circleRadius/scale);
// convex hull of the contour
ofSetColor(yellowPrint);
ofPolyline convexHull = toOf(contourFinder.getConvexHull(i));
convexHull.resize(1/scale);
convexHull.draw();
// defects of the convex hull
vector<cv::Vec4i> defects = contourFinder.getConvexityDefects(i);
for(int j = 0; j < defects.size(); j++) {
ofLine(defects[j][0]/scale, defects[j][1]/scale, defects[j][2]/scale, defects[j][3]/scale);
}
// some different styles of contour centers
ofVec2f centroid = toOf(contourFinder.getCentroid(i));
ofVec2f average = toOf(contourFinder.getAverage(i));
ofVec2f center = toOf(contourFinder.getCenter(i));
ofSetColor(cyanPrint);
ofCircle(centroid/scale, 1/scale);
ofSetColor(magentaPrint);
ofCircle(average/scale, 1/scale);
ofSetColor(yellowPrint);
ofCircle(center/scale, 1/scale);
// you can also get the area and perimeter using ofPolyline:
// ofPolyline::getArea() and ofPolyline::getPerimeter()
double area = contourFinder.getContourArea(i)/scale;
double length = contourFinder.getArcLength(i)/scale;
// balance is useful for detecting when a shape has an "arm" sticking out
// if balance.length() is small, the shape is more symmetric: like I, O, X...
// if balance.length() is large, the shape is less symmetric: like L, P, F...
ofVec2f balance = toOf(contourFinder.getBalance(i));
ofPushMatrix();
ofTranslate(centroid.x/scale, centroid.y/scale);
ofScale(5/scale, 5/scale);
ofLine(0, 0, balance.x/scale, balance.y/scale);
ofPopMatrix();
}
ofSetColor(255);
drawHighlightString(ofToString((int) ofGetFrameRate()) + " fps", 10, 10);
drawHighlightString(ofToString((int) threshold) + " threshold", 10, 30);
drawHighlightString(trackingColorMode == TRACK_COLOR_RGB ? "RGB tracking" : "hue tracking", 10, 50);
ofTranslate(8/scale, 75/scale);
ofFill();
ofSetColor(0);
ofRect(-3/scale, -3/scale, (64+6)/scale, (64+6)/scale);
ofSetColor(targetColor);
ofRect(0, 0, 64/scale, 64/scale);
}
void ofApp::mousePressed(int x, int y, int button) {
targetColor = cam.getPixelsRef().getColor(x/scale, y/scale);
contourFinder.setTargetColor(targetColor, trackingColorMode);
}
void ofApp::keyPressed(int key) {
if(key == 'h') {
trackingColorMode = TRACK_COLOR_HS;
}
if(key == 'r') {
trackingColorMode = TRACK_COLOR_RGB;
}
contourFinder.setTargetColor(targetColor, trackingColorMode);
}
Any help is greatly appreciated.