Passing bitmap from c# to c++

后端 未结 4 999
后悔当初
后悔当初 2020-12-15 00:59

I have an image processing function written in C++ based on opencv. In my wpf application I have used AForge library to access a webcam and update it on UI. This the functio

相关标签:
4条回答
  • 2020-12-15 01:37

    I can suggest you to use EmguCV. It is wrapper for openCV in C#. You dont have to worry about dll, lib etc. I can see that you want to track a face from webcamera. EmguCV gives you possibilty to capture webcamera image and later track face in very easy way: http://www.emgu.com/wiki/index.php/Face_detection This link should help you also. Enjoy.

    0 讨论(0)
  • 2020-12-15 01:49

    An HBITMAP is an opaque handle to a bitmap. It is not a pixel buffer. So your two pieces of code do not match.

    If you pass an HBITMAP to the native code then you need the native code to use GDI functions to obtain the pixel buffer and operate on it. Alternatively you could obtain a pixel buffer in your managed code and pass that to the native code. Whichever way you go you do need to match the two sides of the interop.

    0 讨论(0)
  • 2020-12-15 01:54

    Depends on the scope. If you can guarantee the bitmap isn't used elsewhere, you can lock the image buffer, and then pass the pointer down to the C++ code, and unlock it afterwards.

    The LockBits command returns a BitmapData class that has a pointer to the image buffer in its Scan0 property:

    BitmapData bmpData = bitmapFrame.LockBits(new Rectangle(0, 0, bitmapFrame.Width, bitmapFrame.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, 
                System.Drawing.Imaging.PixelFormat.Format24bppRgb);
    
    NativeFunctions.FaceTracker(bmpData.Scan0 , bitmapFrame.Width, bitmapFrame.Height);
    
    bitmapFrame.UnlockBits(bmpData); //Remember to unlock!!!
    
    0 讨论(0)
  • 2020-12-15 01:56

    You can use Bitmap.Save() method to convert it to a memory stream and then send it to C++ dll.

    public Image ConvertImage(Image image)
    {
       MemoryStream convertedImageMemoryStream;
       using (MemoryStream sourceImageStream = new MemoryStream())
       {
           image.Save(sourceImageStream, System.Drawing.Imaging.ImageFormat.Png);
           byte[] sourceImageData = sourceImageStream.ToArray();
    
           // Send it to dll and get the IntPtr byte array from dll
    
           byte[] imageData = new byte[imInfo.size];
           Marshal.Copy(imInfo.data, imageData, 0, imInfo.size);
           if (imInfo.data != IntPtr.Zero)
               AlgorithmCpp.ReleaseMemoryFromC(imInfo.data);
           convertedImageMemoryStream = new MemoryStream(imageData);
        }
        Image processed = new Bitmap(convertedImageMemoryStream);
        return processed;
    }
    

    Then, in C++ dll use decoding such as cv::imdecode() method to get the image.

    DllExport void convertToGray(unsigned char* data, int dataLen)
    {
        vector<unsigned char> inputImageBytes(data, data + dataLen);
        Mat image = imdecode(inputImageBytes, CV_LOAD_IMAGE_COLOR);
        Mat processed;
        cvtColor(image, processed, CV_BGR2GRAY);
        vector<unsigned char> bytes;
        imencode(".png", processed, bytes);
        // ....
    

    There are some pros in this way such as, 1. fewer data to transfer 2. minimum implementation effort from both C# and C++ end. 3. Does not depend on the source image type eg. color or grayscale or any other color palate type. So it's very safe to use.

    The only problem is that it is CPU intensive as there are an encoding and a decoding.

    Details are here.

    0 讨论(0)
提交回复
热议问题