簡體   English   中英

C#/ EmguCV - 將上傳的HttpPostedFileBase轉換為Emgu.CV.Mat

[英]C# / EmguCV - Convert an uploaded HttpPostedFileBase to a Emgu.CV.Mat

我有一個MVC應用程序,其中一個控制器接收上傳的文件(圖像)作為HttpPostedFileBase對象。

我正在嘗試使用EmguCV處理圖像,但是我很難將我的HttpPostedFileBase轉換為EmguCV矩陣對象Emgu.CV.Mat (這只是cv::Mat對象的C#實現)。

Mat的構造函數如下所示:

public Mat(int rows, int cols, DepthType type, int channels, IntPtr data, int step);

但我不知道如何從我的起始HttpPostedFileBase對象中獲取typedatastep 這可能嗎?

在這里看到,我可以將HttpPostedFileBase轉換為Image對象(我認為它在System.Drawing命名空間中),這允許我查看高度和寬度。 但是,如何使用此信息獲取其余所需參數以發送Mat()構造函數?

根據Emgu規范,這些參數意味着:

  /// <param name="type">Mat element type

  /// <param name="channels">Number of channels

  /// <param name="data">
  /// Pointer to the user data. Matrix constructors that take data and step parameters do not  
  /// allocate matrix data. Instead, they just initialize the matrix header that points to the 
  /// specified data, which means that no data is copied. This operation is very efficient and 
  /// can be used to process external data using OpenCV functions. The external data is not 
  /// automatically deallocated, so you should take care of it.

  /// <param name="step">
  /// Number of bytes each matrix row occupies. 
  /// The value should include the padding bytes at the end of each row, if any.
  • type的類型為CvEnum.DepthType ,它是圖像的深度,您可以傳遞CvEnum.DepthType.Cv32F ,它代表32位深度圖像,其他可能的值的形式為CvEnum.DepthType.Cv{x}{t} ,其中{x}是集合{8,16,32,64}的任何值,{t}可以是S表示SingleF表示Float

  • channels ,取決於圖像的類型,但我認為你可以使用ARGB 4

對於其他2個參數,如果不需要優化部分,則可以使用Mat類的這個構造函數:

public Mat(int rows, int cols, DepthType type, int channels)

如果您真的想使用優化版本,那么(繼續):

  • data ,您可以傳遞Bitmap.GetHbitmap(),它返回一個IntPtr到用戶數據。

  • step ,對於這個家伙,我會給你一個明智的猜測,如果每個像素你有4個通道,每個通道的范圍從0到255( 8*4 = 32位), 8*4 = 32 ,所以對於你需要的每個單位寬度32位。 假設這是正確的,每行有32*width位,將其轉換為字節((8*4)*width)/8 = 4*width ,這是通道數乘以圖像寬度。

UPDATE

獲取datastep其他方法來自BitmapData類,如下所示(摘自MSDN資源):

Bitmap bmp = new Bitmap(Image.FromStream(httpPostedFileBase.InputStream, true, true));

// Lock the bitmap's bits.  
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);

System.Drawing.Imaging.BitmapData bmpData =
    bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
        bmp.PixelFormat);

// data = scan0 is a pointer to our memory block.
IntPtr data = bmpData.Scan0;

// step = stride = amount of bytes for a single line of the image
int step = bmpData.Stride;

// So you can try to get you Mat instance like this:
Mat mat = new Mat(bmp.Height, bmp.Width, CvEnum.DepthType.Cv32F, 4, data, step);

// Unlock the bits.
bmp.UnlockBits(bmpData);

沒有測試過這個解決方案,但你可以嘗試一下。 我的回答是基於這里Emgu代碼。, Bitmap IntPtr 在這里以及這篇文章也幫助我對此有了進一步的了解。

我已經看到了其他方法,除非你真的需要調用那個完整的構造函數,我會嘗試這種方法,看起來更干凈:

HttpPostedFileBase file //your file must be available is this context.

if (file.ContentLength > 0)
{
    string filename = Path.GetFileName(file.FileName);

    // your so wanted Mat!
    Mat img = imread(filename, CV_LOAD_IMAGE_COLOR);
}

注意

OpenCV文檔中有很棒的教程。 只需查看核心模塊的可用教程。 特別是這一個

我想,做你想要什么,最簡單的方法是創建一個Bitmap與您獲得以下你對如何轉換鏈接的圖片HttpPostedFileBaseBitmap Bitmap類有一個帶Image參數的構造函數。 然后,您可以使用此Bitmap創建一個Emgu.CV.ImageImage類也可以在構造函數中創建一個Bitmap 這些方法的缺點是你會得到一個Image而不是Mat

現在,你問如何創建一個Mat對象,我不確定你在說什么,因為我在EmguCV(2.4.9)中找不到這個類。 有一個Matrix類,但它的構造函數看起來不像你問題中的那個。 因此,為了向您提供有關typedatastep參數的更多信息,請知道該type取決於Image的PixelFormat屬性。 它是一個枚舉,可以有大約20個不同的值。 在我的測試中,圖像具有PixelFormat.Format24bppRgb值,這意味着它是3通道圖像,其中每個通道是8位,因此在這種情況下類型應該是字節。 我建議按照這個鏈接來了解如何獲得指定PixelFormat的位深度。

對於數據參數,您將需要得到BitmapDataBitmap ,並獲得Scan0 ,因為它說明財產這里

對於step參數,您將再次需要BitmapData但這次是表示步驟的Stride參數。

暫無
暫無

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

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