我正在尝试使用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.