|
|
●概要 確認のため、空間フィルタを実行するDLLを開発し、その機能と実行速度を確認した。 ●仕様 ○名称 ImageProcessing.dll ○機能 画像の一次変換(Convert)と空間フィルタ(SpatialFilter)を行う。 ○入出力 ・Convert 原画を一次元バイト配列の参照で与え、変換係数(a, b) をDoubleで与える。結果は、原画配列に返す。 ・SpatialFilter 周辺を拡張された原画を一次元バイト配列の参照、結果を収める領域も、一次元バイト配列の参照で与える。フィルタ関数は、一次元Double配列で与える。フィルタ係数もDoubleで与える。その他、原画サイズ、フィルタサイズをIntegerで与える。 ○ラッパ エンドプログラマには、C++を見せなく、VB.NETでラップし、マネージコードのクラスとして見せる。 ●実例 ・2007/3/24 バグ発見 フィルタの試験をしていると不可解な現象が出た。メモリ領域外アクセスと言うもの。配列のサイズやインデックスをチェックしたが問題なし。現象が不安定であるが、どうもフィルタサイズに関係している。暫く悩んでしまった。調べているうちに、C++で、メモリ要求をしているが、この要求サイズはバイト単位であることに気づいた。要求はint配列なので、要求数を4倍して解決。おはずかしい。 その後、C++では、メモリ要求は、malloc ではなく、new 演算子を使った方が良いと判明。new に変更。 ・C++側関数定義 void ImageProcess::SpatialFilter(unsigned char a[], unsigned char b[], double Filter[], double cf, double bs, int w, int h, int x, int y) 注意:特に断らない限り、char型は、符号付バイトとなる。画像の画素を扱う場合、符号付では正しく処理できないので、unsigned char とする必要がある。 ○VB側 ・DLL宣言 <C++Exportの場合>筆者の従来の方法 Friend Declare Sub cppSpatialFilter Lib
"P:\VC.NET2005\DllSrc\ImageProcessing\Release\ImageProcessing.dll"
_ VBでは、DLL宣言で、DLLの場所を絶対パスにしている。これにより、開発中は、C++側の最新オブジェクトを常に参照できる。完成すれば、相対パスにすれば良い。 予測不可能な内部関数名は、関数のシグネチャが変更されない限り、同じ文字列が維持されるようであるので、関数名、引数などを最初に注意深く決めておけば、Alias のメンテは楽になる。 <DEFファイルの場合>筆者の現在の方法 Friend Declare Sub cppSpatialFilter Lib
"・・・・・・\ImageProcessing\Release\ImageProcessing.dll"
_ DEFファイルは、C++コンパイラで外部名と内部名の整合性が検査されている。また、dllファイルにDEFファイルの定義が埋め込まれているので、VB側での開発時や実行にはDEFファイルは不要である。やはりこちらの方がはるかに楽となる。 ・関数呼び出し cppSpatialFilter(BBEx(0), Dst(0), Filter, Coef, Base, W, H, N, M) 配列の参照渡しであるが、実際には、その配列の先頭要素を記述する。 ●結果 ○機能確認 VBによる空間フィルタと同じ結果を得られた。 ○処理時間実測 試作したDLLを使って、空間フィルタの処理時間を計測した。下図のようになった。 VB
:純粋のVB(Get/SetPixelメソッド)のみで処理した場合 VBの処理時間の1/3程度に改善された。ここでのVB処理時間は、元々、かなり頑張った値(巷で紹介されている、VBのGet/SetPixelメソッドによる画像処理・・・などの約十倍以上の速度)であるが、更にその3倍の速度となった訳である。 この試験では、VBによる処理部分は、通り一遍の処理のみであり、C++の恩恵はあまり無い部分であると考えられるので、VBとC++ネイティブのコラボとしての最善値と思われる。C++ネイティブの支援は有効と思う。
|