Mixed mode interfacing

Ask questions on using Emgu CV with C++
Post Reply
mmccullo
Posts: 6
Joined: Thu Feb 02, 2012 2:58 pm

Mixed mode interfacing

Post by mmccullo » Mon Apr 16, 2012 4:20 pm

I have an application that processes video frames and therefore needs the maximum speed possible. However, for various reasons the GUI interface is managed code at present. I have written my core processing code in both managed and unmanaged code and find that the unmanaged code performs with 50% less execution time. This is a large advantage that I need to use.

Therefore, how can I easily interface between managed and unmanaged code in the following example:

Code: Select all

#pragma once

#pragma unmanaged
#include "opencv2\imgproc\imgproc.hpp"
#pragma managed


namespace WorkTest {

    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;


#pragma unmanaged
	class DoWorkAsUnmanaged
	{
	public:
		// constructor
		DoWorkAsUnmanaged()
		{
			result = new cv::Mat();
		};

		// destructor
		~DoWorkAsUnmanaged()
		{
			delete result;
		};

		cv::Mat* DoWork(cv::Mat *image0, cv::Mat *image1, cv::Mat *image2)
		{
			cv::add(*image0, *image1, *result);
			cv::add(*result, *image2, *result);

			return result;
		}

	private:
		cv::Mat *result;

	};

#pragma managed

	/// Form1
	public ref class Form1 : public System::Windows::Forms::Form
	{
	public:
		Form1(void)
		{
			InitializeComponent();
		}

	protected:
		/// Clean up any resources being used.
		~Form1()
		{
			if (components)
			{
				delete components;
			}
		}

	private:
		/// Required designer variable.
		System::ComponentModel::Container ^components;
		private: System::Windows::Forms::Button^  button1;

#pragma region Windows Form Designer generated code
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		void InitializeComponent(void)
		{
			this->button1 = (gcnew System::Windows::Forms::Button());
			this->SuspendLayout();
			//
			// button1
			//
			this->button1->Location = System::Drawing::Point(103, 33);
			this->button1->Name = L"button1";
			this->button1->Size = System::Drawing::Size(75, 23);
			this->button1->TabIndex = 0;
			this->button1->Text = L"Go!";
			this->button1->UseVisualStyleBackColor = true;
			this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
			//
			// Form1
			//
			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->ClientSize = System::Drawing::Size(284, 88);
			this->Controls->Add(this->button1);
			this->Name = L"Form1";
			this->Text = L"C++ Test";
			this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
			this->ResumeLayout(false);
		}
#pragma endregion

	private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e)
		{
			array<Emgu::CV::Image<Bgr, Byte>^>^ image = gcnew array<Emgu::CV::Image<Bgr, Byte>^>(3);

			try{
				image[0] = gcnew Emgu::CV::Image<Bgr, Byte>("C:\\Temp\\image0.png");
				image[1] = gcnew Emgu::CV::Image<Bgr, Byte>("C:\\Temp\\image1.png");
				image[2] = gcnew Emgu::CV::Image<Bgr, Byte>("C:\\Temp\\image2.png");
			}
			catch (CvException ^ex) {
				Debug::WriteLine(ex->Message);
			}

			DoWorkAsUnmanaged *workObject = new DoWorkAsUnmanaged();

			// need help HERE!!
			? = workObject->DoWork(?, ?, ?);
		}
};
}
I believe this sort of mixed mode code works in VS2010. The problem is getting the images (cv::Mat's in this case) across the managed/unmanaged interface. I've looked at pinning pointers and marshaling, but frankly do not know which approach to take. I imagine that the necessary marshaling interface(?) is already done in Emgu if I knew the necessary syntax. I want to have the most efficient pass possible for the images.

I realize the DoWork() example is trivial, but the real DoWork() functions are much more involved as far as how they operate on the images. The native code speed advantage is too large to ignore in my case.

Thanks in advance for any help!

mmccullo
Posts: 6
Joined: Thu Feb 02, 2012 2:58 pm

Re: Mixed mode interfacing

Post by mmccullo » Tue Apr 17, 2012 12:54 pm

Looking through the Emgu code it appears that it has no knowledge of cv::Mat. All the interfacing seems to be to the plain C calls into OpenCV. Therefore, my guess is that I have to work the unmanaged/managed interface using the plain C types instead of any C++ classes in OpenCV.

If anyone can provide further hints on the syntax of the interfacing code, please do!

mmccullo
Posts: 6
Joined: Thu Feb 02, 2012 2:58 pm

Re: Mixed mode interfacing

Post by mmccullo » Thu May 03, 2012 11:16 am

FYI: I couldn't find any detailed help about how to marshal the image data across the managed/unmanaged boundary in several forums. I understand the concept, but I just don't know the syntax to do what I need. The subject of marshaling in general seems to be tersely documented with very few complex examples.

I decided to rewrite the GUI in Qt and use OpenCV via completely unmanaged C++. My previous core functionality benchmarks hinted at a 1.8x speedup of my output. The GUI rewrite in Qt was far easier than I expected -- only taking about a man week since I already had my core processing code converted for benchmarking purposes -- and the end result to date is a 1.6x increase in overall throughput for my application.

Emgu proved very handy in developing a prototype and testing, but ultimately our project needed the speed of unmanaged code.

lisaa
Posts: 1
Joined: Mon Nov 17, 2014 3:36 am

Re: Mixed mode interfacing

Post by lisaa » Mon Nov 17, 2014 3:44 am

Impressive..... Great... :D :D :) :) ;)

Post Reply