Я работаю над проектом по созданию DLL для вывода модели из C#.
В процессе вывода мы выполняем предварительную обработку, вывод и последующую обработку для завершения работы. , Вначале я записываю все эти процессы в одну DLL, и она отлично работает. Но что касается понятия «модульность», мой начальник попросил меня разделить этот процесс на три разные библиотеки DLL.
Итак, идеальный поток данных должен быть таким:
C# || DLL (return cv::Mat*)
pre-processing || image->byte[] -----> Mat (...) -> new Mat(result)
↓
============================================================↓==============
Intptr <---------------------------
==========================↓================================================
inference || byte[] -----> Mat (...) -> new Mat(result)
↓
============================================================↓==============
Intptr <---------------------------
==========================↓===============================================
post-processing || byte[] -----> Mat (...) -> new Mat(result)
Но во время процесс передачи cv :: Mat * в C# и передачи байта [], преобразованного из Intptr, входные данные (cv :: Mat) не совпадают , как это было показано из исходного cv2.Mat (IntPtr). И вот код, который я пишу для этого (он упрощен ...):
//C++(DLL)
//pre-processing DLL ---------------------------------------------------
//dll_pre.h
extern "C" LIB_API cv::Mat* img_padding(unsigned char* img_pointer, int img_H, int img_W, int* len);
//dll_pre.cpp
LIB_API cv::Mat* img_padding(unsigned char* img_pointer, int img_H, int img_W)
{
cv::Mat input_pic = cv::Mat(img_H, img_W, CV_8UC(pic_ch), img_pointer);
//do something...
*len = input_pic.total() * input_pic.elemSize();
return new cv::Mat(input_pic);
}
// ---------------------------------------------------------------------
//inference DLL --------------------------------------------------------
//dll_inf.h
extern "C" LIB_API void dll_inference(unsigned char* img_pointer, int img_H, int img_W);
//dll_inf.cpp'
LIB_API void dll_inference(unsigned char* img_pointer, int img_H, int img_W)
{
cv::Mat input_pic = cv::Mat(img_H, img_W, CV_8UC(pic_ch), img_pointer);
cv::imwrite("dll_pic.png", input_pic)
//do something...
}
// ---------------------------------------------------------------------
//C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing; //Bitmap
using System.Drawing.Imaging;
using System.IO; //Memory Stream
using System.Runtime.InteropServices; //Marshal
using System.Diagnostics;//Timer
using OpenCvSharp;
namespace Test_DLL_Console
{
class Program
{
[DllImport(@"dll_pre.dll")]
private static extern IntPtr img_padding(byte[] img, int img_H, int img_W, out int rt_len);
[DllImport(@"dll_inf.dll")]
private static extern void dll_inference(byte[] img, int img_H, int img_W);
public static byte[] GetRGBValues(Bitmap bmp, out int bmp_w)
{
// Lock the bitmap's bits.
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
System.Drawing.Imaging.BitmapData bmpData =
bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);
// Get the address of the first line.
IntPtr ptr = bmpData.Scan0;
// Declare an array to hold the bytes of the bitmap.
int bytes = bmpData.Stride * bmp.Height;
byte[] rgbValues = new byte[bytes];
Console.WriteLine($"bytes->{bytes}");
// Copy the RGB values into the array.
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes); bmp.UnlockBits(bmpData);
bmp_w = bmpData.Stride;
return rgbValues;
}
static void Main()
{
Bitmap image = new Bitmap("test_pic.bmp");
int img_W = 0;
int rt_len = 0;
byte[] dst = GetRGBValues(image, out img_W);
IntPtr pre_res = img_padding(dst, image.Height, img_W, out rt_len);
//Mat pad_res = new Mat(pre_res); //This is the way I get return picture from DLL in C#
////pad_res is different from dll_pic.png I saved from dll_inf
byte[] btarr = new byte[rt_len];
Marshal.Copy(pre_res, btarr, 0, rt_len);
dll_inference(btarr, image.Height, img_W);
}
}
}
Подводя итог, на данный момент я успешно выполнил преобразование из IntPtr в byte []:
поток данных: IntPtr >> Mat >> Bitmap >> byte []
Но для преобразования потребуется слишком много времени (по моему мнению ...) поэтому я хочу сделать его более простым
Я также попробовал другой способ преобразования, но он все еще не удался:
поток данных: IntPtr >> Mat >> byte []
с этим кодом
//C#
byte[] btarr = new byte[rt_len];
Mat X = new Mat(pre_res);
X.GetArray(image.Height, img_W, btarr);
dll_inference(btarr, image.Height, img_W);
//(But the result is also different from the way it should be...)
Я не знаю, где я сделал не так ... Любая помощь или совет с благодарностью !!