FormアプリからOpenCVのHighGUIを別ウィンドウで開いていたが、Bitmapオブジェクトにキャストする事で.NETアプリのPictureBoxなどに読み込む事が出来る。これにより画像処理だけ高速にC++で行い、アプリケーションのUIやネットワーク部分はC#.NETで実装するといういいとこどりが出来る。■出来た物FormにLoadImageボタンとPictureBoxを追加。LoadButtonを押すとShadowCamera.dllから呼び出しているOpenCV側のCvImageが変換されてBitmapになって出てくる関数を作った。今回作っているShadowCameraは背景を蓄積させて統計を取り、差分で人物の影だけを抜き出すライブラリなので、毎フレーム計算し続ける必要がある。runCapture()の最後でwhileループさせて実現している。1つBitmapオブジェクトを用意しておき、whileループの最後で処理結果を毎回保存しておいてそれをC#側から適当なタイミングで読みに行く実装にした。Formアプリ側から取得できる。例によってOpenCV勉強用mercurialリポジトリのchanges19としてcommitしてある。VisualStudioはC#はutf8なのにC++はshift_jisで保存されてしまい、utf8にするとビルドできなくなってしまうのでリポジトリビューアでは文字化けしてしまっている。文字化けしている部分には大したこと書いてないので無視していいし、必要ならリポジトリの左側からzipでダウンロードできる。ちなみに今回の方法は、3年以上前の開発合宿の記事に匿名様がコメントで教えてくれたSharperCVのCvImage型をSystem.Drawing.Bitmap型に変換する方法が書かれていてそれを元にした。できなかった事とかも書いてみるものだなと思った。助けをアテにしちゃいけないが■ShadowCamera.dll側の変更C++プロジェクトのShadowCameraに、System.Drawingへの参照を追加する。Bitmapクラスを使うため。}これでDLL内のshadowというBitmapオブジェクトを、DLL外から読み出す事が出来るようになった。つけるルールを把握しきれていないけど、他のC++/CLIアプリがそうやっていたので先人の作法に倣うことにする。あとはrunCapture()の最後のwhileループ内で、毎回作られるimgResultというIplImage(CvImage互換)オブジェクトをdynamic_castしてshadowに保存する。static_cast<System::IntPtr>(imgResult->imageDataOrigin)));長いので変換部分のみ抜粋。ShadowCamera.hの85~125行目がwhileループですdynamic_castやstatic_castの違いはC++の新しいキャストが参考になった。Formアプリ側の変更ボタン(buttonLoadImage)と画像を表示するためのPictureBox(pictureBoxResult)を配置。PictureBoxはSizeModeをStretchImageにしておくと自動リサイズされて便利。cam.ShadowImage();BitmapをPictureBoxのImageプロパティに突っ込むだけで表示できる。ボタンじゃなくてThreadなどで適当にsleepを入れながら読み込み続ければふつうに影カメラになる。shokai重い画像処理をC++の画像処理ライブラリであるOpenCVでやって、ネットワーク処理は慣れ親しんだC#.NETでやりたい。そこで、色々試行錯誤した結果、C#からは「処理し終わった画像を表示してくれるカメラ」に見えるような、OpenCVの処理部分を含んだDLLをC++/CLIで作ることにした。SDKのWinUser.hの6373行目あたりから文字化けしていてWinSocketが使えなかったりしたのでDLLを作るやり方に落ち着いた。この方法のメリットは、まず納得のいくOpenCVの処理をC++単体のプロジェクトでいつもどおり書いて、それをほぼコピペすればDLLができてしまうところ。ShaperCVを使う場合は全て関数を照らし合わせてC#で書き直さなければならないので面倒。Socketを使う方はよく知らない。DLLの作り方はかせいさんとこが参考になった。CLIを使う場合と使わない場合が解説されている。(今回は楽する為にCLIを使う)DLLの概要と実装方法。■今回つくるものmercurialリポジトリをアップロードした。opencv-studyしてリポジトリを複製してください。影カメラライブラリを使うFormアプリケーションの2つを作ります。C#で作ったFormアプリで、ボタンを押すとDLLに書いてあるOpenCVの処理が起動してウィンドウが開き画像処理結果が表示/毎フレーム更新される。■C++でDLLを作るまず空のソリューションを作る。ソリューション名を右クリックして新しいプロジェクト追加VC++のクラスライブラリを作成する。名前はShadowCameraにしたできたShadowCameraプロジェクトを右クリックしてプロパティを編集OpenCV用のライブラリを読み込む。runCapture()関数を書く。この関数の中にOpenCVのmain()を全部突っ込んでしまえばそのまま動く。今回はbgsubAvg.cppのmain()をコピペしたけど他にも赤色重心追跡や肌色検出、単純なカメラ入力など色々作ったので好きなものをコピペしてよい。OpenCV関連のヘッダを#includeで読み込むのを忘れずに。asdf()という単に数値を返すだけの関数も作っておいた。このクラスの、ユーザーのメソッドをここに追加してください。0;}};}■C#でFormアプリを作る新しいプロジェクトを作る。ソリューションエクスプローラで[参照設定]→[プロジェクト参照]でShadowCameraを参照。同一Solution内ならプロジェクト参照が便利だけど、ReleaseにShadowCamera.dllができているのでそれを他の人に配布して、[ファイルを参照]してもらってdllから呼び出してもらっても同じ機能が使えますボタンを1つ置く。e){cam.runCapture();}}}ShadowCameraSampleを(右クリックして)スタートアッププロジェクトに設定し、ビルドするとShadowCameraFormが起動する。ボタンを押すとしばらくカメラを読み込んで、数秒後にOpenCVのHighGUIのウィンドウが起動するはず。shokaiちょっとUDPを使ってアプリを作る用事があるので、まずは.NETのSystem.Net.Sockets.UdpClientクラスでシンプルなテキストチャットを作ってみた。相手のIPアドレスとポートを指定してメッセージ(文字列)を送り、受信側はポートを開けてさえいればメッセージが読める。Studioを参考にした。学部の頃にインターネット概論という授業で、コンジェスチョンコントロールがないフローコントロールがないとか習って、「ふーん」という感じだったけど。セッションを張らずに送信できて、受信するかは受信側の自由なんだな。System.Net.Sockets;UdpClientオブジェクトを作ってportを開く。true;これですでに受信できるようになっている。6000);受信バッファから読み出すと、文字列と受信元IPとportがわかる。remoteEP.Port+")");}最後にUdpClientを閉じるのを忘れないようにclient.Close();チャットアプリの実際の処理はUDPClientSampleForm.csに全部書いてある。受信を別スレッドにしてある。APIから使えるとの事だったので試した。helpを参考にした、というかほぼそのままで、UIを付けただけ。日本語OCRは商用の物しか見つからなくて、クセロReaderに入ってるとかどうやってか自分で作ってる人もいるけど、高嶺の花だった。英語はオープンソースプロジェクトがいくつかあるのになあ・・・できたもの。画像をドラッグアンドドロップするとOCR発動、文字を読み取る。この画質の写真でも相当間違える。Writerがインストールされているマシンなら動くと思う。WriterのセットアップWord2007には入っていたのでCDからインストールしなおした。普通にインストールするとチェックが外れててインストールされない。shokaiMonoでコンソールアプリケーションを作るときにargsの扱いが手間だったので作った。今のところ機能はそれだけ。dllとして書き出しているのでVB.NETやC++.NETでも使える。bitbucket.org右上からzipでダウンロードできる。./consolelibnet使用例(ConsoleLibSample.exeのコード)argsをハイフンなし、ハイフンつきなどを分けてくれる。-sこういう風に分割してくれる。world,-o,out.txt,-l,-s,使用例のコードを見ればわかるが、ParamsParserに渡せば分解してくれる。