C#/ EmguCV - 将上传的HttpPostedFileBase转换为Emgu.CV.Mat

Bre*_*ett 6 c# opencv emgucv

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

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

有一个构造函数Mat,看起来像:

public Mat(int rows, int cols, DepthType type, int channels, IntPtr data, int step);
Run Code Online (Sandbox Code Playgroud)

但我不知道如何获得type,data以及step从我开始HttpPostedFileBase的对象.这可能吗?

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

Joã*_*nho 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.
Run Code Online (Sandbox Code Playgroud)
  • type是类型CvEnum.DepthType,它是图像的深度,你可以传递CvEnum.DepthType.Cv32F它代表32位深度图像,其他可能的值是形式CvEnum.DepthType.Cv{x}{t},其中{x}是集合的任何值{8,16,32,64}和{t}可以是Sfor SingleFfor Float.

  • channels,取决于图像的类型,但我认为你可以使用4ARGB.

对于其他2个参数,如果您不需要优化部分,则可以使用Mat该类的构造函数:

public Mat(int rows, int cols, DepthType type, int channels)
Run Code Online (Sandbox Code Playgroud)

如果您真的想使用优化版本,那么(继续):

  • data,您可以传递Bitmap.GetHbitmap(),它将IntPtr返回给用户数据.

  • step对于这个家伙,我会给你一个明智的猜测,如果每个像素你有4个通道,每个通道的范围从0到255(8位)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);
Run Code Online (Sandbox Code Playgroud)

没有测试过这个解决方案,但你可以尝试一下.我的答案是基于这里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);
}
Run Code Online (Sandbox Code Playgroud)

注意

OpenCV文档中有很棒的教程.只需查看核心模块的可用教程.特别是这一个.