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# related code:
DLL Import section:
//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);
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!!!
//...
}
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();
}
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 :
Problematic example:
Fine example:
image width * num bytes per channel * num of channels + padding
. The doc states the number will be 4-byte aligned – Berylberyle1414 * 3 = 4242 bytes
if we then divide by 44242/4=1060.5
you can see that we are left with0.5
which means that the stride will be set to4244
because0.5 * 4 bytes = 2 bytes
, please check if this is the case – BerylberyleCV_8UC3
, how can I get the equivalent type here and send it as well? wouldnt this create an issue when I feed grayscale image or png images with 4 channels? by the way please post that as the answer. – Rostandimdecode
, this should work: #14727767 and docs.opencv.org/3.0-beta/modules/imgcodecs/doc/… also this has the advantage that you can can pass the flag for grayscale and it will just load and convert on the fly, I think this should work without faffing about with bitmap loading – BerylberyleGetResizeHeight
? also the docs for setResolution msdn.microsoft.com/en-us/library/… state you're supposed to pass the resolution in dots per inch, rather than pixel values, this could be your confusion. Additionally you should just use openCV to resize and just pass some scaled resolution size like half height/width – Berylberyle