2013/02/19

コンピュータビジョン オンライン講義

OpenCVで色々検索してたら、コンピュータビジョンのオンライン講義を見れるサイトがあることを知りました。

CourseraJapanese
https://sites.google.com/site/courserajapanese/

基本は英語ですが、一部日本語字幕が付いているものもあります。
CourseraJapaneseには3つのコースがまとめられていました。
以下はそのコースの内容となります。


Computer Vision: The Fundamentals by Jitendra Malik

  1. Overview
  2. Fundamentals of Image Formation
  3. Rotations and translations
  4. Dynamic Perspective
  5. Binocular Stereo
  6. Radiometry
  7. Image processing
  8. Object Recognition


Image and video processing by Guillermo Sapiro

  1. Introduction to image and video processing
  2. Image and video compression
  3. Spatial processing 
  4. Image restoration
  5. Segmentation  
  6. Geometric PDEs 


Machine Learning by Andrew Ng

  1. Introduction
  2. Linear Regression with One Variable
  3. Cost Function
  4. Gradient Descent
  5. What's Next

元のcoursera.orgというサイトは、色々な大学の講義が無料で視聴できるサイトとのこと。コンピュータビジョンの他にもロボット工学などあるようなので、面白そうなものを見てみたいと思います(内容と英語が理解できるかはさておき)。
https://www.coursera.org/course/computervision

ではまた。




OpenCV-javaで輪郭検出

メインのデスクトップが使えない時はMacBook AirのVirtualBox上にUbuntu12.04を入れて開発をしています。仮想PCバンザイ。

さて、年賀状のお年玉抽選チェックアプリの開発をサボっていましたが、
OpenCVのJavaバインディングも入れたところなのでJavaで続きをやってみます。

SVMの部分は後にして、数字を検出して1個ずつ切り出す部分を作りましょう。

切り出す処理は、
  • 輪郭を検出する
  • 輪郭の点列を囲む四角形を計算する
  • 四角形を切り出す
といった処理でできます。

OpenCVの関数を使ってサクッと実装してみましょう。

import java.util.ArrayList;
import java.util.List;
import org.opencv.core.*;
import org.opencv.highgui.Highgui;
import org.opencv.imgproc.Imgproc;

public class Main {

    /**
     * 輪郭を抽出して、輪郭を囲む四角形を描画します。
     */
    public static void main(String[] args)
    {
        System.loadLibrary("opencv_java");
        Mat src= Highgui.imread("num.png",0);
        Mat hierarchy=Mat.zeros(new Size(5,5), CvType.CV_8UC1);
        Mat invsrc=src.clone();
        Core.bitwise_not(src, invsrc);
        
        List<MatOfPoint> contours=new ArrayList<MatOfPoint>();
        
        //一番外側のみでOK
        Imgproc.findContours(invsrc, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_TC89_L1);
        Mat dst=Mat.zeros(new Size(src.width(),src.height()),CvType.CV_8UC3);
        Scalar color=new Scalar(255,255,255);
        
        Imgproc.drawContours(dst, contours, -1, color,1);
        
        int i=0;
        for(i=0;i<contours.size();i++)
        {
            MatOfPoint ptmat= contours.get(i);

            //頂点描画
            /*
             int k=0;
             for(k=0;k<ptmat.height();k++)
            {
                double[] m=ptmat.get(k, 0);
                vertex.x=m[0];
                vertex.y=m[1];
                Core.circle(dst, vertex, 2, color,-1);
            }*/
            
            color=new Scalar(255,0,0);
            MatOfPoint2f ptmat2 = new MatOfPoint2f( ptmat.toArray() );
            RotatedRect bbox=Imgproc.minAreaRect(ptmat2);
            Rect box=bbox.boundingRect();
            Core.circle(dst, bbox.center, 5, color,-1);
            color=new Scalar(0,255,0);
            Core.rectangle(dst,box.tl(),box.br(),color,2);
            
        }
        Highgui.imwrite("test.png",dst);
    }
}

サンプル画像:
結果:

これで切り出す領域を指定できるようになりました。
ただし、輪郭グループの順番は左側から始まるわけではないので、領域の中心点のX座標を元にしてソートをかけてやる必要があります。

Cだと輪郭がCvSeq型でちょっと使いにくかったのですが、JavaだとMatOfPoint型になりました。
MatOfPoint型はN行1列の行列で、要素一つにdoubleの配列(x,yに相当)が格納されていました。CvSeqよりも操作しやすくなった気がします。

次は以前作った数字のSVMファイルを読み込んで、文字認識を行うところもJavaで作ってみましょう。

ではまた。

2013/02/17

デスクトップJavaからOpenCVを使う

OpenCV2.4.4から、デスクトップ用のJavaもサポートされるようになりました。
今日時点(2013-02-17)では、OpenCV2.4.4はベータ版として入手することができます。


Javaバインディングのチュートリアルがあったので、早速読んでみました。
毎度おなじみ適当翻訳です。画像や長いコードは省略してますので、元ページを参照ください。

Introduction to Java Development

=============================================

Java開発の始めかた

OpenCV2.4.4から、OpenCVはデスクトップJavaをAndroid開発向けと同じようなインターフェースでサポートしました。このガイドでは、JavaやScalaでOpenCVを使ったアプリケーションの作り方を説明します。私たちはアプリケーションをビルドするために、Eclipse,Apache AntやSimple Build Tool (SBT)を使用します。

このガイドを読んだあとにIntroduction into Android Development チュートリアルも読んでみましょう。

このガイドですること

このガイドでは、私達は

  • デスクトップJavaをサポートしたOpenCVを入手します
  • Ant,EclipseまたはSBTプロジェクトを作成します
  • ScalaまたはJavaを使って、簡単なOpenCVアプリケーションを書きます

同じ手順がsamples/javaフォルダを作るために使われたので、迷った場合はこれらのファイルを参照してください。

デスクトップJavaをサポートしたOpenCVを入手する
まずはJavaバインディングを含んでいるOpenCVのバージョン2.4.4が必要です。
一番簡単な手順は、SourceForgeのOpenCVリポジトリからバージョン2.4.4またはそれ以上のパッケージをダウンロードすることです。
 注:WindowsユーザはJavaを使った開発に必要なファイルをopencv/build/javaフォルダで見つけることができます。他のOSの場合は、これらをソースからビルドする必要があります。

もう一つは、OpenCVのgitリポジトリから取得する方法です。また、OpenCVのJavaバインディングをビルドするには、JDK (Oracle/Sun JDK 6か7が推奨),Apache AntとPython v2.6以上がインストールされていなければなりません。

OpenCVをビルドする
さぁ、OpenCVをビルドしましょう

 git clone git://github.com/Itseez/opencv.git
 cd opencv
 git checkout 2.4
 mkdir build
 cd build

MakefilleやVisual Studio用のソリューションを生成するには、
    cmake -DBUILD_SHARED_LIBS=OFF ..
オプションを使います。
注: OpenCVライブラリを静的ライブラリセットとしてビルドした場合(-DBUILD_SHARED_LIBS=OFFオプション)、Javaバインディングの動的ライブラリは十分な機能を持っています(他のOpenCVライブラリに依存していませんが、OpenCVのコードをすべて持っています)

CMakeの出力を調べて、javaがビルドされるモジュールに含まれているかを確認してください。もし無ければ、javaをビルドするための依存関係が満たされていません。CMakeの出力を確認して、何が足りないかをトラブルシューティングする必要があります。

ではビルドを始めましょう
     make -j8
または
     msbuild /m OpenCV.sln /t:build /p:Configration=Release /v:m

これでJavaインターフェースを含んでいるjarファイル(bin/opencv_2.4.4jar)とネイティブの動的ライブラリ(bin/Release/opencv_java244.dll か bin/libopencv_java244.so)がビルドされます。これらのファイルは後で使います。

簡単なJavaサンプルとそれ用のAntビルドファイルを作る
省略

Eclipseで簡単なJavaプロジェクトを作る

EclipseIDEでOpenCVを使ったJavaプロジェクトの可能性を見てみましょう。
・Eclipseで新しいワークスペースを作ります
・File -> New -> Java projectを選んで、Javaプロジェクトを新しく作ります。名前はHelloCVとしておきます。
・Project PropertiesダイアログのJava build pathタブを開きます。そして、追加のライブラリ(OpenCV)への参照を追加します。 (私の環境では/usr/local/share/OpenCV/javaでした)

・アプリケーションのエントリポイントを持った新しいJavaクラス(Mainクラス)を追加します。

・OpenCV用の呼び出しコードを追加します。
    import org.opencv.core.CvType;
    import org.opencv.core.Mat;

    public class Main {
        public static void main(String[] args) {
            System.loadLibrary("opencv_java244");
            Mat m  = Mat.eye(3, 3, CvType.CV_8UC1);
            System.out.println("m = " + m.dump());
        }
    }

・Runを押して、単位行列がコンソールに表示されることを確認しましょう。

ScalaとJavaを使ったSBTプロジェクトのサンプルを作る
省略


OpenCV jarファイルをコピーして、簡単なアプリケーションを作る
OpenCVを使って、簡単な顔検出アプリケーションを作ってみましょう。
まず、libフォルダを作ってOpenCVのjarファイルをその中にコピーします。
標準では、SBTはlibフォルダを検索パスに自動的に追加します。オプションで、sbt eclipce コマンドを実行するとEclipseプロジェクトをアップデートすることもできます。
次に、src/main/resourcesフォルダを作って、Lenaの画像をそこにコピーします。
lena.pngがそのフォルダにあることを確認してください。resouresフォルダはJavaアプリケーションの実行時に利用可能になります。
次に、lbpcascade_frontface.xmlファイルを opencv/dataフォルダからresourcesディレクトリにコピーしてきます。
 cp /data/lbpcascades/lbpcascade_frontalface.xml src/main/resources/

そしてsrc/main/java/HellloOpenCV.javaファイルを作ります。
 コード省略

System.loadLibrary("opencv_java244")がOpenCVの関数を実行する前に確実に一度だけ実行されることを確認してください。loadLibraryを実行しなかった場合は、UnsatisfiedLinkエラーが発生します。また、すでにOpenCVライブラリが読み込まれている状態で更に読み込もうとした場合にも発生します。
では sbt runを実行して、顔検出アプリを起動してみましょう。

==============================================



というわけで早速OpenCV 2.4.4を持ってきましょう
今回はgitのリポジトリをもらってきました。
  git-opencv2.4$ git clone git://code.opencv.org/opencv.git
  Cloning into 'opencv'...
  remote: Counting objects: 82644, done.
  remote: Compressing objects: 100% (24460/24460), done.
  remote: Total 82644 (delta 58152), reused 74716 (delta 51522)
  Receiving objects: 100% (82644/82644), 287.72 MiB | 436 KiB/s, done.
  Resolving deltas: 100% (58152/58152), done.

CMakeを実行したところ、
-- Could NOT find JNI (missing:  JAVA_INCLUDE_PATH JAVA_INCLUDE_PATH2 JAVA_AWT_INCLUDE_PATH)
というメッセージがでてopencv_javaがビルド対象になっていません。

OracleのJava7とAnt、Python2.7をインストールしてから下記コマンドでもう一度CMakeしました。

cmake -DBUILD_SHARED_LIBS=OFF \
-DJAVA_INCLUDE_PATH=/usr/lib/jvm/java-7-oracle/include \
-DJAVA_INCLUDE_PATH2=/usr/lib/jvm/java-7-oracl/inlclude/linux \
-DJAVA_AWT_INCLUDE_PATH=/usr/lib/jvm/java-7-oracle/jre/lib/i386  ..

これで無事ビルド対象になりました。あとはmakeしてインストールします。

   sudo make -j8 && sudo make install

(make中に"jni_md.hが見つかりません"的なメッセージが出たら、検索パスを変更してみてください)


インストールが終わったのでEclipseで単位行列を表示するチュートリアルを作ったのですが、実行時に”ライブラリないよ”というエラーが出て来ました。
チュートリアルでは
    system.loadLibrary("opencv_java244");
となっていますが、ビルドされたファイル名が libopencv_java.so なので、
    system.loadLibrary("opencv_java");
に変えるとうまく動きました。

現時点では、highguiは完全にはラップできておらず、imshowやnamedWindowなどの表示関係の関数は使用できないようです。とはいえ、デスクトップJavaでもOpenCVが使えるようになったので、Android用にコードを作るのがちょっと楽になりそうですね。

ではまた。