我正在尝试使用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对象中获取类型,数据和步骤.这可能吗?
我看到here,我可以将HttpPostedFileBase转换为Image对象(我认为它在System.Drawing命名空间中),这允许我查看高度和宽度.但是,如何使用此信息获取其余所需参数以发送Mat()构造函数?
解决方法
- /// <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}可以是Sfor Single或F for Float.
>频道,取决于图像的类型,但我认为你可以使用4来自ARGB.
对于其他2个参数,如果不需要优化部分,则可以使用Mat类的这个构造函数:
- public Mat(int rows,int channels)
如果您真的想使用优化版本,那么(继续):
> data,您可以传递Bitmap.GetHbitmap(),它将IntPtr返回给用户数据.
>一步,对于这个家伙,我会给你一个明智的猜测,如果每个像素你有4个通道,每个通道的范围从0到255(8位),8 * 4 = 32,所以对于每个单位的宽度你需要32位.假设这是正确的,每行有32 *宽度位,将其转换为字节((8 * 4)*宽度)/ 8 = 4 *宽度,这是通道数乘以图像宽度.
UPDATE
获取数据和步骤的其他方法是从BitmapData类,这样(摘自MSDN资源):
- Bitmap bmp = new Bitmap(Image.FromStream(httpPostedFileBase.InputStream,true,true));
- // Lock the bitmap's bits.
- Rectangle rect = new Rectangle(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,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.