MATLABでの.Netライブラリの使用

ハブロフチャナムにこんにちは! Matlabとの.Net統合の問題は、 すでに Habréで議論されています。 この記事の目的は、Matlabの任意の.Netライブラリからマネージコードを呼び出す逆問題を迅速かつ便利に解決する方法を示すことです。

なぜこれが必要ですか?



Matlabの機能には豊富なアルゴリズムがありますが、これが必要となる主なシナリオは、既存の.Net品質インジケータを備えた既存の数学アルゴリズムを実装したライブラリを使用する必要があることです。


免責事項



この記事で検討する例では、幅広いクラスの計算に十分な、統合中に発生する典型的なケースのセットについて説明していますが、Matlabに存在する.Netとの統合の可能性をすべて網羅しているわけではありません。
この記事のコードは、WindowsプラットフォームおよびMatlab 2013aの特定のバージョンで作成およびテストされました。 .Net Frameworkのバージョンが4.5で使用されたため、IDE-VS 2012。

Matlabでの.Netオブジェクトの作成



簡単な例として、標準のDateTimeクラスのオブジェクトを.Netから作成することを検討してください。
.Netから現在の日時を取得するには、次のMatlabコードを使用します。

 dateTimeNow = System.DateTime.Now 


これが完全なコードであることにすぐに注意してください。 .Netシステムライブラリを明示的に接続する必要はなく、CLR変数dateTimeNowは自動的にMatlab変数になります。 この呼び出しが失敗した場合、環境での.Netサポートを確認するコマンドのブール結果を確認できます。

 isnetsupported = NET.isNETSupported 


オブジェクトのCLRメソッドを呼び出す例として、 AddMinutesあるAddMinutesメソッドを使用して、現在の日付に10分を追加します

 dateTimeNow = dateTimeNow.AddMinutes(10) 


これらのコマンドを開始した結果、出力には受信したオブジェクトの内容が表示されます

 Date: [1x1 System.DateTime] Day: 21 DayOfWeek: [1x1 System.DayOfWeek] DayOfYear: 111 Hour: 13 Kind: [1x1 System.DateTimeKind] Millisecond: 160 Minute: 49 Month: 4 Now: [1x1 System.DateTime] UtcNow: [1x1 System.DateTime] Second: 56 Ticks: 635021489961600559 TimeOfDay: [1x1 System.TimeSpan] Today: [1x1 System.DateTime] Year: 2013 MinValue: [1x1 System.DateTime] MaxValue: [1x1 System.DateTime] 


クッキングDLL



Matlabに任意のアセンブリをロードする方法を学ぶ前に、それを準備します。
簡単な例として、 Algorithms.dllという名前のターゲット.Netライブラリに、バイナリイメージの境界ボックスの左上隅の検索アルゴリズムを実装します。

これは、C#で次のようなコードを使用して実行できます。

 using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Algorithms { public class ImageProcessor { public ImageProcessor() {} /// <summary> ///    coordinates       ///  .    - {-1,-1} /// </summary> /// <param name="bitmap">  </param> /// <param name="coordinates">   </param> public void GetLeftUpperCornerBB(Bitmap bitmap, out int[] coordinates) { coordinates = null; var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb); unsafe { //     uint* p = (uint*) bitmapData.Scan0.ToPointer(); coordinates = new int[2]{-1,-1}; //    for (int i = 0; i < bitmap.Height*bitmap.Width; i++) { if( (*p & 0xFFFFFF) == 0) //    { coordinates[0] = i / bitmap.Width; break; } p++; } p = (uint*) bitmapData.Scan0.ToPointer(); for (int i = 0; i < bitmap.Height*bitmap.Width; i++) { if( (p[( i % bitmap.Height) * bitmap.Width + ( i / bitmap.Height) ] & 0xFFFFFF) == 0) //    { coordinates[1] = i / bitmap.Height; break; } } } bitmap.UnlockBits(bitmapData); } } } 


このコードは具体的です。outキーワードを使用して値を返す非静的パブリックメソッドをMatlabから呼び出すことを検討します。 GetLeftUpperCornerBBメソッドは、バイナリ画像を含むBitmapクラスのオブジェクトの入力をGetLeftUpperCornerBBし、 coordinates配列の最初の左上の黒ピクセルのcoordinates返しnull空の画像の場合など、そのような画像がない場合はnull返しnull )。

Matlabでのカスタム.Netライブラリの読み込み



プロジェクトのMatlabディレクトリで、新しいMatlabファイルExample.m作成し、その隣に前の手順で取得したAlgorithms.dllライブラリを配置します(下のスクリーンショットを参照)


addAssembly関数を呼び出すことにより、アセンブリをMatlabにロードします。
 netAssembly = NET.addAssembly('D:\Work\MatlabNetIntegrationExample\Algorithms.dll') 


ロードされたアセンブリのクラスのリストを見てください

 netAssembly.Classes 


結果は

 ans = 'Algorithms.ImageProcessor' 


コマンドを使用して
 import Algorithms.* 

名前空間アルゴリズムを有効にします。

ImageProcessorクラスのオブジェクトを作成し、入力画像をbitmap変数にロードします
 imageProcessor = ImageProcessor(); bitmap = System.Drawing.Bitmap('picture.bmp') 


picture.bmpファイルは現在の作業ディレクトリにあります。
チーム

  methods (imageProcessor) 

このオブジェクトの利用可能なメソッドのリストを表示します
 Methods for class Algorithms.ImageProcessor: Equals delete le GetHashCode eq lt GetLeftUpperCornerBB findobj ne GetType findprop notify ImageProcessor ge ToString gt addlistener isvalid 


次に、ターゲットメソッドGetLeftUpperCornerBBを実行して結果を取得します

  coords = imageProcessor.GetLeftUpperCornerBB(bitmap); 

複数のoutパラメータがある場合(座標を持つ3つの配列と仮定)、それらを取得するためにこのようなコードを記述します

  [coords, cords2, cords3] = imageProcessor.GetLeftUpperCornerBB(bitmap); 


結果はSystem.Int32[] CLRオブジェクトであることに注意してください。したがって、操作の利便性のために、この配列をMatlabのネイティブ配列に変換することができます。 例:

 arrayOfDoubles = coords.double; arrayOfIntegers = coords.int32; 


NET.convertArray関数を使用すると、逆変換が可能です。

合計で、次のリストが取得されます。

 netAssembly = NET.addAssembly('D:\Work\MatlabNetIntegrationExample\Algorithms.dll'); netAssembly.Classes; import Algorithms.*; imageProcessor = ImageProcessor(); bitmap = System.Drawing.Bitmap('picture.bmp'); methods (imageProcessor); coords = imageProcessor.GetLeftUpperCornerBB(bitmap); arrayOfIntegers = coords.int32; 


おわりに



Matlabで.Netオブジェクトを作成し、.Netクラスのメソッドを実行して結果を取得する問題を解決しました。
それとは別に、Matlabのドキュメントによると、ロードされた.Netモジュールのアンロードは明示的に提供されていないことに注意する価値があります。 したがって、DLLファイルを置き換えるには、少なくともMatlab IDEの再起動が必要です。 それ以外の場合、バージョン2013aでは、さまざまなCLR要素とその属性を操作できるという意味で、.Net統合が完全にサポートされています。

使用材料


Source: https://habr.com/ru/post/J177449/


All Articles