ラベル OpenCV の投稿を表示しています。 すべての投稿を表示
ラベル OpenCV の投稿を表示しています。 すべての投稿を表示

2012年4月20日金曜日

Quartz Composer: MacPortsで入れたOpenCV2.2に関するパッチを作るテンプレート的なナニカ

たぶんもっと良い方法がある.けどメモ.
MacPortsでopencv 2.xを入れて/opt/local下に入っている前提


  • 'Project Navigator'内ルート要素を選択

    • PROJECTのBuild Settingsを開き,表示をAllとする.

      1. 'Search Paths'内の'Header Search Paths'に'/opt/local/include'を加える.

    • TARGETSのBuild Phasesを開く.

      1. 'Library Binary With Libraries'を選択し展開する.
      2. '+'ボタンを押し'Add Other …'にて直接ファイル選択を行う.
      3. /opt/local/libs以下にある'libopencv_'で始まるdylibを全て加える.

        • ('/opt/local'あたりをFinderの左ペインに加えておくと楽)



  • '.m'ファイルを'.mm'に変更する.


  • #import <opencv2/opencv.hpp>

    @implementation OpenCV_XXXPlugIn

    @dynamic inputSourceImage;
    @dynamic outputResultImage;

    @end
    @implementation OpenCV_XXXPlugIn (Execution)

    static void _BufferReleaseCallback(const void* address, void* info)
    {
    }
    +(cv::Mat)CVMatWithQCPlugInInputImageSource:(id <QCPlugInInputImageSource>)image
    {
    CGFloat cols = [image bufferPixelsWide];
    CGFloat rows = [image bufferPixelsHigh];
    cv::Mat cvMat(rows, cols, CV_8UC4);
    cvMat.data= (uchar *)[image bufferBaseAddress];
    return cvMat;
    }
    - (BOOL)execute:(id <QCPlugInContext>)context atTime:(NSTimeInterval)time withArguments:(NSDictionary *)arguments
    {
    id inputImage= self.inputSourceImage;
    self.outputResultImage = nil;

    if(inputImage) {
    if(![inputImage lockBufferRepresentationWithPixelFormat:QCPlugInPixelFormatBGRA8
    colorSpace:[inputImage imageColorSpace]
    forBounds:[inputImage imageBounds]]) {
    return NO;
    }
    cv::Mat src_img= [OpenCV_XXXPlugIn CVMatWithQCPlugInInputImageSource:inputImage];
    cv::Mat dst_img(src_img.size(), src_img.type());


    src_img.copyTo(dst_img);


    id <QCPlugInOutputImageProvider> provider= [context outputImageProviderFromBufferWithPixelFormat:QCPlugInPixelFormatBGRA8
    pixelsWide:dst_img.cols
    pixelsHigh:dst_img.rows
    baseAddress:dst_img.data
    bytesPerRow:dst_img.cols*dst_img.channels()
    releaseCallback:_BufferReleaseCallback
    releaseContext:NULL
    colorSpace:[inputImage imageColorSpace]
    shouldColorMatch:YES];

    if(provider == nil)
    return NO;

    self.outputResultImage = provider;

    [inputImage unlockBufferRepresentation];
    }
    return YES;
    }

    @end

2010年6月9日水曜日

NyARToolkit + NyMmd をやってみた ( MacOSX 10.6 ( Snow Leopard ) / Eclipse )

追記(2010/06/13):'やってみた(2010/06/13 追加)'を追加

追記(2010/06/10):'やってみた(追加)'を修正



動機
元動画のようにARToolkit(前回(NyARToolkit)),とMMD(前々回(NyMmd))をくっつけたい!


感謝
各種リソース作者やマトメ等記事を書かれている方に感謝


やってみた
0. 前回前々回がそれぞれできていること.

1. NyARToolkit側の前回実行に用いたjp.nyatla.nyartoolkit.jogl.sample.JavaSimpleLite.javaを編集していくのでNyARToolkitプロジェクトにNyMmdプロジェクトのクラスパスを追加する.

1.a プロジェクトの'Properties'で'Java Build Path'タブを開き'Add Class Folder…'ボタンで選択ダイアログを出す.

1.b NyMmdプロジェクトのbinフォルダを選択し,追加する.


1.c NyMmdプロジェクト中のMmdフォルダ(pmd, vmdを入れたフォルダ)をNyARToolkitプロジェクトルートにDnD等で複写する.
1.c NyARToolkitプロジェクトルートにMmdフォルダを作成し,pmd, vmdファイル(およびテクスチャ)をDnD等で配置する.
 2.eのコードで調整してもらってもよい.


2. jp.nyatla.nyartoolkit.jogl.sample.JavaSimpleLite.javaを編集

2.a NyMmdプロジェクトのjp.nyatla.nymmd.test.MmdTest.javaより
 MmdTestクラス中のinit(GLAutoDrawable drawable)メソッドをJavaSimpleLiteクラスに複写する.
 ただし同名のメソッド名は既にあるので'mmd_'というprefixをつけて'mmd_init(…)'にする.

2.b NyMmdプロジェクトのjp.nyatla.nymmd.test.MmdTest.javaより
 MmdTestクラス中のdisplay(GLAutoDrawable drawable)メソッドをJavaSimpleLiteクラスに複写する.
 ただし同名のメソッド名は既にあるので'mmd_'というprefixをつけて'mmd_display(…)'にする.

2.c NyMmdプロジェクトのjp.nyatla.nymmd.test.MmdTest.javaより
 MmdTestクラス中の以下のフィールド定義をJavaSimpleLiteクラスに複写する.

  • animation_start_time

  • _pmd

  • _vmd

  • _player

  • _render

  • _data_io

  • prev_time



2.d NyMmdプロジェクトのjp.nyatla.nymmd.test.MmdTest.javaより
 FileIOクラスをJavaSimpleLiteファイルに複写する.

2.e 以下のメソッドをに追加
 private void init_mmd_files() {
String pmd_file = "./Mmd/pmdfile.pmd";
String vmd_file = "./Mmd/vmdfile.vmd";
try {
this._pmd = new MmdPmdModel(new FileInputStream(pmd_file));
this._vmd = new MmdVmdMotion(new FileInputStream(vmd_file));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (MmdException e) {
e.printStackTrace();
}
this._player = new MmdMotionPlayer(this._pmd, this._vmd);
this._player.setLoop(true);
File f = new File(pmd_file);
this._data_io = new FileIO(f.getParentFile().getPath());
}


2.f JavaSimpleLiteクラスのdisplayメソッド中でdrawCubeメソッドを呼ぶところをコメントアウトする.
 直後に
  
mmd_display(drawable);

 を追加する.

2.g JavaSimpleLiteクラスのinitメソッド中最後のreturn直前にある
 _animatorフィールドへの値の代入と同フィールドインスタンスのメソッド呼び出しをコメントアウトする.
 直後に
  
mmd_init(drawable);

 を追加する.

2.h JavaSimpleLiteクラスのコンストラクタの中,
 最初に
  
mmd_init_files();

 を追加する.

2.i mmd_displayメソッド内で以下の修正を加える.

  • glClearメソッドを用いている行をコメントアウトする.

  • glLoadIdentityメソッドを用いている行をコメントアウトする.

  • glTranslatefメソッドを用いている行をコメントアウトする.

  • glScalefで1.0,1.0,1.0としているところをモデルに合わせて調整する.0.1, 0.1, 0.1など

  • 上記直後にx軸を90度まわしてやる.
    _gl.glRotatef(90.0f, 1.0f, 0.0f, 0.0f);




2.j mmd_initメソッド内で以下の修正を加える.

  • 光源位置のZ軸を負にしてあげる



3.実行
前回同様VM引数として'-d32 -Djava.library.path=./library:./lib'を与えて実行



やってみた(追加)
カメラ目線モード(?)を実行するにはJavaSimpleLiteクラスmmd_displayメソッド中の
以下のコメントアウト行の下に
// this._player.updateNeckBone(100.0f,10f,10f);

次のコードを追加してみた.
   float x = (float) __display_wk[12];
float y = (float) __display_wk[13];
float z = (float) __display_wk[14];
this._player.updateNeckBone(-x, -y, -z);


それっぽく見えるときもあるんだけどやっぱり違うのかな,所々おかしな方向向いているきもする.


やってみた(追加)
モデル側座標系でみたカメラ(グローバル)側座標系の原点ということだろう.ということで以下のように訂正.

カメラ目線モード(?)を実行するにはJavaSimpleLiteクラスmmd_displayメソッド中の
以下のコメントアウト行の下に
// this._player.updateNeckBone(100.0f,10f,10f);

次のコードを追加してみた.
   NyARMat a = new NyARMat(4, 4);
double[][] a_ary = a.getArray();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
a_ary[j][i] = __display_wk[j * 4 + i];
}
}
a.matrixSelfInv();
float x = (float) a_ary[3][0];
float y = (float) a_ary[3][1];
float z = (float) a_ary[3][2];
this._player.updateNeckBone(x, y, z);


どうだろう?
(NyARMat aはフィールドにする方がよいかもね)


やってみた(2010/06/13 追加)
上のやつをちょっと書き換えてみた.
   float m[] = new float[16];
_gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, m, 0);
NyARMat a = new NyARMat(4, 4);
double[][] a_ary = a.getArray();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
a_ary[j][i] = m[j * 4 + i];
}
}

a.matrixSelfInv();

double[] o = { 0.0, 0.0, 0.0, 1.0 };
double[] v = { 0.0, 0.0, 0.0 };
//o[2] = 10 * Math.sin(iTime / 1000.0);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
v[i] += a_ary[j][i] * o[j];
}
}

float x = (float) v[0];
float y = (float) v[1];
float z = (float) v[2];

this._player.updateNeckBone(x, y, z);

2010年6月8日火曜日

NyARToolkit for Java 2.3.2 を MacOSX/Eclipse でやってみた.'再: NyARToolkit for Java: QtJavaで読み込んで JOGLで書き出す'

動機
二年ぐらい前の怪しいエントリーOpenCV/JNIを利用したのと合わせて前回ぐらい簡単に書き直せないかしら.


感謝
各リンク先リソースに感謝!


やってみた
0. EclipseにJavaプロジェクトを作成
0.a ファイルのエンコーディングを'UTF-8'にしておく.


1. OpenCV
1.a OpenCV.Frameworkの取得とインストール
こちらのサイトの'1. Begin by downloading and installing the implementation of OpenCV appropriate to your platform:'のFor MacOSXの通りに実行
1.b OpenCV.jarの取得
こちらのサイトの'2. Download, unzip, and move the OpenCV Processing Library into your Processing libraries folder, or for Java users copy the content of the library folder in one of your Java Extensions folder.'の'OpenCV Processing Library'部のアンカーからopencv_01.zipをdownload.
1.c OpenCV.jarの設置
展開した中にある'library'フォルダをプロジェクトルートへDnD等で設置
library/OpenCV.jarをbuild pathに追加


2. JOGL
2.a 取得
こちらのサイトのjogl-1.1.1-macosx-universal.zip)をdownload.
2.b 設置
展開した中にある'lib'フォルダをプロジェクトルートへDnD等で設置
lib/gluegen-rt.jar, lib/jogl.jarをbuild pathに追加


3. NyARToolkit
3.a 取得
こちらのサイトよりNyARToolkit for Java - NyARToolkit CoreのNyARToolkit-2.5.2.zipをdownload
3.b 設置
展開した中にある'Data'フォルダをプロジェクトルートへDnD等で設置
展開した中にある'src/jp'フォルダをソースフォルダへDnD等で設置
展開した中にある'src.util/qt/jp'フォルダをソースフォルダへDnD等で設置
jp.nyatla.nyartoolkit.qt.utils packgageの QtCameraCapture.java削除
展開した中にある'src.util/jogl/jp'フォルダをソースフォルダへDnD等で設置
展開した中にある'sample/jogl/jp'フォルダをソースフォルダへDnD等で設置
jp.nyatla.nyartoolkitjogl.sample packageのJavaSimpleLite.javaを除いて削除(この時点ではJavaSimpleLite.javaにはエラーが出ているはず.)

3.c 追加
こちらの'Eclipse/09. Create the 'test.CameraCapture.java' file.'と同じように'text.CameraCapture.java'という以下のファイルを追加作成する

3.d 編集
jp.nyatla.nyartoolkitjogl.sample.JavaSimpleLite.javaを編集

  • 'JmfCaptureListener'を'QtCaptureListener'へ置換

  • 'JmfNyARRaster_RGB'を'QtNyARRaster_RGB'へ置換

  • 'JmfCaptureDevice'を'CameraCapture'へ置換

  • 'JavaSimpleLite'クラスの'onUpdateBuffer'メソッドの引数の型を'Buffer'から'byte[]'へ置換

  • 'JavaSimpleLite'クラスの'onUpdateBuffer'メソッド内,QtNyARRaster_RGBインスタンスのsetBufferメソッドをwrapBufferメソッドに置換


  • ここまでで残るはキャプチャとラスタの準備部だけがエラーになっているはず


  • で該当部をザックリコメントアウトして以下の様に追加する
    _capture = new CameraCapture(SCREEN_X, SCREEN_Y, 30f);
    _capture.setCaptureListener(this);
    _cap_image = new QtNyARRaster_RGB(SCREEN_X, SCREEN_Y);


  • あとはCARCODE_FILEとCARCODE_FILEの相対パスを"../../Data…"から"./Data…"に置き換える


ここまでのプロジェクトの状態


4. 実行
jp.nyatla.nyatoolkit.jogl.sample.JavaSimpleLite.javaを実行
実行時にはVM引数として'-d32 -Djava.library.path=./library:./lib'をつける.

2009年10月7日水曜日

cvCalcOpticalFlowBMでハマったことのメモ

追記(2010/09/22): このままでは動かないらしいです.


動機
こちらの記事をみかけたので.雪豹でやってみようかと思った.

エントリー化の動機
そのままでは動かなかったのでメモ.たぶんOpenCVのバージョンとかの問題.

参考
こちら

現象
動機のサイトの通りやると(おいらが“通り”にはやれてないから動かないわけだが)
OpenCV ERROR: Sizes of input arguments do not match ()
in function cvCalcOpticalFlowBM, ../../src/cv/cvoptflowbm.cpp(596)

とでて落ちた.

やったこと
上記問題については以下について修正(その他雪豹用(OpenCV.frameworkとか)にあれこれ).
修正前
 rows = int(ceil (double (src_img1->height) / block_size));
cols = int(ceil (double (src_img1->width) / block_size));

修正後
 cols = floor((src_img1->width - block.width) / shift.width); 
rows = floor((src_img1->height - block.height) / shift.height);


そんだけ.

2009年9月27日日曜日

NyARToolkit-2.3.1 for Java on Snow Leopard (using OpenCV/JNI)

Environment
01. MacOSX 10.6.1 (Snow Leopard)
02. Eclipse (Java IDE)

Resouce
01. NyARToolkit-2.3.1 for Java (NyARToolkit-2.3.1.zip)
02. OpenCV / Processing and Java Library (opencv_01.zip) (reference: this, this)

Eclipse
01. Make a 'Java Project'
02. DnD (Drag and Drop) from 'NyARToolkit-2.3.1/src/jp' folder to 'src' folder.
03. DnD from 'NyARToolkit-2.3.1/src.utils/qt/jp' folder to 'src' folder.
04. DnD from 'NyARToolkit-2.3.1/sample/qt/jp' folder to 'src' folder.
05. DnD from 'NyARToolkit-2.3.1/Data' folder to the project top (project icon).
06. DnD from 'OpenCV/library' folder to the project top (project icon).
07. Add to build path the 'OpenCV/library/OpenCV.jar' file.
08. Delete the 'jp.nyatla.nyartoolkit.qt.utils.QtCameraCapture.java' file.
09. Create the 'test.CameraCapture.java' file.
package test;

import hypermedia.video.OpenCV;
import jp.nyatla.nyartoolkit.qt.utils.QtCaptureListener;

public class CameraCapture implements Runnable {
private QtCaptureListener listener;
protected byte[] p;

int w;
int h;
int r;
private OpenCV cv;
private Thread t;

public CameraCapture(int _w, int _h, float _r) {
w = _w;
h = _h;
r = (int)(1000.0 / _r);
p = new byte[w * h * 3];

cv = new OpenCV();
cv.capture(w, h);
}

public void setCaptureListener(QtCaptureListener _listener) {
listener = _listener;
}

public void start() {
t = new Thread(this);
t.start();
}

public void stop() {
t = null;
cv.dispose();
}

public void run() {
while (t != null && cv != null) {
try {
Thread.sleep(r);
cv.read();
int[] p_int = cv.pixels();
int j = 0;
for (int i = 0; i < w * h; i++) {
p[j++] = (byte) (p_int[i] >> 16);
p[j++] = (byte) (p_int[i] >> 8);
p[j++] = (byte) (p_int[i]);
}
listener.onUpdateBuffer(p);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

Package Explorer like this

09. Edit the 'jp.nyatla.nyartoolkit.qt.sample.NyarToolkitLinkTest.java' file.
09.a the 2 variables's value
 private final String CARCODE_FILE = "./Data/patt.hiro";
private final String PARAM_FILE = "./Data/camera_para.dat";

09.b Replace from 'QtCameraCapture' to 'CameraCapture'.

10. Edit the 'jp.nyatla.nyartoolkit.qt.sample.NyarToolkitLinkTest.java' file and the 'jp.nyatla.nyartoolkit.qt.sample.QtCaptureTest.java'
10.a Add the 'import test.CameraCapture;'
10.b Replace from 'QtCameraCapture' to 'CameraCapture'.

11. Run
11.a Set the run configuretion

VM arguments: -d32 -Djava.library.path=${project_loc}/library
(The upper image is used a wrong name (lib).

11.b Run the 'jp.nyatla.nyartoolkit.qt.sample.NyarToolkitLinkTest'.


Result

JavaでJNIをつかってOpenCVのビデオキャプチャ

これを単純なキャプチャだけにしてみた.
コード
import hypermedia.video.OpenCV;

import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.MemoryImageSource;

public class Sample extends Frame implements Runnable {

final int FRAME_RATE = 1000 / 30;

private OpenCV cv;
private Thread t;
private Image frame = null;

public Sample() {
cv = new OpenCV();
cv.capture(640, 480);

setBounds(100, 100, cv.width, cv.height);
setVisible(true);
addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
stop();
System.exit(0);
}
}
});

t = new Thread(this);
t.start();
}

@Override
public void run() {
while (t != null && cv != null) {
try {
Thread.sleep(FRAME_RATE);
cv.read();
MemoryImageSource mis = new MemoryImageSource(cv.width,
cv.height, cv.pixels(), 0, cv.width);
frame = createImage(mis);
repaint();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public void paint(Graphics g) {
if (frame == null)
return;
g.drawImage(frame, 0, 0, null);
}

public void stop() {
t = null;
cv.dispose();
}

public static void main(String[] args) {
new Sample();
}
}


Eclipse環境/ファイル配置


Eclipse環境/実行時引数

-d32 -Djava.library.path=${project_loc}/lib

JavaからJNIをつかってOpenCVを使う方法 ( Snow Leopard で )

ProcessingのOpenCV用ライブラリはJavaのJNIであることを知ったので(言われてみればそうだ)やってみた.
結果
BlobDetection


1.ダウンロード
1.1 こちらのサイトから'2.'の項のOpenCV Processing Libraryアンカからダウンロード
1.2 こちらのサイトから'3.'の項のOpenCV Java samplesアンカからダウンロード

2.実行
2.1 ダウンロードしたzipを展開フォルダ(OpenCV)を${OpenCV_Lib}とする.
2.2 ダウンロードしたzipを展開フォルダ(OpenCV Java samples)を${OpenCV_Java}とする.
2.3 やってみよう
> cd ${OpenCV_Java}
> javac -classpath ${OpenCV_Lib}/library/OpenCV.jar BlobDetection.java
> java -d32 -Djava.library.path=${OpenCV_Lib}/library/ -classpath .:${OpenCV_Lib}/library/OpenCV.jar BlobDetection

'-d32'オプションがないと'no suitable image found.'と叱られるw.


使えるメソッドについてはこの辺りを参照のこと.

2009年9月19日土曜日

QC: OpneCVでステレオ画像処理

追記(2009/9/21): &を直接書いて表示されてない問題があった.&amp;として表示を修正.



Quartz Composerでやってみた.
結果


やったこと: OpenCV 1.1preについて
以前の記事に書いた通り
こちらからEnglish Versionの'OpenCV-Private-Framework-1.2.dmg'をdownload.
・インストールとしてOpenCV.frameworkフォルダを/Library/FrameworksフォルダへCopy.


やったこと:プロジェクトの用意
・XcodeにてApplication Plug-inのQuartz Composer Plug-inプロジェクトを選択

・プロジェクトに既存のフレームワークとして‘/Library/Frameworks/OpenCV.framework’を追加
・プロジェクトの情報(インスペクタ)でアーキテクチャを‘32-bit Universal’, 有効なアーキテクチャを‘i386’にする.
・参考:以前の記事


やったこと:コード
FindStereoCorrespondenceBMPlugIn.h
#import <Quartz/Quartz.h>
#import <OpenCV/cv.h>

@interface FindStereoCorrespondenceBMPlugIn : QCPlugIn
{
}

@property(assign) id<QCPlugInInputImageSource> inputLeftSourceImage;
@property(assign) id<QCPlugInInputImageSource> inputRightSourceImage;
@property(assign) id<QCPlugInOutputImageProvider> outputResultImage;

@end
@interface FindStereoCorrespondenceBMPlugIn (Func)
- (IplImage *)grayImageWihtSourceImage:(id)image;
- (IplImage *)iplImageWihtImage:(id<QCPlugInInputImageSource>)image;
@end


FindStereoCorrespondenceBMPlugIn.m
#import <OpenGL/CGLMacro.h>

#import "FindStereoCorrespondenceBMPlugIn.h"
#import "OutputImageProvider.h"

#define kQCPlugIn_Name @"FindStereoCorrespondenceBM"
#define kQCPlugIn_Description @"FindStereoCorrespondenceBM description"

@implementation FindStereoCorrespondenceBMPlugIn
@dynamic inputRightSourceImage;
@dynamic inputLeftSourceImage;
@dynamic outputResultImage;

…略…

- (BOOL) execute:(id<QCPlugInContext>)context atTime:(NSTimeInterval)time withArguments:(NSDictionary*)arguments
{
id<QCPlugInInputImageSource> imageLeft, imageRight;
self.outputResultImage = nil;

if(imageLeft= self.inputLeftSourceImage) {
if(![imageLeft lockBufferRepresentationWithPixelFormat:QCPlugInPixelFormatBGRA8
colorSpace:[imageLeft imageColorSpace]
forBounds:[imageLeft imageBounds]]) {
return NO;
}
if(imageRight= self.inputRightSourceImage) {
if(![imageRight lockBufferRepresentationWithPixelFormat:QCPlugInPixelFormatBGRA8
colorSpace:[imageRight imageColorSpace]
forBounds:[imageRight imageBounds]]) {
return NO;
}



IplImage *image_left= [self grayImageWihtSourceImage:imageLeft];
IplImage *image_right= [self grayImageWihtSourceImage:imageRight];
CvSize size = cvGetSize(image_left);
CvMat *disparity= cvCreateMat(size.height, size.width, CV_16S);
CvStereoBMState *state= cvCreateStereoBMState(CV_STEREO_BM_BASIC, 16);
cvFindStereoCorrespondenceBM(image_left, image_right, disparity, state);
CvMat *disparity_8U= cvCreateMat(size.height, size.width, CV_8U);
cvConvertScale(disparity, disparity_8U, 1, 0);

IplImage *disparity_visual= cvCreateImage(size, IPL_DEPTH_8U, 4);
int i, j;
int w= size.width;
int h= size.height;
for(i= 0;i<h;i++) {
for(j= 0;j<w;j++) {
unsigned char c= disparity_8U->data.ptr[i*w+j];
disparity_visual->imageData[(i*w+j)*4 + 0]= c;
disparity_visual->imageData[(i*w+j)*4 + 1]= c;
disparity_visual->imageData[(i*w+j)*4 + 2]= c;
disparity_visual->imageData[(i*w+j)*4 + 3]= 255;
}
}

cvReleaseMat(&disparity_8U);
cvReleaseStereoBMState(&state);
cvReleaseMat(&disparity);
cvReleaseImage(&image_right);
cvReleaseImage(&image_left);

OutputImageProvider *provider = [[OutputImageProvider alloc] initWithIplImage:disparity_visual
pixelFormat:QCPlugInPixelFormatBGRA8
colorSpaceRef:[imageLeft imageColorSpace]];
if(provider == nil)
return NO;
self.outputResultImage = provider;
[provider release];


[imageRight unlockBufferRepresentation];
}

[imageLeft unlockBufferRepresentation];
}
return YES;
}

…略…

@end
@implementation FindStereoCorrespondenceBMPlugIn (Func)
- (IplImage *)grayImageWihtSourceImage:(id)image
{
IplImage *src_img= [self iplImageWihtImage:image];
IplImage *src_gray = cvCreateImage (cvGetSize(src_img), IPL_DEPTH_8U, 1);
cvCvtColor (src_img, src_gray, CV_BGRA2GRAY);
return src_gray;
}
- (IplImage *)iplImageWihtImage:(id)image
{
char *q= (char *)[image bufferBaseAddress];
IplImage *iplImage = calloc(1, sizeof(IplImage));

iplImage->nSize= sizeof(IplImage);
iplImage->ID= 0;
iplImage->nChannels= 4;
iplImage->depth= IPL_DEPTH_8U;
iplImage->dataOrder= 0;
iplImage->origin= 0;
iplImage->width= [image bufferPixelsWide];
iplImage->height= [image bufferPixelsHigh];
iplImage->roi= NULL;
iplImage->maskROI= NULL;
iplImage->imageData= q;
iplImage->widthStep= [image bufferBytesPerRow];
iplImage->imageDataOrigin= q;

return iplImage;
}

@end


OutputImageProvider.h
#import <Cocoa/Cocoa.h>
#import <OpenCV/cv.h>

@interface OutputImageProvider : NSObject <QCPlugInOutputImageProvider>
{
IplImage *_iplImage;
void *_baseAddress;
NSUInteger _rowBytes;
NSString *_format;
NSRect _bounds;
CGColorSpaceRef _cgColorSpaceRef;
}
- (id)initWithIplImage:(IplImage *)image
pixelFormat:(NSString *)format
colorSpaceRef:(CGColorSpaceRef)cgColorSpaceRef;
@end



OutputImageProvider.m
#import "OutputImageProvider.h"

@implementation OutputImageProvider
- (id)initWithIplImage:(IplImage *)image
pixelFormat:(NSString *)format
colorSpaceRef:(CGColorSpaceRef)cgColorSpaceRef
{
if(self = [super init]) {
_iplImage= image;
_baseAddress= _iplImage->imageData;
_rowBytes= _iplImage->widthStep;
_format= [format retain];
_bounds= NSMakeRect(0, 0, _iplImage->width, _iplImage->height);
_cgColorSpaceRef= cgColorSpaceRef;
}
return self;
}
- (void) dealloc
{
if (_iplImage) {
cvReleaseImage(&_iplImage);
}
[_format release];
[super dealloc];
}
- (NSRect) imageBounds
{
return _bounds;
}
- (CGColorSpaceRef) imageColorSpace
{
return _cgColorSpaceRef;
}
- (NSArray*) supportedBufferPixelFormats
{
return [NSArray arrayWithObjects: _format,
nil];
}
- (BOOL) renderToBuffer:(void*)baseAddress
withBytesPerRow:(NSUInteger)rowBytes
pixelFormat:(NSString*)format
forBounds:(NSRect)bounds
{
memcpy(baseAddress, _baseAddress, _rowBytes*_bounds.size.height);
return YES;
}
@end



実行について
OpenCVの入手に依存するがここにある方法だと32bitモードでないと動かない.Quartz Composerのインスペクタで32ビットモードで開くにチェックを入れておく(後日なにかの問題になるかもしれないから入れた事を忘れないようにw).

LeftとRightを反対にしてみるとまったく面影がないw.


参考
こちらの記事こちらの記事リファレンス
感謝!

MacとOpneCV(1.1pre)でステレオ画像処理 / 結果をgnuplotで

前回の結果で凹凸をつけてみる.
参考先と同じくTsukuba stereo pairでやってみる
・cvSave関数で取り出す.".txt"ならyaml, ".xml"ならxml形式.
・awkでいじる.(好きなものでどうぞ♪)
 ((x, d, y)でやると奥行きらしくだせるのだけど着色が?なので,(x, y, d)でz軸を奥行き扱いにした.)
・gnuplotで表示
> splot 'BM_pm3d.dat' with pm3d


BM法

正面から見るとこんな感じ.

GC法

正面から見るとこんな感じ.


って感じ.

2009年9月18日金曜日

MacとOpneCV(1.1pre)でステレオ画像処理

動機
こちらの記事でおもしろそうとおもったので.

参考
こちらの記事こちらの記事リファレンス
感謝!


やったこと1: OpenCV 1.1preについて
以前の記事に書いた通り
こちらからEnglish Versionの'OpenCV-Private-Framework-1.2.dmg'をdownload.
・インストールとしてOpenCV.frameworkフォルダを/Library/FrameworksフォルダへCopy.

やったこと2:Snow Leopard + Xcode 3.2で
2.1 プロジェクトは‘Applicatoin/Command Line Tool/Type C++ stdc++’を選択.

2.2 プロジェクトに既存のフレームワークとして‘/Library/Frameworks/OpenCV.framework’を追加
2.3 プロジェクトの情報(インスペクタ)でアーキテクチャを‘32-bit Universal’, 有効なアーキテクチャを‘i386’にする.

2.4 main.cppを編集
#include <OpenCV/cv.h>
#include <OpenCV/highgui.h>

int
main (int argc, char **argv)
{
IplImage *image_left, *image_right;

if (argc != 3 ||
(image_left = cvLoadImage (argv[1], CV_LOAD_IMAGE_GRAYSCALE)) == 0 ||
(image_right = cvLoadImage (argv[2], CV_LOAD_IMAGE_GRAYSCALE)) == 0)
return -1;

const char *winName = "Sample";
cvNamedWindow(winName, CV_WINDOW_AUTOSIZE);

CvSize size = cvGetSize(image_left);
if (0) { //切り替え
CvMat *disparity_left= cvCreateMat(size.height, size.width, CV_16S);
CvMat *disparity_right= cvCreateMat(size.height, size.width, CV_16S);
CvStereoGCState *state= cvCreateStereoGCState(16, 2);
cvFindStereoCorrespondenceGC(image_left, image_right, disparity_left, disparity_right, state, 0);
cvReleaseStereoGCState(&state);

CvMat *disparity_left_visual= cvCreateMat(size.height, size.width, CV_8U);
cvConvertScale(disparity_left, disparity_left_visual, -16);
cvShowImage(winName, disparity_left_visual);
}
else {
CvMat *disparity= cvCreateMat(size.height, size.width, CV_16S);
CvStereoBMState *state= cvCreateStereoBMState(CV_STEREO_BM_BASIC, 16);
cvFindStereoCorrespondenceBM(image_left, image_right, disparity, state);
cvReleaseStereoBMState(&state);

CvMat *disparity_visual= cvCreateMat(size.height, size.width, CV_8U);
cvConvertScale(disparity, disparity_visual, 1);
cvShowImage(winName, disparity_visual);
}
cvWaitKey(0);

return 0;
}

2.5 ビルド
2.6 できたのをコマンドラインで引数2つ(ステレオとなるイメージ)をつけて実行
> ./Sample imageLeft.jpg imageRight.jpg


以上

2009年8月13日木曜日

SURFを試したい!/ OpenCV 1.1pre(?)

動機 
こちらの記事を見かけた.

やったこと
やったこと1.OpenCV 1.1preをMacに入れる

  • portで入れたのは…1.0だった.
  • 調べた…普通にやってみたらいいんじゃね?…だめらしい
  • 調べた…あれこれはできるみたいに書いてある? .

    • …svn coの結果のファイルは…ChangeLogも1.1preってなってる.
    • …cmake!…Build Error.
  • よく読む…上のページに'PrivateFramework'って言葉がある.dmgで配布してるのかやってみるか.

    • こちらからEnglish Versionの'OpenCV-Private-Framework-1.2.dmg'をdownload.
    • …dmgの中をみる.'FaceTracker', 'OpenCV.framework', 'README.txt'がある.
    • …Desktopに全部Copy.FaceTrackerフォルダのFaceTracker.xcodeprojをクリック,Xcodeでビルドと実行(OpenCV.frameorkは相対パスになってる).動いた!
    • …インストールとしてOpenCV.frameworkフォルダを/Library/FrameworksフォルダへCopy.

  • できた!

やったこと2.SURFだ!

  • 動機のサイトからsurftest.cppをdownload(UTF-8だよ).
  • コンパイル
    $ g++ surftest.cpp -framework OpenCV  -I/Library/Frameworks/OpenCV.framework/Headers

    ('#include'の書き方を
    #include <OpenCV/cv.h>
    #include <OpenCV/highgui.h>

    とすれば'-I'以降は要らない)
  • で画像(printme.jpg / BazARの時に梱包されていた画像 )とその印刷物を用意して実行.
    $ ./a.out printme.jpg

  • できた!
    特徴点?
    Videoに対する出力

2009年3月1日日曜日

Quartz Composer / OpenCV : 背景統計量の累積のパッチを作ってみる (動作画像)

こんなかんじ(無駄に長いです).
(今回はオーディオ入れ替えってのを使ってみた.)



パッチ類はこんなかんじ

Quartz Composer / OpenCV : 背景統計量の累積のパッチを作ってみる

橋本詳解さん記事もあった背景統計量の累積をやってみた.

cvAcc等が3チャンネルしかだめらしいのでAlphaを抜く(フツーに).



OpenCV_AccumulationOfBackgroundPlugIn.h
#import <Quartz/Quartz.h>
#import <cv.h>
@interface OpenCV_AccumulationOfBackgroundPlugIn : QCPlugIn
{
id<QCPlugInInputImageSource> _image;
IplImage *av_img;
IplImage *sgm_img;
IplImage *lower_img;
IplImage *upper_img;
IplImage *tmp_img;
IplImage *dst_img;
IplImage *msk_img;

int _step;
unsigned char *_ip;
unsigned char *_op;
}
@property(assign) id<QCPlugInInputImageSource> inputSourceImage;
@property(assign) id<QCPlugInOutputImageProvider> outputResultImage;
@end
@interface OpenCV_AccumulationOfBackgroundPlugIn (FUNCTION)
- (void)clearBuffer;
- (void)init_bufferWithWidth:(int)w
height:(int)h
rowBytes:(NSUInteger)rowBytes;
- (IplImage *)removeAlphaChanelWihtWidth:(int)w
height:(int)h
imageData:(unsigned char *)q
rowBytes:(NSUInteger)rowBytes;
- (void)addAlphaChanelWithWidth:(int)w
height:(int)h
imageData:(unsigned char *)oq;
@end


OpenCV_AccumulationOfBackgroundPlugIn.m
#import <OpenGL/CGLMacro.h>

#import "OpenCV_AccumulationOfBackgroundPlugIn.h"
#import "O_AOB_OutputImageProvider.h"

#define kQCPlugIn_Name @"OpenCV Accumulation Of Background"
#define kQCPlugIn_Description @"OpenCV Accumulation Of Background description"

@implementation OpenCV_AccumulationOfBackgroundPlugIn
@dynamic inputSourceImage, outputResultImage;

+ (NSDictionary*) attributes
{
return [NSDictionary dictionaryWithObjectsAndKeys:kQCPlugIn_Name, QCPlugInAttributeNameKey,
kQCPlugIn_Description, QCPlugInAttributeDescriptionKey, nil];
}

+ (NSDictionary*) attributesForPropertyPortWithKey:(NSString*)key
{
if([key isEqualToString:@"inputSourceImage"])
return [NSDictionary dictionaryWithObjectsAndKeys:
@"Source Image", QCPortAttributeNameKey,
nil];
if([key isEqualToString:@"outputResultImage"])
return [NSDictionary dictionaryWithObjectsAndKeys:
@"Result Image", QCPortAttributeNameKey,
nil];
return nil;
}

+ (QCPlugInExecutionMode) executionMode
{
return kQCPlugInExecutionModeProcessor;
}

+ (QCPlugInTimeMode) timeMode
{
return kQCPlugInTimeModeNone;
}

- (id) init
{
if(self = [super init]) {
}

return self;
}

- (void) finalize
{
[super finalize];
}

- (void) dealloc
{
[super dealloc];
}

@end

@implementation OpenCV_AccumulationOfBackgroundPlugIn (Execution)
- (BOOL) startExecution:(id<QCPlugInContext>)context
{
[self clearBuffer];
return YES;
}
- (void) enableExecution:(id<QCPlugInContext>)context
{
}
- (BOOL) execute:(id<QCPlugInContext>)context atTime:(NSTimeInterval)time withArguments:(NSDictionary*)arguments
{
id<QCPlugInInputImageSource> image;
self.outputResultImage = nil;

if(image= self.inputSourceImage) {
if(![image lockBufferRepresentationWithPixelFormat:QCPlugInPixelFormatBGRA8
colorSpace:[image imageColorSpace]
forBounds:[image imageBounds]]) {
return NO;
}

int INIT_TIME = 10;
{
double B_PARAM = 1.0 / 50.0;
double T_PARAM = 1.0 / 200.0;
double Zeta = 10.0;
int w = [image bufferPixelsWide];
int h = [image bufferPixelsHigh];

if (!av_img) {
[self init_bufferWithWidth:w
height:h
rowBytes:[image bufferBytesPerRow]];
}


unsigned char *q= (unsigned char *)[image bufferBaseAddress];
IplImage *frame= [self removeAlphaChanelWihtWidth:w
height:h
imageData:q
rowBytes:[image bufferBytesPerRow]];

if (0 <= _step && _step < INIT_TIME) {
cvAcc ((CvArr *)frame, (CvArr *)av_img, (CvArr *)NULL);
}
if (_step == INIT_TIME) {
cvConvertScale (av_img, av_img, 1.0 / INIT_TIME, 0.0);
}
if (INIT_TIME <= _step && _step < INIT_TIME*2) {
cvConvert (frame, tmp_img);

cvSub (tmp_img, av_img, tmp_img, NULL);
cvPow (tmp_img, tmp_img, 2.0);
cvConvertScale (tmp_img, tmp_img, 2.0, 0.0);
cvPow (tmp_img, tmp_img, 0.5);
cvAcc (tmp_img, sgm_img, NULL);
}
if (_step == INIT_TIME*2) {
cvConvertScale (sgm_img, sgm_img, 1.0 / INIT_TIME, 0.0);
}
if (INIT_TIME*2 < _step) {
cvConvert (frame, tmp_img);

cvSub (av_img, sgm_img, lower_img, NULL);
cvSubS (lower_img, cvScalarAll (Zeta), lower_img, NULL);
cvAdd (av_img, sgm_img, upper_img, NULL);
cvAddS (upper_img, cvScalarAll (Zeta), upper_img, NULL);
cvInRange (tmp_img, lower_img, upper_img, msk_img);

cvSub (tmp_img, av_img, tmp_img, NULL);
cvPow (tmp_img, tmp_img, 2.0);
cvConvertScale (tmp_img, tmp_img, 2.0, 0.0);
cvPow (tmp_img, tmp_img, 0.5);

cvRunningAvg (frame, av_img, B_PARAM, msk_img);
cvRunningAvg (tmp_img, sgm_img, B_PARAM, msk_img);

cvNot (msk_img, msk_img);
cvRunningAvg (tmp_img, sgm_img, T_PARAM, msk_img);

cvSetZero (dst_img);
cvCopy (frame, dst_img, msk_img);

[self addAlphaChanelWithWidth:w
height:h
imageData:(unsigned char *)dst_img->imageData];

O_AOB_OutputImageProvider *provider = [[O_AOB_OutputImageProvider alloc] initWithBuffer:_op
withBytesPerRow:[image bufferBytesPerRow]
pixelFormat:QCPlugInPixelFormatBGRA8
forBounds:[image imageBounds]
colorSpaceRef:[image imageColorSpace]];
if(provider == nil)
return NO;
self.outputResultImage = provider;
[provider release];

}
}

if (_step<(INIT_TIME*2+2)) {
_step++;
}
[_image unlockBufferRepresentation];
}
return YES;
}
- (void) disableExecution:(id<QCPlugInContext>)context
{
}
- (void) stopExecution:(id<QCPlugInContext>)context
{
[self clearBuffer];
}
@end

@implementation OpenCV_AccumulationOfBackgroundPlugIn (FUNCTION)
- (void)clearBuffer
{
if (_ip!=NULL) {
free(_ip);
_ip= NULL;
}
if (_op!=NULL) {
free(_op);
_op= NULL;
}
if (dst_img!=NULL) {
cvReleaseImage (&dst_img);
dst_img= NULL;
}
if (av_img!=NULL) {
cvReleaseImage (&av_img);
av_img= NULL;
}
if (sgm_img!=NULL) {
cvReleaseImage (&sgm_img);
sgm_img= NULL;
}
if (lower_img!=NULL) {
cvReleaseImage (&lower_img);
lower_img= NULL;
}
if (upper_img!=NULL) {
cvReleaseImage (&upper_img);
upper_img= NULL;
}
if (tmp_img!=NULL) {
cvReleaseImage (&tmp_img);
tmp_img= NULL;
}
if (msk_img!=NULL) {
cvReleaseImage (&msk_img);
msk_img= NULL;
}
_step= 0;
}
- (void)init_bufferWithWidth:(int)w
height:(int)h
rowBytes:(NSUInteger)rowBytes
{
av_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_32F, 3);
sgm_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_32F, 3);
tmp_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_32F, 3);
lower_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_32F, 3);
upper_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_32F, 3);

dst_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_8U, 3);
msk_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_8U, 1);

cvSetZero (av_img);
cvSetZero (sgm_img);

NSUInteger bpr= (rowBytes / 4 * 3);
_ip= malloc(bpr * h * sizeof(unsigned char));
_op= malloc(rowBytes * h * sizeof(unsigned char));
}
- (IplImage *)removeAlphaChanelWihtWidth:(int)w
height:(int)h
imageData:(unsigned char *)q
rowBytes:(NSUInteger)rowBytes
{
int x, y;
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
_ip[(w*3) * y + x * 3 + 0] = q[((w*4) * y + x * 4 + 0)];
_ip[(w*3) * y + x * 3 + 1] = q[((w*4) * y + x * 4 + 1)];
_ip[(w*3) * y + x * 3 + 2] = q[((w*4) * y + x * 4 + 2)];
}
}
IplImage *frame = calloc(1, sizeof(IplImage));
{
frame->nSize = sizeof(IplImage);
frame->ID = 0;
frame->nChannels = 3;
frame->depth = IPL_DEPTH_8U;
frame->dataOrder = 0;
frame->origin = 0;
frame->width = w;
frame->height = h;
frame->roi = NULL;
frame->maskROI = NULL;
frame->imageData = (void *)_ip;
frame->widthStep = (rowBytes / 4 * 3);
frame->imageDataOrigin = (void *)_ip;
}
return frame;
}
- (void)addAlphaChanelWithWidth:(int)w
height:(int)h
imageData:(unsigned char *)oq
{
int x, y;
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
_op[(w*4) * y + x * 4 + 0]= oq[(w*3) * y + x * 3 + 0];
_op[(w*4) * y + x * 4 + 1]= oq[(w*3) * y + x * 3 + 1];
_op[(w*4) * y + x * 4 + 2]= oq[(w*3) * y + x * 3 + 2];
_op[(w*4) * y + x * 4 + 3]= 255;
}
}
}
@end

O_AOB_OutputImageProvider.h
#import <Cocoa/Cocoa.h>
@interface O_AOB_OutputImageProvider : NSObject <QCPlugInOutputImageProvider>
{
void *_baseAddress;
NSUInteger _rowBytes;
NSString *_format;
NSRect _bounds;
CGColorSpaceRef _cgColorSpaceRef;
}
- (id)initWithBuffer:(void*)baseAddress
withBytesPerRow:(NSUInteger)rowBytes
pixelFormat:(NSString*)format
forBounds:(NSRect)bounds
colorSpaceRef:(CGColorSpaceRef)cgColorSpaceRef;
@end

O_AOB_OutputImageProvider.m
#import "O_AOB_OutputImageProvider.h"
@implementation O_AOB_OutputImageProvider
- (id)initWithBuffer:(void*)baseAddress
withBytesPerRow:(NSUInteger)rowBytes
pixelFormat:(NSString*)format
forBounds:(NSRect)bounds
colorSpaceRef:(CGColorSpaceRef)cgColorSpaceRef
{
if(self = [super init]) {
_baseAddress= baseAddress;
_rowBytes= rowBytes;
_format= [format retain];
_bounds= bounds;
_cgColorSpaceRef= cgColorSpaceRef;
}
return self;
}
- (void) dealloc
{
[_format release];
[super dealloc];
}
- (NSRect) imageBounds
{
return _bounds;
}
- (CGColorSpaceRef) imageColorSpace
{
return _cgColorSpaceRef;
}
- (NSArray*) supportedBufferPixelFormats
{
return [NSArray arrayWithObjects: _format,
nil];
}
- (BOOL) renderToBuffer:(void*)baseAddress
withBytesPerRow:(NSUInteger)rowBytes
pixelFormat:(NSString*)format
forBounds:(NSRect)bounds
{
memcpy(baseAddress, _baseAddress, _rowBytes*_bounds.size.height);
return YES;
}
@end


動作画像はまた今度

2008年10月15日水曜日

QCのパッチ / OpenCVのFaceDetecotrを入れてみる(再度)...

追記(2009/3/1):入出力の扱いはこっちがただしいかも.

追記(2009/2/15):
コロッと書くのを忘れていたが,出力部に関してはこちらを参照のこと!


先日のQRコードネタFaceDetector側も修正してみた.

#import <Quartz/Quartz.h>
#include <cv.h>
@interface OpenCV_FaceDetectorPlugIn : QCPlugIn
{
CvHaarClassifierCascade *cascade;
IplImage *src_img;
int prevW;
int prevH;

}
@property(assign) id<QCPlugInInputImageSource> inputSourceImage;
@property double outputHeight;
@property double outputWidth;
@property double outputY;
@property double outputX;
@property BOOL outputHasFound;

@end
...
@implementation OpenCV_FaceDetectorPlugIn
@dynamic inputSourceImage;
@dynamic outputHeight, outputWidth, outputY, outputX;
@dynamic outputHasFound;

...
- (id) init
{
if(self = [super init]) {
cascade= nil;
src_img= nil;
prevW= 0;
prevH= 0;

}
return self;
}...
- (BOOL) startExecution:(id<QCPlugInContext>)context
{
NSBundle* mainBundle = [NSBundle bundleWithIdentifier:@"com.yourcompany.OpenCV_FaceDetector"];
const char *cascade_name = [[mainBundle pathForResource:@"haarcascade_frontalface_default" ofType:@"xml"] UTF8String];
cascade = (CvHaarClassifierCascade *) cvLoad (cascade_name, 0, 0, 0);

return YES;
}
...
- (BOOL) execute:(id<QCPlugInContext>)context atTime:(NSTimeInterval)time withArguments:(NSDictionary*)arguments
{
id<QCPlugInInputImageSource> image= self.inputSourceImage;
if (!image) {
return YES;
}

[image lockBufferRepresentationWithPixelFormat:QCPlugInPixelFormatBGRA8
colorSpace:[image imageColorSpace]
forBounds:[image imageBounds]];
{
if (src_img==nil
|| prevW!=[image bufferPixelsWide]
|| prevH!=[image bufferPixelsHigh]){
if (src_img!=nil) {
cvReleaseImage(&src_img);
}
src_img= cvCreateImage(cvSize([image bufferPixelsWide], [image bufferPixelsHigh]), IPL_DEPTH_8U, 4);
prevW= [image bufferPixelsWide];
prevH= [image bufferPixelsHigh];
}
src_img->imageData= [image bufferBaseAddress];
//src_img->imageDataOrigin= [image bufferBaseAddress];


IplImage *src_gray = cvCreateImage (cvGetSize (src_img), IPL_DEPTH_8U, 1);
CvMemStorage *storage = cvCreateMemStorage (0);
cvClearMemStorage (storage);
cvCvtColor (src_img, src_gray, CV_BGRA2GRAY);
cvEqualizeHist (src_gray, src_gray);
CvSeq *faces = cvHaarDetectObjects (src_gray, cascade, storage, 1.11, 4, 0, cvSize (40, 40));
int i;
double resultA= 0.0;
CvRect *resultR;
for (i = 0; i < (faces ? faces->total : 0); i++) {
CvRect *r = (CvRect *) cvGetSeqElem (faces, i);
double tmpA= r->width * r->height;
if (resultA<tmpA) {
resultA= tmpA;
resultR= r;
}
}

self.outputHasFound= NO;
if (resultA>0.0) {
self.outputHasFound= YES;
self.outputX= resultR->x;
self.outputY= resultR->y;
self.outputWidth= resultR->width;
self.outputHeight= resultR->height;
}


cvReleaseImage (&src_gray);
cvReleaseMemStorage (&storage);

}
[image unlockBufferRepresentation];

return YES;
}
...
- (void) stopExecution:(id<QCPlugInContext>)context
{
if (src_img!=nil) {
cvReleaseImage(&src_img);
}

}
@end

一応,
イタリック体はIplImageを利用するための記述.
ボールド体は顔検出パッチ用の記述
というつもり.

追加ライブラリは
libcv.dylib, libcxcore.dylib
である.
追加リソースは
haarcascade_frontalface_default.xml (/opt/local/share/opencv/haarcascades/haarcascade_frontalface_default.xml)
である.
プロジェクトのインスペクタで以下を設定した.
アーキテクチャ/アーキテクチャ: Native Architecture of Build Machine
検索パス/ヘッダ検索パス: /opt/local/include/opencv


opencvをportで入れると/opt/local以下に入る.入れ方はこう
> sudo port install opencv


間違いをご指摘いただければ幸いです.

2008年10月13日月曜日

で,libdecodeqrをいつものことながらQuartz Composerに入れてみる

で,いつものことながらやってみた.
面倒なので今回はコードのみ.(QRDecoderという名前でプロジェクトを起こした.)


#import <Quartz/Quartz.h>
#import <cv.h>
#import <decodeqr.h>
@interface QRDecoderPlugIn : QCPlugIn
{
IplImage *src_img;
int prevW;
int prevH;

}
@property(assign) id<QCPlugInInputImageSource> inputSourceImage;
@property(assign) NSString *outputString;
@end
...
@implementation QRDecoderPlugIn
@dynamic inputSourceImage;
@dynamic outputString;
...
- (id) init
{
if(self = [super init]) {
src_img= nil;
prevW= 0;
prevH= 0;

}
return self;
}
...
- (BOOL) execute:(id<QCPlugInContext>)context atTime:(NSTimeInterval)time withArguments:(NSDictionary*)arguments
{
id<QCPlugInInputImageSource> image= self.inputSourceImage;
if (!image) {
return YES;
}
[image lockBufferRepresentationWithPixelFormat:QCPlugInPixelFormatBGRA8
colorSpace:[image imageColorSpace]
forBounds:[image imageBounds]];
if (src_img==nil
|| prevW!=[image bufferPixelsWide]
|| prevH!=[image bufferPixelsHigh]){
if (src_img!=nil) {
cvReleaseImage(&src_img);
}
src_img= cvCreateImage(cvSize([image bufferPixelsWide], [image bufferPixelsHigh]), IPL_DEPTH_8U, 4);
prevW= [image bufferPixelsWide];
prevH= [image bufferPixelsHigh];
}
src_img->imageData= [image bufferBaseAddress];


//----content--------------------------------------------
{
self.outputString= @"";
QrDecoderHandle decoder= qr_decoder_open();
{
short stat=qr_decoder_decode_image(decoder, src_img, 25, 10);
QrCodeHeader header;
if(qr_decoder_get_header(decoder, &header)){
char *buf= malloc(sizeof(unsigned char) * header.byte_size+1);
qr_decoder_get_body(decoder,(unsigned char *)buf,header.byte_size+1);
//NSLog(@"%s", buf);
self.outputString= [NSString stringWithCString:buf encoding:NSShiftJISStringEncoding];
free(buf);
}
}
qr_decoder_close(decoder);
}
//-----------------------------------------------------

[image unlockBufferRepresentation];
return YES;

}
...
- (void) stopExecution:(id<QCPlugInContext>)context
{
if (src_img!=nil) {
cvReleaseImage(&src_img);
}

}
@end

追加ライブラリは
libcv.dylib, libcxcore.dylib, libdecodeqr.dylib(libdecodeqr.0.9.3.dylib)
である.当然libdecodeqr.dylibは先のエントリーで作ったものだ.
イタリックにしたところはIplImageを使うためのおまじない

で,やるとこうなる.

(画像はlibdecodeqr-0.9.3に入ってた画像のimg/01-4.jpg)


間違いあればご指摘いただきたく,よろしくお願いいたします.

2008年10月10日金曜日

QRコードのデコーダライブラリ libdecodeqr-0.9.3 をMacOSXでコンパイルする

QRコードって何バイト情報をもてるのか?という疑問からはじまってちょっと調べてたんだけどふとQRコードのデコーダってフリーであるのか?という疑問で調べた.JavaもあったがC/C++のものがこちら

libdecodeqr


でみてみるとOpenCVが必要ってかいてある.おっ,この前入れたよ.
MacOSXでやった方のページも発見.でも途中で
プログラマの道具箱: osxでlibdecodeqr-0.9.3をコンパイル
とにかくさきにすすみたいので直接
libdecodeqr-0.9.3/src/libdecodeqr /Makefile
を書き換えて、makeだけできるようにする。

うー.その中身もおしえてー.と思ったのだが,まぁできる保証があるというのはありがたい.
で,やってみてその記録を書いておく.

1.ソースコードの取得
0.9.3を同ページからdownload.で展開.
libdecodeqr-0.9.3/srcがソースコードのホーム(?).

2.configureを実行する
portsでopencvを入れたので/opt/local/の下にOpenCV関連は入っている.
で,それに合わせる必要あある.先ほどのサイトのアドバイスもいただき,とりあえずこんな感じでconfigureが成功した.
> LDFLAGS="$LDFLAGS -L/opt/local/lib";export LDFLAGS
> CPPFLAGS="$CPPFLAGS -I/opt/local/include/opencv";export CPPFLAGS
> ./configure --prefix=/opt/local --with-cv=cxcore


3.そのままmakeしてみる.
> make
...
o galois.o imagereader.o libdecodeqr.o
ld -o libdecodeqr.so.0.9.3 bitstream.o codedata.o container.o ecidecoder.o formatinfo.o galois.o imagereader.o libdecodeqr.o -L/opt/local/lib -shared -soname libdecodeqr.so.0 -lcxcore
ld: unknown option: -shared
make[1]: *** [libdecodeqr.so.0.9.3] Error 1
make: *** [libdecodeqr] Error 2
>
これが噂のでもmakeで、失敗…..
MacOS Xのldに-sharedはないらしいんです .
原因はlibraryがdylib形式(?)だから?,
こちらに対策が書かれている

4.そこでlibdecodeqrへ移動.
> cd libdecodeqr

つまるところldでなくg++, -sharedでなく-dynamiclibで頑張るしかないらしい.
あとはopencv用のlib環境を指定すればよいのだろうということでこんな感じ.
>g++ -o libdecodeqr.0.9.3.dylib -dynamiclib -L/opt/local/lib -lcxcore -lcv bitstream.o codedata.o container.o ecidecoder.o formatinfo.o galois.o imagereader.o libdecodeqr.o
>

ということでlibdecodeqr.0.9.3.dylibができた!.あとこのこが使うheaderはMakefileを見ると
decodeqr.h qrerror.h qrtypes.h

らしいので後でインストールする時には気をつける事.

5.いざサンプル作成
いざサンプルなのだが当然Makefileを使うとまたいろいろ面倒.そこで
libdecodeqr-0.9.3/src/sample/webcam
へ移動し,先ほどのサイトのコマンドをそのまま利用させていただく,
> g++ `pkg-config --cflags opencv` `pkg-config --libs opencv` -ldecodeqr -I../../libdecodeqr -L../../libdecodeqr webcam.cpp
#opencv周りを一撃で,'pkg-config --cflags --libs opencv'でも良い.

でできたa.outを実行する(MBPなので内蔵カメラが使用されました).

6.サンプルで遊ぶ
同封されているイメージをARToolkitの時と同様にAirSharingでiPhoneへ移して表示させたものを内蔵カメラで撮影してみる.
でスペースキーで認識.うまく認識されるとこんな感じ(画像は添付されていた01-1.jpg(若干拡大)).

取得された文字列はターミナルに出る.(これがなんて出たかはご自身でどうぞ.).ちなみにサンプルに含まれていた別画像のデコードされた日本語はSJISで出てきてた.


ということで以上でした.
間違いあればご指摘いただけると幸いです.

2008年10月7日火曜日

BEAT CRUSADERS風のお面とまではいかなかったが.

追記(2009/3/1):入出力の扱いはこっちがただしいかも.

追記(2008/10/16):
修正してみた



ネットをさまよっていたら出会ったこちらのサイト
?"BEAT CRUSADERS風"ってなに(BEAT CRUSADERSサイト(音でます))?
と,やっているうちに先日のFace Detecotrを使ってみようと思いちょっと出力周りを変更してやってみた.

対象はiPhoneアプリのAirSharingに入っていたDemo画像.
色の変換で二値化ってどのパッチなんでしょう?時間がないのでとりあえずポスタライズして反転…(目的を見失う).

相変わらず動画入力であっても動画処理できるほど速度がでない(私がへぼい).

2008年9月30日火曜日

OpenCVのナニカをQuartz ComposerのPatchに入れてみる

追記(2009/9/19):入出力の扱いはこっちがただしいかも.

追記(2009/3/1):入出力の扱いはこっちがただしいかも.

追記(2009/2/15):
コロッと書くのを忘れていたが,出力部に関してはこちらを参照のこと!

追記(2008/10/16):
修正してみた

追記(2008/10/03):
OpenCVをMacにいれるのはこちらの"やったこと/1.OpenCVを入れる"を参照してください.


という例にならんかな.まぁ前のエントリの勢いなだけです.
これ.
ポートレートのオリジナルはこちら(Photo by Joi)
ただ,この機能はそれなりに重たいので画像をクリックして右下をみてもらいたいのですが
0.84 FPS
….

それだけ.


以下記録.
1.ライブラリを入れる
zlib同様に/opt/local/libを開いてDnDしておく.
> pkg-config --cflags opencv --libs opencv
-I/opt/local/include/opencv -L/opt/local/lib -lcxcore -lcv -lhighgui -lcvaux -lml
>
の結果からとりあえず
libcv.dylib, libcxcore.dylib, libcvaux.dylib, libml.dylib, libhighgui.dylib
あたりになる.

2.ヘッダファイルの検索先を指定する
プロジェクトの情報/ビルド(タブ)/検索パス/ヘッダ検索パス
/opt/local/include/opencv
を追加する.

3.アーキーテクチャを指定する
portsがどうしているかわからないけどとりあえず自身のアーキテクチャしかどうにもできないらしい.(っていうかOpenCVが入れられるのがIntelのみなのかもしれない.)
ので,
プロジェクトの情報/ビルド(タブ)/アーキテクチャ/アーキテクチャ
Native Architecture of Build Machine
に切り替えておく.

4.画像の入出力まわり
あってるかわからんがこんな感じ.

...
@interface OpenCV_FaceDetectorPlugIn : QCPlugIn
{
...
}
...
@property(assign) id<QCPlugInInputImageSource> inputSourceImage;
@property(assign) id<QCPlugInOutputImageProvider> outputResultImage;
...
@end
//---------------------------------------------------------
...
@implementation OpenCV_FaceDetectorPlugIn
@dynamic inputSourceImage, outputResultImage;
...
- (BOOL) execute:(id<QCPlugInContext>)context atTime:(NSTimeInterval)time withArguments:(NSDictionary*)arguments
{
id<QCPlugInInputImageSource> image= self.inputSourceImage;
if (!image) {
return YES;
}
[image lockBufferRepresentationWithPixelFormat:QCPlugInPixelFormatBGRA8
colorSpace:[image imageColorSpace]
forBounds:[image imageBounds]];
void *p= malloc([image bufferBytesPerRow]*[image bufferPixelsHigh]);
memcpy(p, [image bufferBaseAddress], [image bufferBytesPerRow] * [image bufferPixelsHigh]);
IplImage *src_img = calloc(1, sizeof(IplImage));
{
src_img->nSize = sizeof(IplImage);
src_img->ID = 0;
src_img->nChannels = 4;
src_img->depth = IPL_DEPTH_8U;
src_img->dataOrder = 0;
src_img->origin = 0;
src_img->width = [image bufferPixelsWide];
src_img->height = [image bufferPixelsHigh];
src_img->roi = NULL;
src_img->maskROI = NULL;
src_img->imageData = p;
src_img->widthStep = [image bufferBytesPerRow];
src_img->imageDataOrigin= p;
}

[image unlockBufferRepresentation];

//op.

self.outputResultImage=
[context outputImageProviderFromBufferWithPixelFormat:QCPlugInPixelFormatBGRA8
pixelsWide:src_img->width
pixelsHigh:src_img->height
baseAddress:src_img->imageData
bytesPerRow:src_img->widthStep
releaseCallback:_BufferReleaseCallback
releaseContext:NULL
colorSpace:[image imageColorSpace]
shouldColorMatch:NO];
return YES;
}
...
@end
IplImageへの複写(ボールド体部)はほんとにこれでいいか不明で不安.

5.リソースへのアクセス(パスの取得)
 NSBundle* mainBundle = [NSBundle bundleWithIdentifier:@"com.yourcompany.OpenCV_FaceDetector"];
const char *cascade_name = [[mainBundle pathForResource:@"haarcascade_frontalface_default" ofType:@"xml"] UTF8String];

Identifierはプロジェクト内のInfo.plistにある"Bundle identifier"参照.

参考:こちらとかもスナップが豊富で参考になる.
XcodeでOpenCV開発 - MineAPの(開発)日記
http://d.hatena.ne.jp/MineAP/20080112/1200125226

2008年9月29日月曜日

「Haar-like特徴を使った顔検出器」ってのを使ってみた.

工学ナビさんのところのこちらの記事にあった「Haar-like特徴を使った顔検出器」というのを試してみたいなぁー.というそれだけの話.

環境
MBP (Intel) / MacOS X 10.5.5 / MacPorts 1.600

やったこと
1.OpenCVを入れる
>sudo port install opencv
Password:
---> Fetching opencv
---> Attempting to fetch opencv-1.0.0.tar.gz from http://downloads.sourceforge.net/opencvlibrary
---> Verifying checksum(s) for opencv
---> Extracting opencv
---> Configuring opencv
---> Building opencv with target all
---> Staging opencv into destroot
---> Installing opencv 1.0.0_0
---> Activating opencv 1.0.0_0
---> Cleaning opencv
>

サックリ.


2.サンプルのコードを写す
opencv.jp - OpenCV: 物体検出(Object Detection)サンプルコード -
sample.cとした.


3.コンパイル
OpenCV for OSX インストール編を参考に.
> gcc sample.c `pkg-config --cflags opencv --libs opencv`
>

サックリ.(無指定なので"a.out"ができているはず)


4.設定ファイルの調達
学習によってあらかじめ獲得された,分類器のカスケードが記述されたxmlファイル
というのが必要らしい.
OpenCVのサンプルに付属する正面顔画像学習結果の1つである,"haarcascade_frontalface_default.xml"を利用する
というのがあるらしい.
> find /opt -name "haarcascade_frontalface_default.xml" -print
/opt/local/share/opencv/haarcascades/haarcascade_frontalface_default.xml
/opt/local/var/macports/software/opencv/1.0.0_0/opt/local/share/opencv/haarcascades/haarcascade_frontalface_default.xml
>

ということで
> cp /opt/local/share/opencv/haarcascades/haarcascade_frontalface_default.xml .


5.人画像を探すと実行
Googleで検索

実行は
> ./a.out [画像ファイル]

です(コンパイルで指定していなければa.out).


動作の様子

まずはスタンダードそうなこちらで試す.
Photo by Joi

では二人
Photo by babasteve

もっちょっとたくさん
Photo by crouch/photo
…少し横向きの方は無理としても女性は前髪あたりが原因かしら?(検出数の制限とかではないみたいだしね.)


という遊び.
#思ったよりすんなりできた.


追記:OpenCVのこのページをみて思ったのは「機械学習周りが色々あって面白そう」w.