【问题标题】:C# / EmguCV - Convert an uploaded HttpPostedFileBase to a Emgu.CV.MatC# / EmguCV - 将上传的 HttpPostedFileBase 转换为 Emgu.CV.Mat
【发布时间】:2014-06-05 02:46:07
【问题描述】:

我有一个MVC 应用程序,其中我的一个控制器接收上传的文件(图像)作为HttpPostedFileBase 对象。

我正在尝试使用EmguCV 处理图像,但我很难将我的HttpPostedFileBase 转换为EmguCV 矩阵对象Emgu.CV.Mat(这只是C# 实现cv::Mat对象)。

Mat 的构造函数如下所示:

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

但我不确定如何从我的起始HttpPostedFileBase 对象中获取typedatastep。这可能吗?

我看到here,我可以将HttpPostedFileBase 转换为Image 对象(我认为这是在System.Drawing 命名空间中),这使我可以看到高度和宽度。 但是如何使用这些信息来获取发送Mat() 构造函数所需的其余参数?

【问题讨论】:

  • 你做到了吗?还是你还在努力?您需要更多帮助吗?

标签: c# opencv emgucv


【解决方案1】:

根据 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.
  • typeCvEnum.DepthType的类型,是图像的深度,你可以传递CvEnum.DepthType.Cv32F,代表32位深度的图像,其他可能的值是CvEnum.DepthType.Cv{x}{t}的形式,其中{x} 是集合 {8,16,32,64} 的任何值,{t} 可以是 Sfor SingleF for 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 位),8*4 = 32,那么对于每个单元宽度都需要 32 位。假设这是正确的,每一行都有32*width 位,将其转换为字节((8*4)*width)/8 = 4*width,即通道数乘以图像宽度。

更新

获取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 代码 here.、Bitmap IntPtr here 以及这个 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

【讨论】:

  • 嗨,我如何从 Image 创建一个 Mat ?用 EmguCV 尝试了很多方法,但都失败了
【解决方案2】:

我认为做你想做的最简单的方法是从你得到的图像创建一个Bitmap,点击你的链接,了解如何将HttpPostedFileBase 转换为BitmapBitmap 类有一个带有 Image 参数的构造函数。然后,您可以使用此Bitmap 创建一个Emgu.CV.Image,同样Image 类可以在构造函数中使用Bitmap。这些方法的缺点是您将获得Image 而不是Mat

现在,您问如何创建 Mat 对象,我不确定您在说什么,因为我在 EmguCV (2.4.9) 中找不到这个类。有一个 Matrix 类,但它的构造函数看起来不像你问题中的那个。因此,为了向您提供有关typedatastep 参数的更多信息,请知道type 依赖于图像的PixelFormat 属性。它是一个枚举,可以有大约 20 个不同的值。在我的测试中,图像有一个PixelFormat.Format24bppRgb 值,这意味着它是一个 3 通道图像,其中每个通道是 8 位,所以在这种情况下类型应该是字节。我建议关注this 链接,了解如何获取指定 PixelFormat 的位深度。

对于数据参数,您需要从Bitmap 中获取BitmapData 并获取Scan0 属性,如here 中所述。

对于步骤参数,您将再次需要BitmapData,但这次是代表步骤的Stride 参数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-12
    • 1970-01-01
    • 1970-01-01
    • 2012-07-26
    • 1970-01-01
    相关资源
    最近更新 更多