[MFC]MFCでOpenCVを描画する(CvvImage)

OpenCV1.0でのお話.

MFC上でOpenCVを描画する方法は,あまり紹介されていない気がする.
カットシステムから出版されている「実践OpenCV」では
IplImageの画像データ領域に,BITMAPINFO等を付けて
DIB形式とし,StretchDIBitsメソッドでDCに対して描画を行う方法を紹介している.
手法としては間違ってはいないが,正直面倒である(笑)

※ DIB(デバイス独立ビットマップ)
メモリ上の任意の領域をRGB形式(またはカラーテーブルで指定される色の配列)の画像データを格納した
ビットマップ(フレームバッファ)として扱い、画面などに描画する機能

あまり知られていないが,OpenCVには
C++用にIplImage構造体をラッピングしたCvImageクラスが存在する.
その中でも,CvvImageクラスはWindowsのGDIをサポートしており,
DCに対して描画を行う事が出来るという素晴らしさ!!
画像のリサイズも自動で行ってくれるため,コードの無駄をかなり減らす事が出来,
ダブルバッファリングを組み合わせればほぼ完璧!?

実際の使い方としては,以下の通り.
  1. // 画像データを既に保持している IplImage* m_img がDocumentクラスに定義済みと仮定
  2. void C**View::OnDraw(CDC* pDC)
  3. {
  4. // TODO: ここに特定なコードを追加するか、もしくは基本クラスを呼び出してください。
  5. CAttitudeEstimationDoc* pDoc = this->GetDocument();
  6.  
  7. // 描画対象の領域サイズを取得
  8. CRect rect;
  9. GetDlgItem(ID)->GetClientRect(&rect);
  10.  
  11. CvvImage cvvImage;
  12. cvvImage.copyOf(pDoc->m_img);
  13. cvvImage.DrawToHDC(pDC->GetSafeHdc(), &rect);
  14. }

このCvvImageクラスには,DrawToHDC()メソッドの他にShow()メソッドもある.
正直,GDIを扱う人であればhighgui.hにあるCvvImageクラスの定義を読めば理解出来るハズ.

注意すべき点としては,cvvImageクラスをCImageクラスとして定義しているため,
ATLのCImageクラスと名前が被ってしまう点であろう.
同時にATLのCImageクラスを扱う場合は,ATLのCImageクラスの名前を別の名前に定義し直す方が良いと思われる.

記事の続きにhighgui.hのCvvImageクラスが定義されている箇所を提示しておく.
続き▽
| Programming::C++ (MFC) | comments (0) |
[MFC] ツールバーのグリップ部分(覚え書き)

正直,研究でのプログラムはMFCで開発することはあまり無い.
ただ,計算値の監視とかするのにコンソール出力では
流れてしまってあまりにも現実的では無い時や
形として残しておきたい時はMFCを使う.

で,久しぶりにMFCのDocument-Viewerアーキテクチャーを使って開発してみたところ
ツールバーのグリップ部分がちゃんと描画されないバグに出会った.
過去に修正した事はあるが,覚え書きとして以下に記載しておく.

CMainFrame::OnCreate()のツールバーを作成している部分を修正

以下の部分を
  1. if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE
  2. | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS
  3. | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
  4. !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
  5. {
  6. TRACE0("Failed to create toolbar\n");
  7. return -1; // 作成に失敗
  8. }


以下の通りに修正
  1. if (!m_wndToolBar.CreateEx(this, 0, WS_CHILD | WS_VISIBLE
  2. | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS
  3. | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
  4. !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
  5. {
  6. TRACE0("Failed to create toolbar\n");
  7. return -1; // 作成に失敗
  8. }
  9. // TBSTYLE_FLATを改めてセット
  10. m_wndToolBar.ModifyStyle( 0, TBSTYLE_FLAT );


ソース
気まぐれソフトハウス >> VC++6.0でXPビジュアルスタイルを使うには
| Programming::C++ (MFC) | comments (0) |
[WDK] WinDbgのお相手は仮想マシンに 2

仮想マシンの名前付きパイプ接続を使ってWinDbgとの接続実験をしてみました。
とりあえず、Windows XP SP3 (x86)の環境下で
Sun VirtualBox、VMware Player、VMware Workstation(v6.5)の3つで試した結果。
VMware Workstationのみ接続を確認出来ました。
VMware系での接続を確認しました。

VirtualBoxはWindowsでの名前付きパイプでの接続方法の資料が見つからず、接続出来ているか怪しい。
VMware Playerは名前付きパイプでの設定は出来るが
GesutOS起動時に何故か怒られて接続出来ない。これは設定が怪しい・・・。

VMware Playerでの名前付きパイプでの接続を確認。やはり設定に問題がありました。
Web上でのWinDbg動作確認報告が多いVMware Workstationだと問題なく動作確認出来ました。

その時の設定は以下のとおり。
[X] 起動時に接続
名前付きパイプを使用
・ \\.\pipe\com_1
・ この端末はサーバです。
・ 接続先はアプリケーションです。
[X] ポーリングでCPUを放棄する

ちなみに、VMwareの構成ファイルであるvmxファイルの中は以下のとおり。
serial0.present = "TRUE"
serial0.yieldOnMsrRead = "TRUE"
serial0.fileType = "pipe"
serial0.fileName = "\\.\pipe\com_1"
serial0.tryNoRxLoss = "TRUE"

WinDbg側の設定は以下のとおり。
port : \\.\pipe\com_1
baudrate : 115200
pipe : true
reconnect : true

仮想マシン上でOSをデバッグモードで起動し
WinDbgからPIPE接続でKernelDebugを開始すると1台の端末でデバイスドライバの
開発からデバッグおよび動作確認を楽々行う事が出来ます。

但し、WinDbgでソース上にDbgBreakPoint()を記載してソースデバッグ等を行った場合は
デバイスドライバをコンパイルした際に出力される.pdb(Program Debug Database)ファイルが
WinDbgに使用されているため、そのままドライバの再コンパイルを行った際にリンケージで失敗します。
その場合は、一度WinDbg側でBreakをして停止して、WinDbgを終了させた上で終了し再コンパイルを行う。
再びWinDbgを開始するとBreakした状態からデバッグを再スタートする事が出来る。
(WinDbgを終了する際にSessionを保持しないといけないかも・・・[未確認]

とりあえず、仮想マシンを使ったデバイスドライバの開発が一番スマートかつ安全な環境だと思う。
特に、VMware WorkstationのようにSnapshot機能で元の状態に戻せるのは
ブルースクリーンから逃れられなくなるといった精神的な負担も減らしてくれる(笑

欲を言えば、VirtualBox上でWindowsの名前付きパイプ接続が出来れば
お金が掛からなくて良いんだけど・・・誰か情報ありません?
| Programming::WDK | comments (0) |
[WDK] WinDbgのお相手は仮想マシンに 1

仕事(バイト)でDeviceDriverの開発はじめました(笑
本来ならうちでやる仕事じゃないんですが・・・
まぁ、今まで触れたことの無い領域のため、ワクワクしながら作業してます・・・面倒だけど。

Driverの開発は楽しいです。特にWindowsのKernelDebug。
まず2台の端末を用意し、お互いをRS-232Cのクロスケーブルで物理的に接続。
ターゲットとなるPC(Debug対象)のBoot.iniを編集しoperation systemのセクションの値の後ろに以下を追加
(OS:WindowsXP COM1にて115200bpsの環境の場合)
/debugport=com1 /baudrate=115200
もう一台のPC(デバッガ側)ではWinDbgを起動して、KernelDebugの設定を行う。
KernelDebug時の接続(及び設定)
あとは、WinDbgが接続待ちになったのを確認して
ターゲットPCをデバッグモードで起動すると、KernelDebugが始まる。

さてさて、このWinDbgというデバッガ
brakeやらWatchやらStepOverやら、よく見るデバッグツールと同じ機能が付いてます(笑
もちろん、breakを行うとターゲットPCは止まります(笑
ダンプも出来て、メモリの手動書き換え等も出来る。再起動までも・・・

で、実際にDeviceDriverのデバッグをする際には
Driverのソース類をWinDbgに設定しておくと、ソースレベルでデバッグが出来ちゃいます。
もちろん、ソースの中でブレークポイントを呼び出すコードを記述しておけば
ソース側(実際はドライバ)からbreakしてくれます。
まぁ、こういう機能が無いと根性デバッグになってしまうので困りますが・・・

問題は、OS内部(Kernelモード)での動作になるので
ドライバにバグが含まれているとOSごとクラッシュします(汗
下手するとPCがそのままお亡くなりになる可能性大・・・。

そこで考えたのが最近流行の仮想マシン
仮想シリアルポートを用意して、GesutOSをデバッグモードで作業すればクラッシュしても問題無い。
今日はVirtualBoxを使って試していたのですが・・・上手くいかず(?)
とりあえずWeb上で先人が見つかったため、またリベンジをしてみる予定。

blog : WinDbgでGesutOSに接続
| Programming::WDK | comments (0) |
[C++] DLLリンクの使い分け

今の仕事で自分で作ったDLLをC#で使っているのもあって
色々調べてたところ、MSDNに良い記事を見つけためURLをメモしておく。

参照URL : リンク方式の使い分け

DLLを使ったことがある人なら知っているとは思うが
暗黙的なリンクと明示的なリンクの 2 種類のリンク方法がある。
個人的には暗黙的なリンクの方をよく使うが
明示的リンクは扱いが面倒なためあまり使うことがない。

ただ、趣味として使うのであれば理解していなくても構わないかもしれないが
仕事として使っているので理解する必要があるだろう。

ついでに、DLLを作る際の注意を以下にメモしておく。
・ 関数名を明示的にするにはDLL側の関数で __declspec(dllexport) を戻り値の型の前につける。(#defineしておくとラク)
 => DEFファイルが必要なくなる
・ Export部分にC++(ClassやOverload)の機能を用いて作成されたDLLは、呼び出す側はC++でしか扱えない。
extern "C"構文を利用して、C++の名前装飾をやめれば、他の環境(他言語等)にも対応できる。
・ 作成後はVisualStudio付属の dumpbin.exe を使ってExportの確認。(/EXPORTS)
| Programming::C++ (MFC) | comments (0) |
1 2 >> 

  

  
PROFILE
GSX-R1000
  • Author : Gaku
  • Age : 22 [1987.03.10]
  • Bike : SUZUKI GSX-R1000 K1 [E-28:Canada]
  • Web!ke : MyGarage
COMMENTS
TRACBACK
SEARCH
CALENDAR
S M T W T F S
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30      
<<   11 - 2009   >>
LINKS
OTHERS
POWERED BY
POWERED BY
ぶろぐん

SKIN BY
ゲットネット...¥

SERVER BY
wish-star.sytes.net