From 3ffa0ac381e23484181b0d5f4a06964407214a6f Mon Sep 17 00:00:00 2001 From: Mario Fleischmann Date: Thu, 6 May 2021 09:48:06 +0200 Subject: [PATCH] Implemented Contour Finding Before contours can be found, video is converted to grayscale, background subtraction is performed and results get binarized. Circles are characterized by the aspect ratio of the individual blob. --- beerpong/bin/data/README.txt | 3 ++ beerpong/src/ofApp.cpp | 73 +++++++++++++++++++++++++++++++++++- beerpong/src/ofApp.h | 14 +++++++ 3 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 beerpong/bin/data/README.txt diff --git a/beerpong/bin/data/README.txt b/beerpong/bin/data/README.txt new file mode 100644 index 0000000..951150a --- /dev/null +++ b/beerpong/bin/data/README.txt @@ -0,0 +1,3 @@ +Video mit FFMPEG verkleinern: + +ffmpeg -i beer.mkv -s 568x320 -c:a copy shrink.mkv \ No newline at end of file diff --git a/beerpong/src/ofApp.cpp b/beerpong/src/ofApp.cpp index 0d3236e..cafcf4e 100644 --- a/beerpong/src/ofApp.cpp +++ b/beerpong/src/ofApp.cpp @@ -1,23 +1,94 @@ #include "ofApp.h" +#define VIDEO_WIDTH 568 +#define VIDEO_HEIGHT 320 + //-------------------------------------------------------------- void ofApp::setup(){ + vidPlayer.load("beer.mkv"); // in /bin/data/ + vidPlayer.play(); + vidPlayer.setLoopState(OF_LOOP_NORMAL); + colorVideo.allocate(VIDEO_WIDTH, VIDEO_HEIGHT); + grayVideo.allocate(VIDEO_WIDTH, VIDEO_HEIGHT); + + learnBackground = true; + threshhold = 80; } //-------------------------------------------------------------- void ofApp::update(){ + vidPlayer.update(); + colorVideo.setFromPixels(vidPlayer.getPixels()); + + grayVideo = colorVideo; // Convert Color to Grayscale + + if (learnBackground){ + background = grayVideo; + learnBackground = false; + } + + // Background subtraction + binarized.absDiff(background, grayVideo); + // Binarization + binarized.threshold(threshhold); + + contourFinder.findContours( + binarized, + 10, + VIDEO_HEIGHT * VIDEO_WIDTH / 10, + 10, + true); } //-------------------------------------------------------------- void ofApp::draw(){ + ofSetHexColor(0xffffff); + colorVideo.draw(20, 20); + grayVideo.draw(40 + VIDEO_WIDTH, 20); + background.draw(20, 40 + VIDEO_HEIGHT); + binarized.draw(40 + VIDEO_WIDTH, 40 + VIDEO_HEIGHT); + ofFill(); + ofSetHexColor(0x333333); + ofDrawRectangle(40 + VIDEO_WIDTH, 60 + VIDEO_HEIGHT + VIDEO_HEIGHT, VIDEO_WIDTH, VIDEO_HEIGHT); + ofSetHexColor(0xffffff); + + for (int i = 0; i < contourFinder.blobs.size(); i++) { + ofxCvBlob blob = contourFinder.blobs[i]; + + + // draw over the centroid if the blob is a hole + ofSetColor(255); + + // https://docs.opencv.org/master/d1/d32/tutorial_py_contour_properties.html + float aspect_ratio = blob.boundingRect.getWidth() / blob.boundingRect.getHeight(); + + stringstream sizeStr; + sizeStr << std::to_string(i) << ": " << std::to_string(contourFinder.blobs[i].area); + sizeStr << " | F=" << aspect_ratio; + + + if (aspect_ratio > 0.5 && aspect_ratio < 1.5) + { + blob.draw(40 + VIDEO_WIDTH, 60 + VIDEO_HEIGHT + VIDEO_HEIGHT); + ofDrawBitmapString(sizeStr.str(), + contourFinder.blobs[i].boundingRect.getCenter().x + 40 + VIDEO_WIDTH, + contourFinder.blobs[i].boundingRect.getCenter().y + 60 + VIDEO_HEIGHT + VIDEO_HEIGHT); + } + } } //-------------------------------------------------------------- void ofApp::keyPressed(int key){ - + if (key == '-') threshhold--; + else if (key == '+') threshhold++; + else if (key == ' ') learnBackground = true; + else if (key == '0') vidPlayer.setPaused(!vidPlayer.isPaused()); + else if (key == OF_KEY_RIGHT) vidPlayer.nextFrame(); + else if (key == OF_KEY_LEFT) vidPlayer.previousFrame(); + else; } //-------------------------------------------------------------- diff --git a/beerpong/src/ofApp.h b/beerpong/src/ofApp.h index a9a1eea..ce594b9 100644 --- a/beerpong/src/ofApp.h +++ b/beerpong/src/ofApp.h @@ -1,6 +1,7 @@ #pragma once #include "ofMain.h" +#include "ofxOpenCv.h" class ofApp : public ofBaseApp{ @@ -21,4 +22,17 @@ class ofApp : public ofBaseApp{ void dragEvent(ofDragInfo dragInfo); void gotMessage(ofMessage msg); + ofVideoPlayer vidPlayer; + + // Images displaying original video + ofxCvColorImage colorVideo; + ofxCvGrayscaleImage grayVideo; + + ofxCvGrayscaleImage background; + ofxCvGrayscaleImage binarized; + + ofxCvContourFinder contourFinder; + + bool learnBackground; + int threshhold; };