C#でOpenCV

凄いことに先人がいて、SharperCVを利用するとC#からOpenCVを利用することができます。それには、ここのサイトで配布しているページの下のほうにあるSoftware Releaseの部分にある、Installation Package:(msi)をダウンロードし、インストールします。
インストールの最初に以下のようなメッセージが出る場合があります。
これは「Microsoft .NET Framework Version 1.1 再頒布可能パッケージ」をインストール必要があります。



この中にC#のコンパイラなども含まれています。
上記のが出なかった場合には下記のようなウィンドウが出ます。「Next」を押します。



すると次のようなウィンドウが出ます。普通はこのままでいいでしょう。「Next」を押します。



インストールの最後の確認が出ます。「Next」を押します。



すると次のようなウィンドウが出てインストールが始まります。



暫くするとインストールが終わり、次のようなウィンドウが出ます。「Close」を押します。

インストールができたら、コンパイル・実行してみましょう。 C:\SharperCV\samples\SampleContourの中を見てみましょう。

この中に、SampleContour.csprojがあります。これをダブルクリックします。



するとVisual Studioを使用するのが初めての時は下のようなウィンドウが出ますので、C#にするか全般的な開発環境設定にしてください。私は全般的な開発環境設定にしました。

すると次のように変換ウィザードが出ますので、「次へ」あるいは、すぐに「完了」ボタンを押します。



次に、下のようなメッセージが出ますが、気にせず「はい」を押します。



変換が完了すると次のように出ます。「閉じる」をクリックします。



変換されなかったファイルが3つあるとか・・・。



App.icoはbinフォルダにあるのでこれを指定するか、コピーして持ってきます。



ビルドする時に、保存を促されますが、そのままソリューションを「保存」します。



ビルドすると、いきなり次のようなエラーにぶつかります。



参照設定のopenCVWrapperに問題があることが分かります。



これは「参照設定」を右クリックし、「参照の追加」で次のようなウィンドウが出ます。参照タブを選び、
C:\SharperCV\bin\openCVWrapper.dll
を選択し、OKを押します。



これでコンパイルが出来るようになり、エラーが無くなります
ところが、この設定でビルド・実行すると次のようなウィンドウが出て、エラーになります。



これは何故か・・・・? 答えは、SharperCVは、一番最初に出てきたメッセージに関係あります。

↓これです。



つまり、SharperCVは、.NET Framework version 1.1対応なのです。Visual Studio 2008は2.0以上しか選択できません。従って、Visual Studio 2008では多分コンパイル・実行は出来ません。dllのフォーマットが変更されたようです。ですから、Visual Studioはとりあえず諦めて、コマンドプロンプトでのコンパイルを試みてみます。
それには、path環境変数に.NET Framework version 1.1のC#コンパイラのパスを含めるように設定します。次のようなバッチファイルを利用します。

@echo off
set path=C:\Windows\Microsoft.NET\Framework\v1.1.4322;C:\SharperCV\bin;%path%
また、コンパイルには参照設定の指定をしますので、やはり次のようなバッチファイルを作っておくと良いでしょう。
csc /r:openCVWrapper.dll %1
このファイル名をccc.bat とした場合、使い方は、
ccc filename
となります。当然、ccc.batはパスの通ったディレクトリ、例えば、C:\SharperCV\binに入れておきます。

先ほどの、SampleContourをコンパイルしてみましょう。
ソースと同じ場所に実行時に使用するdllをコピーしておきましょう。

highguisharper.dll、openCVWrapper.dll、cv.dllでOKだと思います。その問題によって他のdllもコピーが必要になります。
これでコンパイルすれば、実行も正常に行われます。

Visual Studio 2008問題

さて、Visual Studio 2008でコンパイル・実行するにはどうしたらよいのでしょうか。
本家は、SharperCVで、配布版は上記で説明したように.NET Framework version 1.1用にコンパイルされているので、2008では利用できないという結果でした。ですから、dllをコンパイルしなおせば良い訳です。ソースは、 ここにありますが、配布版とはバージョンが多少異なっています。また、エラーが多数出るのでこれと格闘しながらdllを作ると出来上がります。また、元は古いOpenCVに対応するように出来ている(0.9x)ので新しいOpenCVに対応するようにするためにはさらに変更が必要になります。

OpenCV自体はここからダウンロードします。versionが1.0なので上記SharperCVでは使えません。・・・では困るので、少しソースをいじって少しは使えるようにしてみました。OpenCVの機能を全て使えるようにするには、かなりの根気が必要です。とにかくopenCVWrapper.dllと、多分cvshim.dllも要るようなので使ってみてください。チェック用のソースを下に示しますが、環境はOpenCV1.0がインストールされている必要があります。このソースは、C:\Program Files\OpenCV\samples\c\squares.cの四角検出の四角検出部分を抜いたものです。早い話がpic1.png~pic6.pngを表示するだけです。ですから、ソースと同じ所にこれらのファイルがある必要があります。また、openCVWrapper.dllも同じディレクトリにある必要があります。また、当然ですが、OpenCVのdllもPATHが通っている必要があります。
using System;
using SharperCV;

namespace squares
{
  public class squares {
    CvImage img0 ;
    const string wndname = "ImageWin";
    CvWindow  imageWin;

    public squares(){
      imageWin = new CvWindow(wndname);
    }

    string [] names = { "pic1.png", "pic2.png", "pic3.png",
                  "pic4.png", "pic5.png", "pic6.png"};
    static void Main(string[] args)
    {
      new squares().go();
    }
    
    public void go()
    {
      foreach( String name in names)
      {
        Console.WriteLine(name);
        img0 = new CvImage( name, 1 );
        if( img0 == null )
        {
            Console.WriteLine("Couldn't load {0}", name );
            continue;
        }
        imageWin.Image = img0;
        int key = CvWindow.WaitKey(0);
        if( key == 27 ) break;
      }
    }
  }
}
次に、USBカメラからの画像をそのまま表示するプログラムです。終了はqを押すかESCキーを押します。画像提示中にスペースキーを押すとtest.jpgというファイル名で保存されます。
using System;
using SharperCV;

//SharperCVによるカメラキャプチャ&jpeg保存

namespace Camera
{
  class Camera
  {
    static void Main()
    {
      CvWindow windowCapture;
      CvCapture capture;
      CvImage captureImage;
      CvSize sizeCapture;
      int key = 0;

      windowCapture = new CvWindow("USBカメラ qで終了", true);
      capture = new CvCapture(-1);
      sizeCapture.width = 320;                 // window size
      sizeCapture.height = 240;                // window size
      captureImage = new CvImage(sizeCapture, BitDepths.IPL_DEPTH_8U, 3);

      do{
        if((captureImage = capture.QueryFrame()) == null)
          break;
        windowCapture.Image = captureImage;       // display
        key = CvWindow.WaitKey(1);
        if(key == ' ') 
          captureImage.SaveImage("test.jpg");
      }while((key != 'q') && (key != 27) );
      windowCapture.Close();
    }
  }
}