LoginSignup
4
1

More than 5 years have passed since last update.

【openFrameworks】アドオンofxOpenCvの ofxCvContourFinderで抽出した輪郭に線をかく。

Last updated at Posted at 2017-11-16

前回までofxOpenCvを色々いじってきましたが、
とりあえず第1章のシメとして、輪郭に線を引きたかったのです。
こんな感じ。こんくらいの精度で良いのかなぁ??

前回まで
http://www.sudara-bluse.tokyo/entry/openframeworks_11

処理内容

カメラから映像をキャプチャー

グレースケールに変換

スペースキーで背景画像を登録

背景画像と現在の画像の差分を求める(grayDiff)

差分の画像を2値化(grayDiff.threshold())

2値化した画像から輪郭を抽出

発見した輪郭の点を結んで線を描く

ofApp.h

#pragma once

#include "ofMain.h"
#include "ofxOpenCv.h"

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);

    // カメラ
    ofVideoGrabber cam;

    // カメラから入った1フレーム分の画像
    ofxCvColorImage colorImg;

    // カメラから入った1フレーム分のグレースケールの画像
    ofxCvGrayscaleImage grayImg;

    // グレースケール画像で背景用と差分
    ofxCvGrayscaleImage grayBase;
    ofxCvGrayscaleImage grayDiff;

    // フレームを保存したかどうかのフラグ
    bool isSave;

    // 輪郭検出用
    ofxCvContourFinder contourFinder;

    // しきい値
    int threshold;

    // 輪郭線を格納する動的配列
    vector <ofPolyline> edgeLines;


};


ofApp.cpp

#include "ofApp.h"


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

    // 背景を黒に
    ofBackground(0, 0, 0);


    /* 今回は1024*768です! */
    // カメラからの取り込み
    cam.initGrabber(640, 480);

    // それぞれを処理するメモリ領域を確保   allocate(割り当てる)
    colorImg.allocate(640, 480);
    grayImg.allocate(640, 480);
    grayBase.allocate(640, 480);
    grayDiff.allocate(640, 480);

    // フラグ初期化
    isSave = true;

    threshold = 80;

}

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

    // カメラの更新
    cam.update();

    // 一個一個のピクセルデータをカラーイメージにほりこんでる
    colorImg.setFromPixels(cam.getPixels().getData(), 640, 480);
    colorImg.mirror(false, true);

    // グレースケールイメージにカラーデータを入れる
    grayImg = colorImg;

    // スペースキー押した時に、元画像に現在のグレーイメージを入れる
    if(isSave == true){
        grayBase = grayImg;
        isSave = false;
    }
    // 白黒画像と動体検知のベースとなる画像の差を求める
    grayDiff.absDiff(grayBase, grayImg);

    // 二値化 (白黒はっきりさせる)
    grayDiff.threshold(threshold);


    // 輪郭を描く
    // 第1引数 輪郭検出対象
    // 第2引数 検出する最小の大きさ(20)
    // 第3引数 検出する最大の大きさ
    // 第4引数 検出する数
    // 第5引数 穴が空いたものを検出するかどうか trueで 検出する
    contourFinder.findContours(grayDiff, 20, (640*480)/3, 10, true);



    // 動的配列をクリアする
    edgeLines.clear();

    //-----------------------------------------
    // 輪郭線の座標を結んで線にする
    //-----------------------------------------

    // 1周目for文で複数の輪郭にアクセス
    for(int i = 0; i< contourFinder.nBlobs; i++){
        ofPolyline line;
        // 2周目for文でそれぞれの輪郭の点にアクセスし、点を結んで線にする。
        for(int j =0; j<contourFinder.blobs[i].pts.size(); j++){
            // 点を線にする。
            line.addVertex(contourFinder.blobs[i].pts[j]);
        }
        // 作成した線を格納
        edgeLines.push_back(line);
    }
}

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

    // カラー画像の描画
    ofSetColor(255, 255, 255);
    colorImg.draw(0,0, 640, 480);

    // 境界線のサイズと色指定
    ofSetLineWidth(5);
    ofSetColor(255, 255, 0);
    // 輪郭線の描画
    for(int cnt = 0; cnt< edgeLines.size(); cnt++){
        edgeLines[cnt].draw();
    }


}

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

    switch (key){
        case ' ':
            isSave = true;   // スペースキーを押す事によってフレームを保存
            break;
        case '+':
            threshold ++;     //しきい値を上げる
            if (threshold > 255) threshold = 255;
            break;
        case '-':
            threshold --;     //しきい値を下げる
            if (threshold < 0) threshold = 0;
            break;
    }

}


4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1