iPhoneのカメラからの入力をリアルタイムに取得し、何らかの画像処理を行う、つまり iOSアプリで動画処理を行う のは、なかなか面倒です。
下記記事を見るとわかりますが、
シャッター音の鳴らないカメラアプリの実装方法 - Over&Out その後
AVFoundation を用いて、 カメラからの入力を毎フレーム取得しようとするだけで、かなりやることが多い です。デリゲートメソッドに渡されてくる画像データが CMSampleBufferRef という型で渡ってくるのも(個人的には)ハードルを感じる部分で、毎回「どう取り扱うんだっけ?」とググってしまいます。
さらに、毎フレーム送られてくる画像情報をリアルタイムに処理をしようとすると、やっぱり OpenGL ベースで処理 する必要が出てきて、これまた(個人的には)気が重くなってしまうところです。
ところが、videoGrabberExample という openFrameworks に同梱されているサンプルのソースを見ると、実にシンプルな実装で、カメラからの入力のリアルタイム処理が実現されていました。
openFrameworks for iOS のサンプル一覧 - Qiita [キータ]
こりゃ便利そう、ということで、その使い方と、チラッとソースをのぞいてみた内容を以下にまとめます。
##実装
こんな感じで、カメラからの入力に対してリアルタイムに反転処理をかけ、左下に表示するための実装手順です。(基本的には videoGrabberExample のコードをシンプルにしてコメントつけただけです)
###セットアップ
メンバ変数に
ofVideoGrabber grabber;
ofTexture tex;
unsigned char * pix;
を定義しておき、
void testApp::setup(){
// ofVideoGrabberを初期化
grabber.initGrabber(480, 360, OF_PIXELS_BGRA);
// テクスチャをallocate
tex.allocate(grabber.getWidth(), grabber.getHeight(), GL_RGB);
// バッファ確保
pix = new unsigned char[ (int)( grabber.getWidth() * grabber.getHeight() * 3.0) ];
}
###カメラからの入力を取得して画像処理
void testApp::update(){
// カメラからの入力を取得
grabber.update();
unsigned char * src = grabber.getPixels();
// 画素数 x チャンネル数
int totalPix = grabber.getWidth() * grabber.getHeight() * 3;
// 反転処理
for(int k = 0; k < totalPix; k+= 3){
pix[k ] = 255 - src[k];
pix[k+1] = 255 - src[k+1];
pix[k+2] = 255 - src[k+2];
}
// テクスチャデータ生成
tex.loadData(pix, grabber.getWidth(), grabber.getHeight(), GL_RGB);
}
上記コードではフレーム毎の入力を取得して、そこに各画素値を反転させる処理を行っています。
###描画
void testApp::draw(){
// カメラからの入力を描画
grabber.draw(0, 0);
// 生成したテクスチャを描画
tex.draw(0, 0, tex.getWidth() / 4, tex.getHeight() / 4);
}
##ソースの中身をのぞいてみる
先日書いた こちらの記事 で、一部の oF クラスに、 単なるラッパー疑惑 を抱いたのですが、これはその逆ですごく便利なので、どんな感じにラップされてるのかソースの中身をみてみました。
###AVFoundationVideoGrabber
ソースは addons/ofxiOS/src/video/AVFoundation
にあるのですが、AVFoundation まわりの諸々はこの AVFoundationVideoGrabber というクラスでラップされてました。
###ofxiOSVideoGrabber
このクラスのソースは addons/ofxiOS/src/video
にあります。
上記の AVFoundationVideoGrabber へのポインタを持っています。ofBaseVideoGrabber を継承していて、オーバーライドしている各メソッドの中身では、AVFoundationVideoGrabber のメソッドを呼んでいます。
###ofVideoGrabber
ソースの場所は libs/openFrameworks/video
iOS環境の場合に、ofxiOSVideoGrabber をインスタンスとして持つように実装されています。
#ifdef OF_VIDEO_CAPTURE_IOS
#include "ofxiOSVideoGrabber.h"
#define OF_VID_GRABBER_TYPE ofxiOSVideoGrabber
#endif
if( grabber == NULL ){
setGrabber( ofPtr<OF_VID_GRABBER_TYPE>(new OF_VID_GRABBER_TYPE) );
}
AVFoundation 以外 の諸々(OpenGLのテクスチャとしての描画とか)はここに実装されています。
##いずれ調べる
iOS アプリで OpenGL で画像/動画処理をする場合、GPUImage を利用することが多いので、それと併用するにはどうやるのがいいか(何かしらの共通フォーマットにすればいいと思うので、それを、どのタイミングで、どのフォーマットにするのがいいか)というのをいずれ調べようと思います。