Skip to content

Commit

Permalink
Merge pull request #23 from brainmachine/detection
Browse files Browse the repository at this point in the history
Detection
  • Loading branch information
brainmachine authored Aug 23, 2017
2 parents c7aeef2 + bba6320 commit 5e0d2b3
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 101 deletions.
6 changes: 3 additions & 3 deletions addons.make
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ofxGui
ofxNetwork
ofxOpenCv
ofxCv
ofxEditableSVG
ofxGui
ofxJSON
ofxNetwork
ofxOPC
ofxOpenCv
212 changes: 117 additions & 95 deletions src/ofApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

//--------------------------------------------------------------
void ofApp::setup(){
ofSetFrameRate(30);
int framerate = 5; // Used to set oF and camera framerate
ofSetFrameRate(framerate);

// Input
cam.listDevices();
cam.setDeviceID(1); // External webcam
cam.setup(640, 480);

cam.setDesiredFrameRate(framerate); // This gets overridden by ofSetFrameRate

// GUI
gui.setup();
Expand All @@ -20,28 +21,31 @@ void ofApp::setup(){
contourFinder.setMinAreaRadius(1);
contourFinder.setMaxAreaRadius(100);
contourFinder.setThreshold(15);
// wait for half a frame before forgetting something
contourFinder.getTracker().setPersistence(15);
// wait for half a frame before forgetting something (15)
contourFinder.getTracker().setPersistence(1);
// an object can move up to 32 pixels per frame
contourFinder.getTracker().setMaximumDistance(32);
contourFinder.getTracker().setSmoothingRate(1.0);

showLabels = true;

// LED

ledIndex = 0;
numLeds = 50;
ledBrightness = 100;
ledBrightness = 200;
isMapping = false;
isTesting = false;
isLedOn = false; // Prevent sending multiple ON messages

// Set up the color vector, with all LEDs set to off(black)
pixels.assign(numLeds, ofColor(0,0,0));
setAllLEDColours(ofColor(0, 0,0));


// Connect to the fcserver
opcClient.setup("192.168.1.104", 7890);
// opcClient.setup("127.0.0.1", 7890);
opcClient.sendFirmwareConfigPacket();
setAllLEDColours(ofColor(0, 0,0));

// SVG
svg.setViewbox(0, 0, 640, 480);
Expand All @@ -66,11 +70,13 @@ void ofApp::update(){
background.reset();
resetBackground = false;
}
if(cam.isFrameNew() && isTesting==false) {

if (isMapping && !isLedOn) {
chaseAnimationOn();
}
if(cam.isFrameNew() && !isTesting && isMapping) {
// Light up a new LED for every frame
if (isMapping) {
chaseAnimation();
}
bool success = false; // Indicate if we successfully mapped an LED on this frame
// Background subtraction
background.setLearningTime(learningTime);
background.setThresholdValue(thresholdValue);
Expand All @@ -80,9 +86,64 @@ void ofApp::update(){
// Contour
ofxCv::blur(thresholded, 10);
contourFinder.findContours(thresholded);
// TODO: Turn off LED here

// We have 1 contour
if (contourFinder.size() == 1 && isLedOn) {
// ofLogNotice("Detected one contour, as expected.");
ofPoint center = ofxCv::toOf(contourFinder.getCenter(0));
centroids.push_back(center);
success = true;
ofLogNotice("added point (only found 1)");
}
// We have more than 1 contour, select the brightest one.

else if (contourFinder.size() > 1 && isLedOn){
//ofLogNotice("num contours: " + ofToString(contourFinder.size()));
int brightestIndex = 0;
int previousBrightness = 0;
for(int i = 0; i < contourFinder.size(); i++) {
int brightness = 0;
cv::Rect rect = contourFinder.getBoundingRect(i);
//ofLogNotice("x:" + ofToString(rect.x)+" y:"+ ofToString(rect.y)+" w:" + ofToString(rect.width) + " h:"+ ofToString(rect.height));
ofImage img;
img = thresholded;
img.crop(rect.x, rect.y, rect.width, rect.height);
ofPixels pixels = img.getPixels();

for (int i = 0; i< pixels.size(); i++) {
brightness += pixels[i];
}
brightness /= pixels.size();

// Check if the brightness is greater than the previous contour brightness
if (brightness > previousBrightness) {
brightestIndex = i;
}
previousBrightness = brightness;

//ofLogNotice("Brightness: " + ofToString(brightness));
}
//ofLogNotice("brightest index: " + ofToString(brightestIndex));
ofPoint center = ofxCv::toOf(contourFinder.getCenter(brightestIndex));
centroids.push_back(center);
success = true;
ofLogNotice("added point, ignored additional points");
}
// Deal with no contours found

else if (isMapping && !success && isLedOn){
// This doesn't care if we're trying to find a contour or not, it goes in here by default
ofLogNotice("NO CONTOUR FOUND!!!");
//chaseAnimationOn();
}

if(isMapping && success) {
chaseAnimationOff();
}
}

ofSetColor(ofColor::white);
}

//--------------------------------------------------------------
Expand All @@ -93,78 +154,19 @@ void ofApp::draw(){
}
gui.draw();

ofSetBackgroundAuto(showLabels);
ofxCv::RectTracker& tracker = contourFinder.getTracker();

if(showLabels) {
ofSetColor(255);
//movie.draw(0, 0);
contourFinder.draw();
for(int i = 0; i < contourFinder.size(); i++) {
ofPoint center = ofxCv::toOf(contourFinder.getCenter(i));
// Store centroids for drawing/saving
centroids.push_back(center);
ofPushMatrix();
ofTranslate(center.x, center.y);
int label = contourFinder.getLabel(i);
string msg = ofToString(label) + ":" + ofToString(tracker.getAge(label));
ofDrawBitmapString(msg, 0, 0);
ofVec2f velocity = ofxCv::toOf(contourFinder.getVelocity(i));
ofScale(5, 5);
ofDrawLine(0, 0, velocity.x, velocity.y);
ofPopMatrix();


}
} else {
for(int i = 0; i < contourFinder.size(); i++) {
unsigned int label = contourFinder.getLabel(i);
// only draw a line if this is not a new label
if(tracker.existsPrevious(label)) {
// use the label to pick a random color
ofSeedRandom(label << 24);
ofSetColor(ofColor::fromHsb(ofRandom(255), 255, 255));
// get the tracked object (cv::Rect) at current and previous position
const cv::Rect& previous = tracker.getPrevious(label);
const cv::Rect& current = tracker.getCurrent(label);
// get the centers of the rectangles
ofVec2f previousPosition(previous.x + previous.width / 2, previous.y + previous.height / 2);
ofVec2f currentPosition(current.x + current.width / 2, current.y + current.height / 2);
ofDrawLine(previousPosition, currentPosition);
}
}
}
ofSetColor(0, 255, 0);
//movie.draw(0, 0);
contourFinder.draw(); // Draws the blob rect surrounding the contour

// Draw the detected contour center points
for (int i = 0; i < centroids.size(); i++) {
ofDrawCircle(centroids[i].x, centroids[i].y, 3);
}

// this chunk of code visualizes the creation and destruction of labels
const vector<unsigned int>& currentLabels = tracker.getCurrentLabels();
const vector<unsigned int>& previousLabels = tracker.getPreviousLabels();
const vector<unsigned int>& newLabels = tracker.getNewLabels();
const vector<unsigned int>& deadLabels = tracker.getDeadLabels();
ofSetColor(ofxCv::cyanPrint);
for(int i = 0; i < currentLabels.size(); i++) {
int j = currentLabels[i];
ofDrawLine(j, 0, j, 4);
}
ofSetColor(ofxCv::magentaPrint);
for(int i = 0; i < previousLabels.size(); i++) {
int j = previousLabels[i];
ofDrawLine(j, 4, j, 8);
}
ofSetColor(ofxCv::yellowPrint);
for(int i = 0; i < newLabels.size(); i++) {
int j = newLabels[i];
ofDrawLine(j, 8, j, 12);
}
ofSetColor(ofColor::white);
for(int i = 0; i < deadLabels.size(); i++) {
int j = deadLabels[i];
ofDrawLine(j, 12, j, 16);
}


// if (isMapping) {
// ofSaveFrame();
// }
}

//--------------------------------------------------------------
Expand All @@ -190,11 +192,15 @@ void ofApp::keyPressed(int key){
break;
case 'g':
generateSVG(centroids);
break;
case 'j':
generateJSON(centroids);
break;
case 't':
isTesting = true;
break;
case 'f': // filter points
centroids = removeDuplicatesFromPoints(centroids);
}

}
Expand Down Expand Up @@ -250,18 +256,15 @@ void ofApp::dragEvent(ofDragInfo dragInfo){
}

// Cycle through all LEDs, return false when done
void ofApp::chaseAnimation()
void ofApp::chaseAnimationOn()
{
ofLogNotice("animation: ON");
// Chase animation
for (int i = 0; i < numLeds; i++) {
ofColor col;
if (i == ledIndex) {
col = ofColor(ledBrightness, ledBrightness, ledBrightness);
}
// wait a bit if this is the last LED
//else if (i == numLeds) {

//}
else {
col = ofColor(0, 0, 0);
}
Expand All @@ -270,14 +273,21 @@ void ofApp::chaseAnimation()

opcClient.writeChannel(1, pixels);

isLedOn = true;
}

void ofApp::chaseAnimationOff()
{
ofLogNotice("animation: OFF");

ledIndex++;
if (ledIndex >= numLeds) {
if (ledIndex > numLeds) {
ledIndex = 0;
setAllLEDColours(ofColor(0, 0, 0));
isMapping = false;
}
isLedOn = false;
}

// Set all LEDs to the same colour (useful to turn them all on or off).
void ofApp::setAllLEDColours(ofColor col) {
for (int i = 0; i < numLeds; i++) {
Expand Down Expand Up @@ -312,17 +322,10 @@ void ofApp::generateSVG(vector <ofPoint> points) {
}
svg.addPath(path);
path.draw();
svg.save("mapper-test-new.svg");
svg.save("mapper-test-tilted.svg");
}

void ofApp::generateJSON(vector<ofPoint> points) {
/*
[
{"point": [1.32, 0.00, 1.32]},
{"point": [1.32, 0.00, 1.21]}
]
*/

int maxX = ofToInt(svg.info.width);
int maxY = ofToInt(svg.info.height);
cout << maxX;
Expand All @@ -341,5 +344,24 @@ void ofApp::generateJSON(vector<ofPoint> points) {
}

json.save("testLayout.json");
}

vector <ofPoint> ofApp::removeDuplicatesFromPoints(vector <ofPoint> points) {

vector <ofPoint> filtered;

float thresh = 5.0;
for (int i = 0; i < points.size(); i++) {
float dist = points[i].distance(points[i-1]);
ofLogNotice("distance: "+ofToString(dist));
if (dist > thresh) {
filtered.push_back(points[i]);
}
else {
ofLogNotice("distance below threshold, removing point. distance: " + ofToString(dist));
}

}

return filtered;
}
8 changes: 5 additions & 3 deletions src/ofApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ class ofApp : public ofBaseApp{
void dragEvent(ofDragInfo dragInfo);
void gotMessage(ofMessage msg);

void chaseAnimation();
void chaseAnimationOn();
void chaseAnimationOff();
void test();
void setAllLEDColours(ofColor col);
void generateSVG(vector <ofPoint> points);
void generateJSON(vector <ofPoint> points);
vector <ofPoint> removeDuplicatesFromPoints(vector <ofPoint> points);

// OPC
ofxOPC opcClient;
Expand All @@ -43,6 +45,8 @@ class ofApp : public ofBaseApp{
bool isTesting;
int ledBrightness;

bool isLedOn;

// Input
ofVideoGrabber cam;

Expand All @@ -58,11 +62,9 @@ class ofApp : public ofBaseApp{
// Contours
float threshold;
ofxCv::ContourFinder contourFinder;
bool showLabels;
vector <ofPoint> centroids;

// SVG
ofxEditableSVG svg;


};

0 comments on commit 5e0d2b3

Please sign in to comment.