ofx OpenCVExample

header -----------------------------

#pragma once

#include "ofMain.h"
// for ofxCvColorImage, ofxCvGrayImage, ofxCvContourFinder
#include "ofxOpenCv.h"

//#define _USE_LIVE_VIDEO        // uncomment this to use a live camera
                                // otherwise, we'll use a movie file

class ofApp : public ofBaseApp{

    public:
        // 예약 메써드
        void setup();
        void update();
        void draw();
       
        // 이벤트 핸들러
        void keyPressed(int key);
        void keyReleased(int key);
        void mouseMoved(int x, int y );
        void mouseDragged(int x, int y, int button);
        void mousePressed(int x, int y, int button);
        void mouseReleased(int x, int y, int button);
        void mouseEntered(int x, int y);
        void mouseExited(int x, int y);
        void windowResized(int w, int h);
        void dragEvent(ofDragInfo dragInfo);
        void gotMessage(ofMessage msg);       

        #ifdef _USE_LIVE_VIDEO
          ofVideoGrabber         vidGrabber;
        #else
          ofVideoPlayer         vidPlayer;
        #endif

        ofxCvColorImage            colorImg;

        // 그레이 이미지 클래스
        ofxCvGrayscaleImage     grayImage;
        ofxCvGrayscaleImage     grayBg;
        ofxCvGrayscaleImage     grayDiff;

        ofxCvContourFinder     contourFinder;

        int                 threshold;
        bool                bLearnBakground;
};

App ----------------------------------------------
#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){

    #ifdef _USE_LIVE_VIDEO
        vidGrabber.setVerbose(true);
        vidGrabber.setup(320,240);
    #else
        vidPlayer.load("fingers.mov");      // 비디오 파일 업로드
        vidPlayer.play();                   // 재생, 안보이게 자체적으로 돌아감.
        vidPlayer.setLoopState(OF_LOOP_NORMAL);     // 노멀 루프
    #endif

    // 이미지 크기
    colorImg.allocate(320,240);     // 칼라
    grayImage.allocate(320,240);    // 그레이
    grayBg.allocate(320,240);       // 배경
    grayDiff.allocate(320,240);     // 차영상
    // 상수들
    bLearnBakground = true;
    threshold = 80;
}

//--------------------------------------------------------------
void ofApp::update(){
    ofBackground(100,100,100);      // 배경 회색

    bool bNewFrame = false;         //

    #ifdef _USE_LIVE_VIDEO
       vidGrabber.update();         // 비디오 업데이트
       bNewFrame = vidGrabber.isFrameNew();     // 한 프레임 취득
    #else
        vidPlayer.update();         //
        bNewFrame = vidPlayer.isFrameNew();     //
    #endif

    if (bNewFrame){                 // 프레임이 있을때

        #ifdef _USE_LIVE_VIDEO
            colorImg.setFromPixels(vidGrabber.getPixels()); //
        #else
            colorImg.setFromPixels(vidPlayer.getPixels());  // 이미지에 표시
        #endif

        grayImage = colorImg;   // 그레이 영상 생성, 자동 그레이화.
        if (bLearnBakground == true){
            // 이미지 카피는 등호로 간단히.
            grayBg = grayImage;        // the = sign copys the pixels from grayImage into grayBg (operator overloading)
            bLearnBakground = false;
        }

        // take the abs value of the difference between background and incoming and then threshold:
        grayDiff.absDiff(grayBg, grayImage);    // 그레이 이미지에만 있는 차영상 메써드
        grayDiff.threshold(threshold);          // 그레이 이미지에만 있는 이진화 메써드

        // find contours which are between the size of 20 pixels and 1/3 the w*h pixels.
        // also, find holes is set to true so we will get interior contours as well....
        // 윤곽선 찾기.
        contourFinder.findContours(grayDiff, 20, (340*240)/3, 10, true, true);    // find holes
        // int ofxCvContourFinder::findContours( ofxCvGrayscaleImage&  input,
        //int minArea,
        //int maxArea,
        //int nConsidered,
        //bool bFindHoles,
        //bool bUseApproximation)
    }

}

//--------------------------------------------------------------
void ofApp::draw(){

    // draw the incoming, the grayscale, the bg and the thresholded difference
    ofSetHexColor(0xffffff);    // 헥사 컬러 지정, 백색.
    // 이미지들 위치에 그리기
    colorImg.draw(20,20);
    grayImage.draw(360,20);
    grayBg.draw(20,280);
    grayDiff.draw(360,280);

    // then draw the contours:

    ofFill();       //
    ofSetHexColor(0x333333);
    ofDrawRectangle(360,540,320,240);   // 윤곽선 묘사용 회색 박스
    ofSetHexColor(0xffffff);

    // we could draw the whole contour finder
    //contourFinder.draw(360,540);

    // or, instead we can draw each blob individually from the blobs vector,
    // this is how to get access to them:
    for (int i = 0; i < contourFinder.nBlobs; i++){
        contourFinder.blobs[i].draw(360,540);
       
        // draw over the centroid if the blob is a hole
        ofSetColor(255);
        if(contourFinder.blobs[i].hole){
            ofDrawBitmapString("hole",
                contourFinder.blobs[i].boundingRect.getCenter().x + 360,
                contourFinder.blobs[i].boundingRect.getCenter().y + 540);
        }
    }

    // finally, a report:
    ofSetHexColor(0xffffff);
    stringstream reportStr;     //문자열 스트림.
    // 고정 문자열 + 프레임레이트 취득 표시. << 로 연결. endl 로 개행.
    reportStr << "bg subtraction and blob detection" << endl
              << "press ' ' to capture bg" << endl
              << "threshold " << threshold << " (press: +/-)" << endl
              << "num blobs found " << contourFinder.nBlobs << ", fps: " << ofGetFrameRate();
    ofDrawBitmapString(reportStr.str(), 20, 600);   // 문자열 스트림을 문자열로 변환해 위치에 표시

}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

    switch (key){
        case ' ':
            bLearnBakground = true;
            break;
        case '+':
            threshold ++;
            if (threshold > 255) threshold = 255;
            break;
        case '-':
            threshold --;
            if (threshold < 0) threshold = 0;
            break;
    }
}

댓글

이 블로그의 인기 게시물

파이썬으로 Homomorphic Filtering 하기

파이썬으로 2D FFT/iFFT 하기: numpy 버전