在C ++中将它们从C#发送到OpenCV后得到扭曲的图像?

我从我的C ++类创建了一个C DLL,它使用OpenCV进行图像处理,并希望在我的C#应用​​程序中使用这个DLL。 目前,这就是我实现它的方式:

 #ifdef CDLL2_EXPORTS #define CDLL2_API __declspec(dllexport) #else #define CDLL2_API __declspec(dllimport) #endif #include "../classification.h" extern "C" { CDLL2_API void Classify_image(unsigned char* img_pointer, unsigned int height, unsigned int width, char* out_result, int* length_of_out_result, int top_n_results = 2); //... } 

C#相关代码:

DLL导入部分:

 //Dll import [DllImport(@"CDll2.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] static extern void Classify_Image(IntPtr img, uint height, uint width, byte[] out_result, out int out_result_length, int top_n_results = 2); 

将图像发送到DLL的实际function:

 //... //main code private string Classify(int top_n) { byte[] res = new byte[200]; int len; Bitmap img = new Bitmap(txtImagePath.Text); BitmapData bmpData = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); Classify_Image(bmpData.Scan0, (uint)bmpData.Height, (uint)bmpData.Width, res, out len, top_n); img.UnlockBits(bmpData); //Remember to unlock!!! //... } 

和DLL中的C ++代码:

 CDLL2_API void Classify_Image(unsigned char* img_pointer, unsigned int height, unsigned int width, char* out_result, int* length_of_out_result, int top_n_results) { auto classifier = reinterpret_cast(GetHandle()); cv::Mat img = cv::Mat(height, width, CV_8UC3, (void*)img_pointer, Mat::AUTO_STEP); std::vector result = classifier->Classify(img, top_n_results); //... *length_of_out_result = ss.str().length(); } 

这适用于某些图像,但它不能与其他图像一起使用,例如当我尝试在imshow显示图像时,在从C#应用程序发送的数据创建后,我面对的图像如下:

问题的例子:

在此处输入图像描述

很好的例子:

在此处输入图像描述

您最初的问题是所谓的步幅或图像缓冲区间距。 基本上出于性能原因,像素行值可以与内存对齐,在这里我们看到,在您的情况下,它导致像素行不对齐,因为行大小不等于像素行宽度。

一般情况是:

 resolution width * bit-depth (in bytes) * num of channels + padding 

在你的情况下, 位图类状态:

步幅是单行像素(扫描线)的宽度,四舍五入到四字节边界

因此,如果我们查看有问题的图像,它的分辨率为1414像素宽,这是一个8位RGB位图,所以如果我们做数学:

 1414 * 1 * 3 (we have RGB so 3 channels) = 4242 bytes 

所以现在除以4个字节:

 4242 / 4 = 1060.5 

所以我们留下0.5 * 4 bytes = 2 bytes padding

所以步幅实际上是4244字节。

所以这需要通过才能使步幅正确。

看看你在做什么,我将文件作为内存传递给你的openCV dll,这应该可以调用imdecode来嗅探文件类型,另外你可以传递标志cv::IMREAD_GRAYSCALE来加载图像并在运行中转换灰度。