![](/img/trans.png)
[英]EmguCV capture error: Cannot implicitly convert type 'Emgu.CV.Mat' to 'Emgu.CV.Image<Emgu.CV.Structure.Bgr,byte>
[英]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
對象中獲取type
, data
和step
。 這可能嗎?
我在這里看到,我可以將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
表示Single
, F
表示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
獲取data
和step
其他方法來自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);
}
注意
我想,做你想要什么,最簡單的方法是創建一個Bitmap
與您獲得以下你對如何轉換鏈接的圖片HttpPostedFileBase
以Bitmap
。 Bitmap
類有一個帶Image
參數的構造函數。 然后,您可以使用此Bitmap
創建一個Emgu.CV.Image
, Image
類也可以在構造函數中創建一個Bitmap
。 這些方法的缺點是你會得到一個Image
而不是Mat
。
現在,你問如何創建一個Mat
對象,我不確定你在說什么,因為我在EmguCV(2.4.9)中找不到這個類。 有一個Matrix
類,但它的構造函數看起來不像你問題中的那個。 因此,為了向您提供有關type
, data
和step
參數的更多信息,請知道該type
取決於Image的PixelFormat
屬性。 它是一個枚舉,可以有大約20個不同的值。 在我的測試中,圖像具有PixelFormat.Format24bppRgb
值,這意味着它是3通道圖像,其中每個通道是8位,因此在這種情況下類型應該是字節。 我建議按照這個鏈接來了解如何獲得指定PixelFormat的位深度。
對於數據參數,您將需要得到BitmapData
從Bitmap
,並獲得Scan0
,因為它說明財產這里 。
對於step參數,您將再次需要BitmapData
但這次是表示步驟的Stride
參數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.