前のブログ昼下がりの数式でもっともよくアクセスされたを転載します。
完全にopenFrameworks WikiのColorTrackingの頁の写経ですが、コメントをつけてます。
元ページ
http://wiki.openframeworks.cc/index.php?title=Color_Tracking(Color%20Tracking)
ヘッダファイル testApp.h
#ifndef _TEST_APP #define _TEST_APP #include "ofMain.h" #include "ofxVectorMath.h" #include "ofxOpenCv.h" //色の基本的な情報を持ったクラスを作ります。 class Color { public: float hue, sat, bri; ofxVec2f pos; }; class testApp : 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 windowResized(int w, int h); //カメラの映像を取得するためのオブジェクト ofVideoGrabber vidGrabber; //カメラの幅と高さ int camWidth; int camHeight; //もともとの映像情報 ofxCvColorImage colorImg; //HSV系に変換した映像情報 ofxCvColorImage colorImgHSV; //HSV系の色相、彩度、明度のマップ ofxCvGrayscaleImage hueImg; ofxCvGrayscaleImage satImg; ofxCvGrayscaleImage briImg; //色を追跡して輪郭を出すための映像情報 ofxCvGrayscaleImage reds; //追跡する色です。 Color one; //もとの映像情報のピクセルの彩度と明度が //指定した色に近ければ255を代入、遠ければ0を代入 unsigned char * colorTrackedPixelsRed; //二値画像 ofTexture trackedTextureRed; //輪郭を判別してくれるメチャクチャ便利なやつです。 ofxCvContourFinder finderRed; }; #endif
CPPファイル testApp.cpp
#include "testApp.h" //-------------------------------------------------------------- void testApp::setup(){ //最初は色が原点にあることにします one.pos = ofxVec2f(0,0); //カメラの大きさを指定 camWidth = 320; camHeight = 240; //それぞれの映像情報の大きさを指定してあげます。 colorImg.allocate(camWidth, camHeight); colorImgHSV.allocate(camWidth, camHeight); hueImg.allocate(camWidth, camHeight); satImg.allocate(camWidth, camHeight); briImg.allocate(camWidth, camHeight); reds.allocate(camWidth, camHeight); //二値画像を作るための配列の大きさを指定 colorTrackedPixelsRed =new unsigned char [camWidth*camHeight]; //二値画像の大きさ trackedTextureRed.allocate(camWidth, camHeight, GL_LUMINANCE); //Grabberの「何か」と大きさ設定 //setVerboseってなんだろ? Verbose:冗長な、言葉数の多い vidGrabber.setVerbose(true); vidGrabber.initGrabber(camWidth, camHeight); } //-------------------------------------------------------------- void testApp::update(){ //映像を取得! vidGrabber.grabFrame(); //colorImgの中身をピクセルごとに指定 colorImg.setFromPixels(vidGrabber.getPixels(), camWidth, camHeight); //HSV系に変換 colorImgHSV = colorImg; colorImgHSV.convertRgbToHsv(); //色相、彩度、明度にマッピング colorImgHSV.convertToGrayscalePlanarImages(hueImg, satImg, briImg); //ここが何やってんのか分からん。 hueImg.flagImageChanged(); satImg.flagImageChanged(); briImg.flagImageChanged(); //ピクセルの配列をそれぞれに作成 unsigned char * huePixels = hueImg.getPixels(); unsigned char * satPixels = satImg.getPixels(); unsigned char * briPixels = briImg.getPixels(); //ピクセルの数 int nPixels = camWidth*camHeight; //ピクセルの色が指定した色と色相と彩度が近ければ、 //colorTrackedPixelsRedに255を、遠ければ0を代入。 for (int i=0; i < nPixels; i++) { if ( (huePixels[i] >=one.hue-12 && huePixels[i] <= one.hue + 12) && (satPixels[i] >=one.sat-24 && satPixels[i] <=one.sat+200)){ colorTrackedPixelsRed[i] = 255; }else { colorTrackedPixelsRed[i]=0; } } //colorTrackedPixelsRedをもとにredsを作成 //redsは輪郭線を求めるためだけにあるのかな? reds.setFromPixels(colorTrackedPixelsRed, camWidth, camHeight); //輪郭線を見つける finderRed.findContours(reds, 10, nPixels/3, 1, false, true); //colorTrackedPixelsRedをもとにtrackedTextureRedを作成 //これが二値画像になってるっぽい trackedTextureRed.loadData(colorTrackedPixelsRed, camWidth, camHeight, GL_LUMINANCE); //追跡する色の位置を中心にあわせる if (finderRed.blobs.size() > 0) { one.pos = ofxVec2f(finderRed.blobs[0].centroid.x, finderRed.blobs[0].centroid.y); } } //-------------------------------------------------------------- void testApp::draw(){ //背景色を指定 ofBackground(100, 100, 100); ofSetColor(0xffffff); //元映像を表示 vidGrabber.draw(0, 0); //HSV系に変換したものを表示 colorImgHSV.draw(340, 0); //二値画像を表示 trackedTextureRed.draw(20, 300); ofDrawBitmapString("red", 20, 280); //元映像に輪郭線を表示 finderRed.draw(); //二値画像の方に輪郭線表示 glPushMatrix(); glTranslatef(20, 300, 0); finderRed.draw(); glPopMatrix(); //追跡する色の位置を表示 if (finderRed.blobs.size() > 0) { char tempStr1[255]; sprintf(tempStr1, "x:%fny:%f", finderRed.blobs[0].centroid.x, finderRed.blobs[0].centroid.y); ofDrawBitmapString(tempStr1, 20, 250); } } //-------------------------------------------------------------- void testApp::mousePressed(int x, int y, int button){ unsigned char * huePixels = hueImg.getPixels(); unsigned char * satPixels = satImg.getPixels(); unsigned char * briPixels = briImg.getPixels(); //クリックした場所の色を追跡する色に設定。 x=MIN(x,hueImg.width-1); y=MIN(y,hueImg.height-1); if (button==0) { one.hue = huePixels[x+(y*hueImg.width)]; one.sat = satPixels[x+(y*satImg.width)]; one.bri = briPixels[x+(y*briImg.width)]; } }
これで、色の追跡ができています。
[…] 前、掲載したColorTrackingの記事と組み合わせるには、colorTrackedPixelsRedがここでいうbinaryImgPixelsに対応します。 […]