将图像从C#发送到C ++中的OpenCV之后,图像失真了吗? [英] Getting distorted images after sending them from C# to OpenCV in C++?

查看:94
本文介绍了将图像从C#发送到C ++中的OpenCV之后,图像失真了吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I created a C DLL out of my C++ class which uses OpenCV for image manipulations and want to use this DLL in my C# application. Currently, this is how I have implemented it:

#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的实际功能:

The actual function sending the image to the DLL:

//...
//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 ++代码:

and the C++ code in the DLL :

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<Classifier*>(GetHandle());

        cv::Mat img = cv::Mat(height, width, CV_8UC3, (void*)img_pointer, Mat::AUTO_STEP);

        std::vector<Prediction> result = classifier->Classify(img, top_n_results);

        //...
        *length_of_out_result = ss.str().length();
    }

这对于某些图像来说是完美的,但对其他图像却不起作用,例如,当我尝试从C#应用程序发送的数据创建后,立即在Classify_Image中的图像中imshow时,我面临着带有这样的图像:

This works perfectly with some images but it doesn't work with others, for example when I try to imshow the image in the Classify_Image, right after being created from the data sent by C# application, I am faced with images like this :

有问题的示例:

很好的例子:

推荐答案

最初的问题与图像缓冲区的步幅或间距有关. 基本上出于性能方面的原因,像素行值可以进行内存对齐,在这里,我们发现由于行大小不等于像素行宽度,导致像素行不对齐.

Your initial issue is to do with what is called stride or pitch of image buffers. Basically for performance reasons pixel row values can be memory aligned, here we see that in your case it's causing the pixel rows to not align because the row size is not equal to the pixel row width.

一般情况是:

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

在您的情况下

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

The stride is the width of a single row of pixels (a scan line), rounded up to a four-byte boundary

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

So if we look at the problematic image, it has a resolution of 1414 pixel width, this is a 8-bit RGB bitmap so if we do the maths:

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

所以现在除以4个字节:

So now divide by 4-bytes:

4242 / 4 = 1060.5

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

所以跨度实际上是4244字节.

So the stride is in fact 4244 bytes.

因此需要通过此操作,以便跨步正确.

So this needs to be passed through so that the stride is correct.

看看您在做什么,我会将文件作为内存传递给您的openCV dll,这应该能够调用imdecode,它将监听文件类型,此外,您还可以传递标志 cv::IMREAD_GRAYSCALE 可以加载图像并即时转换灰度.

Looking at what you're doing, I'd pass the file as memory to your openCV dll, this should be able to call imdecode which will sniff the file type, additionally you can pass the flag cv::IMREAD_GRAYSCALE which will load the image and convert the grayscale on the fly.

这篇关于将图像从C#发送到C ++中的OpenCV之后,图像失真了吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆