Using .Net Libraries in MATLAB

Hi to Khabrovchanam! The issue of .Net integration with Matlab was already discussed on Habré . The purpose of this article is to show how you can quickly and conveniently solve the inverse problem: call managed code from arbitrary .Net libraries in Matlab.

Why is this needed?



Despite the rich set of algorithms in Matlab’s functionality, the main scenario in which this may be needed is the need to use libraries that have mathematical algorithms implemented in existing and possessing well-known .Net quality indicators.


Disclaimer



The example that is discussed in the article describes a typical set of cases arising during integration, sufficient for a wide class of calculations, however, it does not cover all the possibilities of integration with .Net that are present in Matlab.
The code from this article was made and tested on a Windows platform and in a specific version of Matlab 2013a. As the version of .Net Framework was used 4.5, IDE - VS 2012.

Creating .Net objects in Matlab



As a simple example, consider creating a standard class object DateTimefrom .Net.
Getting the current date-time from .Net can be written with the following Matlab code

dateTimeNow = System.DateTime.Now


Immediately note that this is the complete code. We are not required to explicitly connect any .Net system libraries, and the CLR variable dateTimeNow automatically becomes a Matlab variable. If this call fails, you can check the Boolean result of the command that checks for .Net support in the environment.

isnetsupported = NET.isNETSupported


As an example of calling the CLR method of an object, we add 10 minutes to the current date using the method familiar to donors AddMinutes

dateTimeNow = dateTimeNow.AddMinutes(10)


As a result of launching these commands, the output displays the contents of the received objects


           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]


Cooking DLL



Before we learn how to load an arbitrary assembly into Matlab, we will prepare it.
As a simple example, we implement in the target .Net library with the name Algorithms.dllthe search algorithm for the upper left corner of the bounding box of the binary image.

This can be done with the following C # code:

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() {}
        /// 
        /// Возвращает в массиве coordinates координаты левого верхнего угла бинарной картинки
        /// на изображении. Если их нет - {-1,-1}
        /// 
        /// Входное бинарное изображение
        /// Координаты левого верхнего угла
        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);
        }
    }
}


This code is specific: we will consider calling non-static public methods from Matlab that return values ​​using a keyword out. The method GetLeftUpperCornerBBaccepts an object of the class Bitmapthat contains the binary image as an input and returns the coordinatescoordinates of the first left upper black pixel in the array (and if there isn’t such an image, for example, in the case of an empty image, it returns null).

Loading custom .Net libraries in Matlab



In the Matlab directory of the project, create a new Matlab file Example.m, next to which we will place the library obtained in the previous step Algorithms.dll(see the screenshot below)


Using the function call, addAssemblyload the assembly into Matlab.

 netAssembly = NET.addAssembly('D:\Work\MatlabNetIntegrationExample\Algorithms.dll')


look at the list of classes of the loaded assembly


netAssembly.Classes


the result will be

ans = 
    'Algorithms.ImageProcessor'


using the command
import Algorithms.*

enable namespace Algorithms.

Create a class object ImageProcessor and load the input image into a variablebitmap
imageProcessor = ImageProcessor();
bitmap = System.Drawing.Bitmap('picture.bmp')


the file picture.bmpis located in the current working directory.
Command

 methods (imageProcessor)

will show us a list of available methods of this object
Methods for class Algorithms.ImageProcessor:
Equals                delete                le                    
GetHashCode           eq                    lt                    
GetLeftUpperCornerBB  findobj               ne                    
GetType               findprop              notify                
ImageProcessor        ge                    
ToString              gt                    
addlistener           isvalid               


Now, run the target method GetLeftUpperCornerBB and get the result

 coords = imageProcessor.GetLeftUpperCornerBB(bitmap);

If we had several out parameters (suppose, as many as three arrays with coordinates), then we would write such code to get them

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


Note that the result is a CLR object of type System.Int32[], therefore, for the possible convenience of working with it, it is possible to convert this array to Matlab's native array. For instance:

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


Reverse conversion is possible using the function NET.convertArray.

Total, we get the following listing:


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;


Conclusion



We solved the problem of creating a .Net object in Matlab, running methods of .Net classes and getting results.
Separately, it is worth noting that, according to the Matlab documentation, unloading loaded .Net modules is not explicitly provided. Therefore, to replace the DLL file, you will need at least a reboot of the Matlab IDE. Otherwise, in version 2013a, there is quite complete support for .Net integration in the sense of the ability to work with various CLR elements and their attributes.

Materials used



Also popular now: