サクッと導入したOpenCVですが、openFrameworksと連携できなければ意味がありません。OpenCVでは、cv::Matクラスを使うのでopenFrameworksのデータと、このcv::Matの変換は必須です。
と言っても、非常に簡単で、openFrameworksのofVideoGrabberで取得したカメラ入力をcv::Matにコンバート、cv::Matで色変換、結果をopenFrameworksで描画するコードは、こんな感じです。
ofApp.h
class ofApp : public ofxiOSApp { // (中略) // Grabber ofVideoGrabber grabber; ofTexture tex; unsigned char * pix; };
ofApp.mm
#include "ofApp.h" #ifdef __cplusplus #include <opencv2/opencv.hpp> #endif //-------------------------------------------------------------- void ofApp::setup(){ ofSetOrientation(OF_ORIENTATION_90_RIGHT); ofSetFrameRate(30); // ofVideoGrabberを初期化する grabber.initGrabber(320, 568, OF_PIXELS_BGRA); // テクスチャを確保 tex.allocate(grabber.getWidth(), grabber.getHeight(), GL_RGB); // バッファを確保 pix = new unsigned char [ (int)(grabber.getWidth() * grabber.getHeight() * 3.0)]; } //-------------------------------------------------------------- void ofApp::update(){ // カメラからの入力の取得と検出処理 // カメラ入力を取得 grabber.update(); // cv::Mat形式に変換(OpenCVはBGR配列が標準) cv::Mat cvColor = cv::Mat(grabber.getWidth(), grabber.getHeight(), CV_8UC3, grabber.getPixels()); // 色変換 cv::Mat grayColor; cv::cvtColor(cvColor, grayColor, CV_BGR2GRAY); cv::Mat binColor; // 2値化 cv::threshold(grayColor, binColor, 128, 255, cv::THRESH_BINARY); int totalPixel = grabber.getWidth() * grabber.getHeight(); for (int i = 0; i < totalPixel; i++) { pix[3*i+0] = binColor.data[i]; pix[3*i+1] = binColor.data[i]; pix[3*i+2] = binColor.data[i]; } // 結果を表示 tex.loadData(pix, grabber.getWidth(), grabber.getHeight(), GL_RGB); } //-------------------------------------------------------------- void ofApp::draw(){ // カメラからの入力を描画 grabber.draw(0, 0); // 結果のテクスチャを描画 tex.draw(0, 0, tex.getWidth() / 2, tex.getHeight() / 2); }
実行結果
ofVideoGrabberのピクセルデータをフォーマットで渡すだけです。
cv::MatからofTextureへの変換もフォーマット指定で渡すだけ。なんですが、グレースケールにした後、ofTextureへうまく戻せなかったので、一旦RGBでバッファに変換してからGL_RGBで渡しています。
たしかグレースケールならGL_LUMINANCEで変換できると思ったんですけどうまくいかなかった。
ちなみに、前回のOpenCV導入記事はこちら。hellkite.hatenablog.com