2012年11月4日日曜日

iPhoneでOpenCVを使う

久しぶりに投稿します。いろいろと書けるネタがいろいろ溜まっているのに書けていないですねー。 実はOpenCVがオフィシャルでiOSに対応しているというのに、それに対応した日本語の記事がなかなかないので、マシンパワーあるモバイル端末での画像処理の研究とかが捗ってないとかあったら悲しいので、ビルドの方法とか書きます。

 といっても、この記事の日本語訳でしかないんですが。

コマンドラインとか怖くて使えないという人をある程度想定して書いています。
後、iOSプログラミングするんだから,Mac使っててXcode入ってないと出来ないです。

1. ソースコードのダウンロード

ターミナルを開いて、以下のコマンドを打ちます。

cd ~/ ##どこか適当なディレクトリ.ソースコードをDLしてもいい所
git clone https://github.com/Itseez/opencv.git ## githubからソースコードをDL。git入ってない場合はmacportsあたりでDL

ここまでで、きっとソースコードのDLが終わっているはず

2. ソースコードのコンパイル


cd /
sudo ln -s /Applications/Xcode.app/Contents/Developer Developer

Developerにシンボリックリンクを張ります。


cd ~/## ソースコードをDLしたのと同じディレクトリに戻る
python opencv/ios/build_framework.py ios ## ios用のframeworkをビルド。結構時間かかった

3. Frameworksの追加

外部ライブラリを追加するときの手順と同じように、frameworksを追加します。




今までみたいにCMakeしてビルドしてっていうのをしなくていいので、だいぶとっかかりがしやすくなったと思います。

2012年7月22日日曜日

Blockを使ったNSArrayのソート

NSArrayのソートって、

- (NSArray *)sortedArrayUsingDescriptors:(NSArray *)sortDescriptors
とかを使ってしかソートできないのかと思ったらBlocks使ってソートできるみたい。

このメソッド
- (NSArray *)sortedArrayUsingComparator:(NSComparator)cmptr

使い方


// arrayにはNSDate型のオブジェクトが入っているとする
    NSArray *sorted = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        return [(NSDate *)obj1 earlierDate:(NSDate*)obj2] == (NSDate*)obj1;
    }];
これで日付の降順にソートされたNSArrayを取得できます。
うだうだ別メソッドに書き出さなくてすむので、便利ですね!

2012年7月20日金曜日

パノラマ合成

パノラマ合成のアルゴリズムを実装してみましたので公開します。

環境
C++, OpenCV2.4

ソースコード
https://gist.github.com/3135917

使い方
入力として、画像ファイルを入れると,panorama.pngとしてパノラマ画像が出力されます。
画像サイズとか高さとかは割と適当なので、時間を見つけて直して行きます。
ToDo

  • カラー対応
  • サイズをきっちり揃える

コンパイル方法
MacPortsでOpenCVをインストールしたと仮定した後の話
g++ panorama_stitching.cpp `pkg-config --cflags opencv` `pkg-config --libs opencv` -lm
でコンパイルができます。多分


アルゴリズムの概説

  1. 各入力画像に対してSURFで特徴点を抽出
  2. 隣り合う画像(入力の前後)で対応点マッチング
  3. 前後の画像から、変換行列を最小二乗法で推定。
    座標系は円筒座標を仮定し、全ての写真は同じ奥行きにあると仮定
  4. 変換行列を逐次乗じながら、それぞれの画像を結果画像にマッピングして行く
注意)
入力するときは隣り合う画像を入力してください。連続する画像で対応点が取れないと破綻します。
変換行列の全体最適は行っていないので、少しずつ計算誤差が累積します。





2012年6月17日日曜日

OpenCV 2.4 で SURF が使えない

OpenCV 2.4 (c++版)でSURFを使おうとするとコンパイルが通りません。


こんな感じのコード

#include <iostream>
#include <string>

#include <cv.h>
#include <highgui.h>

using namespace std;
using namespace cv;

int main( int argc, char* argv[] ){
  if( argc < 1 ) return 1;
  
  Mat colorImage = imread( argv[1], 1);
  if( colorImage.empty() ) return -1;

  Mat grayImage;
  cvtColor( colorImage, grayImage, CV_BGR2GRAY );

  SURF calc_surf = SURF(500,4,2,true);

  vector<keypoint> kp_vec;
  vector<float> desc_vec;
  calc_surf( grayImage, Mat(), kp_vec, desc_vec);

  cout << "Image keypoints " << kp_vec.size() << endl;
  return 0;
}


これでコンパイルすると、


~/Development/cpp-study# g++ study.cpp `pkg-config --cflags opencv` `pkg-config --libs opencv`
study.cpp: In function ‘int main(int, char**)’:
study.cpp:19: error: ‘SURF’ was not declared in this scope
study.cpp:19: error: expected `;' before ‘calc_surf’
study.cpp:23: error: ‘calc_surf’ was not declared in this scope

な感じで怒られます。
どうやら、ヘッダファイルにSURFがインクルードされていないみたいです。
SURFが定義されているのが、nonfree/nonfree.hpp なのですが、インクルードしたcv.h
を見てみると、nonfree.hppがインクルードされていません

なのでcv.hを以下のように変更します

/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.

~~~中略~~~~
#include "opencv2/core/core_c.h"
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/flann/flann.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/legacy/compat.hpp"
#include "opencv2/nonfree/nonfree.hpp" // <-- ここを追加
~~~以下略~~~

多分これでうまく行くと思います。
nonfreeっていう名前から、ただでは使えないみたいですね。

2012年6月5日火曜日

Instagramの画像処理3 -色味変換-

前々回のポスト のトーンカーブによる画像変換の続きで、トーンカーブを求めます。

トーンカーブなので、ガンマ曲線をフィッティングしてもいいんですが、

  • そこまで厳密に求める必要がない
  • 8bit 256階調なので、その入出力をマッピングしても事足りる

ということなので、ある入力値に対して、いくら出力するか、というデータをテーブルで保持しておくルックアップテーブル(LUT)を求めます。

求め方

黒から白へとなだらかに変化する画像を入力画像とし、この画像にInstagramで変換を行ったものを出力画像とする。
入出力画像の各ピクセルの入力と、出力の関係をテーブルに保持して行きます。
同じ入力輝度値の画素がいくつか出てきますが、平均化してならしました。

入力画像

出力画像


実行結果

instagramの結果

LUTの出力結果


なかなかいい感じですね。
この辺のデータはまとまってgithubにあがってます

https://github.com/ginrou/OpenCV-Sample/blob/master/src/instagram_hack.c
computeLookUpTableという関数が、このLUTを求める関数です。


次は

  • チルトによるぼけ効果
  • ケラレ

あたりをキャリブレーションするかもしれません。


前回の補足

色変換行列を、ランダムカラーの画像を使って推定してみましたが、あまりうまく行きませんでした。
推定に使った画像
Instagramへの入力
Instagramで変換
色変換行列で変換

色味が変わってるのは分かりますが、じゃあちゃんと変わってるかと言うと、そういうわけではないです。




2012年6月3日日曜日

Instagramの画像処理2

色変換行列で試してみよう。



色変換行列の推定

色変換行列が
[r g b 1 ]' = A [r g b 1]
のような4×4の行列で表現されているとして、この変換行列を推定しました。
変換前後の画像から、最小二乗法を用いてパラメータを推定しました。
変換前
変換後

推定した行列はこんな感じです。

0.373982 0.373982 0.373982 -1.927580
0.376430 0.376430 0.376430 0.711464
0.372265 0.372265 0.372265 13.394824
0.000000 0.000000 0.000000 1.000000

この変換行列でやってみたのがこんな感じ
入力
この行列で変換
本来はこうなるはず
それっぽいと言えばそれっぽいけど。。。
っていうか、白黒画像だとうまいこと変換行列を推定できないですよね。
もう少し入力データをいじって実験してみます。

2012年5月30日水曜日

Instagramの画像処理

おそらくトーンカーブいじりながら、線形変換してるんだろうなーという予想をたててる。
とりあえず、

  • 0-255の間で変化する画像
  • 0-255のランダム画像
を使ってとりあえずデータを取ってみた

やり方

  1. 上で書いた画像を作る
  2. Instagramで変換(フィルタはBrannan)
  3. パソコンに持ってくる
  4. 入力を作った画像、出力を変換した画像としてプロット

入出力画像

ランダム-入力

ランダム-出力

グレー出力

グレー入力
画像の端の方が暗くなる現象(ケラレ)があるけど、今回は無視して色変換のみで

プロット出力










所感

ひとまず、同じような変換をしているみたいで一安心。中身を解釈して変換を変えてたらなかなかに面倒だったなと思う。
トーンカーブがあるように見えるけど、線形というように言われてもそうだと思えるしなー。
次は色変換行列を作ってみて、調べてみます。