EmguCV Mat元素访问的方法

来源:互联网 发布:java学多久可以上岗 编辑:程序博客网 时间:2024/05/17 03:48

EmguCV Mat元素访问的方法

Emgu是C#封装的OpenCV库,基本的使用方法和OpenCV一样,但是在具体使用中还是有一些不太一样的地方。例如对矩阵元素的访问方法上,Emgu因为C#封装的关系,而不推荐使用指针直接访问元素,因此我们对元素的操作和处理就变得比较费力了。

举个例子来说

#include <opencv/core.hpp>...cv::Mat mat = // get from somewherecv::Mat_<float> matrix = mat;float * ptr = matrix.ptr<float>(x,y); // access the elementfloat pt = matrix.at<float>(x,y); // access the element...

但是Emgu就不能这样直接访问操作了。根据我目前的研究看,访问Emgu数据的方法,若数据元素是基础数据,也就是double, float, int这种类型,那么可以用Marshal的Copy方法,把底层数据拷贝到一个一维数组中,然后你对数组进行操作后,再把写好的数据用Marshal的Copy方法写回Emgu Mat中,如果是Bgr,Bgra,Xyz 或者其他的数据,最安全的方法是用ToImage方法将数据转换成为Image,然后再去操作处理。

using Emgu.CV;using Emgu.CV.Structure;using System;using System.Runtime.InteropServices;namespace VpgLibCS{    public static class MatExtension    {        public static double[] GetDoubleArray(this Mat mat)        {            double[] temp = new double[mat.Height * mat.Width];            Marshal.Copy(mat.DataPointer, temp, 0, mat.Height * mat.Width);            return temp;        }        public static int[] GetIntArray(this Mat mat)        {            int[] temp = new int[mat.Height * mat.Width];            Marshal.Copy(mat.DataPointer, temp, 0, mat.Height * mat.Width);            return temp;        }        public static byte[] GetByteArray(this Mat mat)        {            byte[] temp = new byte[mat.Height * mat.Width];            Marshal.Copy(mat.DataPointer, temp, 0, mat.Height * mat.Width);            return temp;        }        public static Image<Bgr, Byte> GetBgrImage(this Mat mat)        {            Image<Bgr, Byte> image = mat.ToImage<Bgr, Byte>();            return image;        }        public static Image<Xyz, Byte> GetXyzImage(this Mat mat)        {            Image<Xyz, Byte> image = mat.ToImage<Xyz, Byte>();            return image;        }        public static Image<Bgra, Byte> GetBgraImage(this Mat mat)        {            Image<Bgra, Byte> image = mat.ToImage<Bgra, Byte>();            return image;        }        public static void SetImage(this Mat mat, Image<Bgr, Byte> image)        {            mat.Dispose();            mat = image.Mat;        }        public static void SetImage(this Mat mat, Image<Bgra, Byte> image)        {            mat.Dispose();            mat = image.Mat;        }        public static void SetImage(this Mat mat, Image<Xyz, Byte> image)        {            mat.Dispose();            mat = image.Mat;        }        public static void SetArray(this Mat mat, double[] data)        {            Marshal.Copy(data, 0, mat.DataPointer, mat.Height * mat.Width);        }        public static void SetArray(this Mat mat, int[] data)        {            Marshal.Copy(data, 0, mat.DataPointer, mat.Height * mat.Width);        }        public static void SetArray(this Mat mat, byte[] data)        {            Marshal.Copy(data, 0, mat.DataPointer, mat.Height * mat.Width);        }    }}

我在这里把我处理的方法贴出来,仅供参考。

另外说一下,我不赞成用dynamic进行编译这个程序,感觉在某些时候可能会出点莫名其妙的bug,最安全的手段还是直接多写几个常用的类型,做多态处理,这样安全点。毕竟这种类写好了,就基本不需要修改的。另外,我们常用的基本类型是double, int, byte三种类型,偶尔可能会用到float,或者char类型,这个根据你个人需要进行修改吧。

目前这些处理方法,针对一维、二维的矩阵都能正常使用,高纬的没测试过,你可以试着做个扩展。

使用方法是导入这个文件后,当你申明了自己的Mat类型,就可以用以上方法进行访问,例如:

    ...    public void MatTester()    {        Emgu.CV.Mat mat = // get from somewhere        double[] array = mat.GetDoubleArray()        for (int i = 0; i < mat.Rows; i++)        {            for (int j = 0; j < mat.Cols; j++)            {                array[i*mat.Rows + j] = // assign something            }        }        // copy back to matrix        mat.SetArray(array);    }    ...

需要注意,没测试过不同维度不同基础数据的矩阵赋值是否存在问题,感觉应该会,因为Marshal.Copy的本质,是对byte的读写,如果基础数据不同,例如double和int,可能就会出现问题,所以使用的时候务必小心点。

原创粉丝点击