Last active
December 21, 2015 13:49
-
-
Save joshuajnoble/6315618 to your computer and use it in GitHub Desktop.
Using Background subtraction in Cinder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "cinder/app/AppBasic.h" | |
#include "cinder/gl/gl.h" | |
#include "cinder/gl/Texture.h" | |
#include "cinder/Capture.h" | |
#include "CinderOpenCV.h" | |
using namespace ci; | |
using namespace ci::app; | |
using namespace std; | |
class bgSubtractApp : public AppBasic { | |
public: | |
void setup(); | |
void keyDown(KeyEvent key); | |
void update(); | |
void draw(); | |
cv::BackgroundSubtractorMOG bgsubtractor; | |
vector< vector<cv::Point> > mContours; | |
vector<PolyLine2f> mContourLine; | |
bool mUpdateBackground; | |
Capture mCapture; | |
Surface mCaptureSurf; | |
gl::Texture mForegroundTexture, mBackgroundTexture; | |
int mDrawMode; | |
}; | |
void bgSubtractApp::setup() | |
{ | |
mDrawMode = 0; | |
// we want to start with the background updating | |
mUpdateBackground = true; | |
// make some textures to draw into | |
gl::Texture::Format fmt; | |
mForegroundTexture = gl::Texture(640, 480, fmt); | |
mBackgroundTexture = gl::Texture(640, 480, fmt); | |
mCapture = Capture(640, 480); | |
mCapture.start(); | |
} | |
void bgSubtractApp::keyDown(KeyEvent key) { | |
mDrawMode++; | |
if(mDrawMode > 2) { | |
mDrawMode = 0; | |
} | |
} | |
void bgSubtractApp::update() | |
{ | |
if(mCapture.checkNewFrame()) { | |
if(getElapsedFrames() % 120 == 0) { // only do this only every 4 secs or so | |
mUpdateBackground = true; | |
} | |
mCaptureSurf = mCapture.getSurface(); | |
cv::Mat working, newFrame, fgFrame; | |
newFrame = toOcv( mCaptureSurf ); // capture the frame | |
// case you're wondering, this is overloaded (), not a constructor call | |
bgsubtractor(newFrame, fgFrame, mUpdateBackground ? 1 : 0); | |
mUpdateBackground = false; | |
int numberOfIters = 3; | |
vector<cv::Vec4i> hierarchy; | |
cv::dilate(fgFrame, working, cv::Mat(), cv::Point(-1,-1), numberOfIters); | |
cv::erode(working, working, cv::Mat(), cv::Point(-1,-1), numberOfIters * 2); | |
cv::dilate(working, working, cv::Mat(), cv::Point(-1,-1), numberOfIters); | |
mContours.clear(); | |
// get all the contours now | |
cv::findContours( working, mContours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE ); | |
// now copy them into a | |
mContourLine.clear(); | |
for( int i = 0; i < mContours.size(); i++) { | |
mContourLine.push_back(PolyLine2f()); | |
for( int j = 0; j < mContours[i].size(); j++) { | |
mContourLine.at(i).push_back(Vec2f(mContours[i][j].x, mContours[i][j].y) ); | |
} | |
} | |
if( mContours.size() == 0 ) | |
return; | |
// we're going to ^ the mask | |
cv::Mat filledFG, filledBG; | |
filledBG = cv::Mat::zeros(fgFrame.size(), CV_32F); | |
filledFG = cv::Mat::zeros(fgFrame.size(), CV_32F); | |
// get the foreground | |
newFrame.copyTo(filledFG, fgFrame); | |
// now get the background | |
newFrame.copyTo(filledBG, 255 - fgFrame); | |
mBackgroundTexture.update( Surface(fromOcv(filledBG) )); | |
mForegroundTexture.update( Surface(fromOcv(filledFG) )); | |
} | |
} | |
void bgSubtractApp::draw() | |
{ | |
// clear out the window with black | |
gl::clear( Color( 0, 0, 0 ) ); | |
switch (mDrawMode) { | |
case 0: | |
if(mBackgroundTexture) | |
gl::draw(mBackgroundTexture); | |
break; | |
case 1: | |
if(mForegroundTexture) | |
gl::draw(mForegroundTexture); | |
break; | |
case 2: | |
for( int i = 0; i < mContourLine.size(); i++) { | |
gl::draw(mContourLine.at(i)); | |
} | |
break; | |
} | |
} | |
CINDER_APP_BASIC( bgSubtractApp, RendererGl ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment