2014-06-05 33 views
6

我有一個MVC應用程序,其中一個控制器接收上傳文件(圖像)作爲HttpPostedFileBase對象。C#/ EmguCV - 將上傳的HttpPostedFileBase轉換爲Emgu.CV.Mat

我嘗試過程中使用EmguCV的形象,但我有困難的轉換我HttpPostedFileBaseEmguCV矩陣對象Emgu.CV.Mat(這僅僅是一個C#實施cv::Mat的對象)。

沒有爲Mat構造,看起來像:

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

,但我不知道如何讓typedatastep從我開始HttpPostedFileBase對象。這可能嗎?

我看到here,我可以一個HttpPostedFileBase轉換爲Image對象(我認爲這是在System.Drawing命名空間),這讓我看到的高度和寬度。 但是我怎樣才能使用這些信息來獲得剩下的參數來發送Mat()的構造函數呢?

+0

你做到了嗎?或者你還在嘗試?你需要更多的幫助嗎? –

回答

5

按照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,可以傳遞返回一個IntPtr到用戶數據的Bitmap.GetHbitmap()。如果每個像素有4個通道,每個通道的範圍從0到255(8位),8*4 = 32,那麼對於你的每個單位寬度,你都會給你一個猜測的猜測需要32位。假設這是正確的,每行有32*width位,將其轉換爲字節數((8*4)*width)/8 = 4*width,這是通道數乘以圖像寬度。

UPDATE

其他方式獲得datastepBitmapData類,像這樣(摘自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代碼here位圖的IntPtrhere,也對這個post這有助於我還獲得這個進一步的瞭解。

我看到其他的方法來做到這一點還,除非你真的需要調用完整的構造,我會嘗試這種做法,似乎更清潔:

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 documentation有很棒的教程。只需看看核心模塊的可用教程。特別是這個one

+1

嗨,我如何從圖片創建一個墊子?用EmguCV嘗試很多方法,但每個都失敗 –

3

我認爲最簡單的方法就是根據您的鏈接創建一個Bitmap,然後按照如何將HttpPostedFileBase轉換爲BitmapBitmap類具有一個參數爲Image的構造函數。然後,您可以使用此Bitmap創建一個Emgu.CV.Image,同樣Image類可以在構造函數中使用Bitmap。這些方法的缺點是你會得到一個Image而不是一個Mat

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

對於數據參數,您需要從Bitmap獲取BitmapData,並獲取Scan0屬性,如here所述。

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