簡體   English   中英

將位圖從c#傳遞到c ++

[英]Passing bitmap from c# to c++

我有一個基於opencv用C ++編寫的圖像處理功能。 在我的wpf應用程序中,我使用AForge庫來訪問網絡攝像頭並在UI上更新它。 這是處理新幀的功能。

void UI_NewFrame(object sender, NewFrameEventArgs eventArgs)
    {
        try
        {
            System.Drawing.Bitmap bitmapFrame = (Bitmap)eventArgs.Frame.Clone();

            MemoryStream ms = new MemoryStream();
            bitmapFrame.Save(ms, ImageFormat.Bmp);
            ms.Seek(0, SeekOrigin.Begin);

            BitmapImage bitmapImageFrame = new BitmapImage();
            bitmapImageFrame.BeginInit();
            bitmapImageFrame.StreamSource = ms;
            bitmapImageFrame.EndInit();
            bitmapImageFrame.Freeze();
            CurrentFrame = bitmapImageFrame;
        }
        catch (Exception ex)
        {
            Debug.WriteLine("fatal::" + ex.Message);
        }
    }

這是我的c ++代碼:

void FaceTracker(unsigned char* imageBuffer, int width, int height){    
   Mat frame(Size(width, height), CV_8UC4, imageBuffer, Mat::AUTO_STEP);
   Mat gray;
   cvtColor(frame, gray, COLOR_BGR2GRAY);
   //do more operations
}

我有兩個選擇。 我已經找到了一個代碼,用於使用CopyPixels將數據從BitmapImage復制到IntPtr緩沖區。 我測試了它,它工作正常。 但我也讀過我可以使用GetHBitmap將句柄傳遞給Bitmap。 但這不適合我。 我讀了這個如何將.NET位圖傳遞給本機DLL? 但是我不了解GetDIBits的部分內容。 我也嘗試鎖定位圖像素並像這樣傳遞:

bitmapFrame.LockBits(new Rectangle(0, 0, bitmapFrame.Width, bitmapFrame.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, 
            System.Drawing.Imaging.PixelFormat.Format24bppRgb);
NativeFunctions.FaceTracker(bitmapFrame.GetHbitmap(), bitmapFrame.Width, bitmapFrame.Height);

並簡單地傳遞HBitMap,既不起作用。 我總是得到一個說明內存訪問沖突的異常。

取決於范圍。 如果可以保證在其他地方不使用位圖,則可以鎖定圖像緩沖區,然后將指針向下傳遞給C ++代碼,然后將其解鎖。

LockBits命令返回一個BitmapData類,該類在其Scan0屬性中具有指向圖像緩沖區的指針:

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!!!

您可以使用Bitmap.Save()方法將其轉換為內存流,然后將其發送到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;
}

然后,在C++ dll使用解碼如cv::imdecode()方法來獲取圖像。

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);
    // ....

這種方式有一些優點,例如, 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. 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.

唯一的問題是它是CPU密集型的,因為有編碼和解碼。

細節在這里

HBITMAP是位圖的不透明句柄。 它不是像素緩沖區。 所以你的兩段代碼不匹配。

如果將HBITMAP傳遞給本機代碼,則需要本機代碼使用GDI函數來獲取像素緩沖區並對其進行操作。 或者,您可以在托管代碼中獲取像素緩沖區並將其傳遞給本機代碼。 無論你走哪條路,你都需要匹配互操作的兩面。

我建議你使用EmguCV。 它是C#中openCV的包裝器。 你不必擔心DLL,lib等。我可以看到你想從webcamera追蹤一張臉。 EmguCV讓您可以捕獲webcamera圖像,然后以非常簡單的方式跟蹤人臉: http ://www.emgu.com/wiki/index.php/Face_detection此鏈接也可以幫助您。 請享用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM