EmguCV Mat元素访问的方法——加强方法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/poisonchry/article/details/78550845

有一段时间没更新博客了,主要是因为团队现在正全力攻关事关生死的一个基于机器视觉的项目,作为一家创业公司来说,因为时间、精力、人手不够,所以一些技术方案就必须优先考虑它的便捷还有效率问题。毫无疑问,Python + OpenCV 是一种让人欲罢不能的诱惑,但是考虑到之前做的几个小DEMO,它所表现的性能看,就只好将它Pass掉了。

为此,基于 CSharp 的 EmguCV 成为我们团队首选的方案,要说它和本尊的区别,其实不大,而且考虑最近Mac、Linux都开始有了对CSharp技术的支持和跨平台方案,那么加上Visual Studio大杀器的加持,相信能很快帮助我们团队提高一定的效率。

关于我的上一篇的文章,《EmguCV Mat元素访问的方法》,确实提供了一些友谊的想法和思路去访问和解决Emgu矩阵元素的访问,不过测试过程中也发现效率不高(毕竟需要先拷贝数据到一个数组,然后再将数据数据写回内存)而且也存在对Bgr,Xyz,Bgra等特殊数据结构支持不够友好的问题。

我一直怀疑一个问题,虽然还没有找到证据,但从我感觉上,OpenCV的基本数据可能是存储在显存上,或者内存某块特定内存上的,当然如果你找到了证据请私密我

综合一段时间的使用,我这里给出一个加强版的技术方案,供有需要的朋友使用。

我在这里直接给出代码片段好了,你看一看就明白,可以在这个代码基础上进一步修改。


首先,是基于Mat类型的扩展类

    public static class MatExtension
    {

        /*
         * Caution!
         * The following method may leak memory and cause unexcepted errors.
         * Plase use GetArray after calling GetImage methods.
         */
        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;
        }

        /*
        * Caution!
        * The following method may leak memory and cause unexcepted errors.
        * Plase use GetArray after calling GetImage methods.
        */
        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;
        }

        /*
        * Caution!
        * The following method may leak memory and cause unexcepted errors.
        * Plase use GetArray after calling GetImage methods.
        */
        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;
        }

        /*
        * Caution!
        * The following method may leak memory and cause unexcepted errors.
        * Plase use GetArray after calling GetImage methods.
        */
        public static void SetDoubleArray(this Mat mat, double[] data)
        {
            Marshal.Copy(data, 0, mat.DataPointer, mat.Height * mat.Width);
        }

        /*
        * Caution!
        * The following method may leak memory and cause unexcepted errors.
        * Plase use GetArray after calling GetImage methods.
        */
        public static void SetIntArray(this Mat mat, int[] data)
        {
            Marshal.Copy(data, 0, mat.DataPointer, mat.Height * mat.Width);
        }

        /*
        * Caution!
        * The following method may leak memory and cause unexcepted errors.
        * Plase use GetArray after calling GetImage methods.
        */
        public static void SetByteArray(this Mat mat, byte[] data)
        {
            Marshal.Copy(data, 0, mat.DataPointer, mat.Height * mat.Width);
        }

        public static Image<Gray, Byte> GetGrayImage(this Mat mat)
        {
            Image<Gray, Byte> image = mat.ToImage<Gray, Byte>();
            return image;
        }

        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;
        }
    }

然后,是基于Image的拓展类

    public static class ImageExtension
    {
        public static Bgr Clone(this Bgr src)
        {
            Bgr bgr = new Bgr(src.Blue, src.Green, src.Red);
            return bgr;
        }

        public static Bgra Clone(this Bgra src)
        {
            Bgra bgr = new Bgra(src.Blue, src.Green, src.Red, src.Alpha);
            return bgr;
        }

        public static Xyz Clone(this Xyz src)
        {
            Xyz xyz = new Xyz(src.X, src.Y, src.Z);
            return xyz;
        }

        public static Mat ConvertMat(this Image<Gray, Byte> image)
        {
            Mat mat = new Mat(image.Mat, new Rectangle(0, 0, image.Width, image.Height));
            return mat;
        }

        public static Mat ConvertMat(this Image<Bgr, Byte> image)
        {
            Mat mat = new Mat(image.Mat, new Rectangle(0, 0, image.Width, image.Height));
            return mat;
        }

        public static Mat ConvertMat(this Image<Xyz, Byte> image)
        {
            Mat mat = new Mat(image.Mat, new Rectangle(0, 0, image.Width, image.Height));
            return mat;
        }

        public static Mat ConvertMat(this Image<Bgra, Byte> image)
        {
            Mat mat = new Mat(image.Mat, new Rectangle(0, 0, image.Width, image.Height));
            return mat;
        }

        public static void SubChannelsOfImage(this Image<Bgr, Byte> image,
            out Image<Gray, Byte> blue, out Image<Gray, Byte> green, out Image<Gray, Byte> red)
        {
            Image<Gray, Byte>[] subchannels = image.Split();
            blue = subchannels[0];
            green = subchannels[1];
            red = subchannels[2];
        }

        public static void SubChannelsOfImage(this Image<Xyz, Byte> image,
            out Image<Gray, Byte> x, out Image<Gray, Byte> y, out Image<Gray, Byte> z)
        {
            Image<Gray, Byte>[] subchannels = image.Split();
            x = subchannels[0];
            y = subchannels[1];
            z = subchannels[2];
        }

        public static void SubChannelsOfImage(this Image<Bgra, Byte> image,
            out Image<Gray, Byte> blue, out Image<Gray, Byte> green, out Image<Gray, Byte> red, out Image<Gray, Byte> alpha)
        {
            Image<Gray, Byte>[] subchannels = image.Split();
            blue = subchannels[0];
            green = subchannels[1];
            red = subchannels[2];
            alpha = subchannels[3];
        }

        public static double GetBlue(this Image<Bgr, Byte> image, Point point)
        {
            return image[point].Blue;
        }

        public static double GetGreen(this Image<Bgr, Byte> image, Point point)
        {
            return image[point].Green;
        }

        public static double GetRed(this Image<Bgr, Byte> image, Point point)
        {
            return image[point].Red;
        }

        public static void SetBlue(this Image<Bgr, Byte> image, Point point, double blue)
        {
            Bgr bgr = image[point].Clone();
            bgr.Blue = blue;
            image[point] = bgr;
        }

        public static void SetGreen(this Image<Bgr, Byte> image, Point point, double green)
        {
            Bgr bgr = image[point].Clone();
            bgr.Green = green;
            image[point] = bgr;
        }

        public static void SetRed(this Image<Bgr, Byte> image, Point point, double red)
        {
            Bgr bgr = image[point].Clone();
            bgr.Red = red;
            image[point] = bgr;
        }

        public static double GetBlue(this Image<Bgra, Byte> image, Point point)
        {
            return image[point].Blue;
        }

        public static double GetGreen(this Image<Bgra, Byte> image, Point point)
        {
            return image[point].Green;
        }

        public static double GetRed(this Image<Bgra, Byte> image, Point point)
        {
            return image[point].Red;
        }

        public static double GetAlpha(this Image<Bgra, Byte> image, Point point)
        {
            return image[point].Alpha;
        }

        public static void SetBlue(this Image<Bgra, Byte> image, Point point, double blue)
        {
            Bgra bgra = image[point].Clone();
            bgra.Blue = blue;
            image[point] = bgra;
        }

        public static void SetGreen(this Image<Bgra, Byte> image, Point point, double green)
        {
            Bgra bgra = image[point].Clone();
            bgra.Green = green;
            image[point] = bgra;
        }

        public static void SetRed(this Image<Bgra, Byte> image, Point point, double red)
        {
            Bgra bgra = image[point].Clone();
            bgra.Red = red;
            image[point] = bgra;
        }

        public static void SetAlpha(this Image<Bgra, Byte> image, Point point, double alpha)
        {
            Bgra bgra = image[point].Clone();
            bgra.Alpha = alpha;
            image[point] = bgra;
        }

        public static double GetX(this Image<Xyz, Byte> image, Point point)
        {
            return image[point].X;
        }

        public static double GetY(this Image<Xyz, Byte> image, Point point)
        {
            return image[point].Y;
        }

        public static double GetZ(this Image<Xyz, Byte> image, Point point)
        {
            return image[point].Z;
        }

        public static void SetX(this Image<Xyz, Byte> image, Point point, double x)
        {
            Xyz xyz = image[point].Clone();
            xyz.X = x;
            image[point] = xyz;
        }

        public static void SetY(this Image<Xyz, Byte> image, Point point, double y)
        {
            Xyz xyz = image[point].Clone();
            xyz.Y = y;
            image[point] = xyz;
        }

        public static void SetZ(this Image<Xyz, Byte> image, Point point, double z)
        {
            Xyz xyz = image[point].Clone();
            xyz.Z = z;
            image[point] = xyz;
        }

        public static double[] GetDoubleArray(this Image<Gray, Byte> image)
        {
            double[] array = new double[image.Height * image.Width];
            Array.Copy(image.Bytes, array, image.Height * image.Width);
            return array;
        }

        public static int[] GetIntArray(this Image<Gray, Byte> image)
        {
            int[] array = new int[image.Height * image.Width];
            Array.Copy(image.Bytes, array, image.Height * image.Width);
            return array;
        }

        public static byte[] GetByteArray(this Image<Gray, Byte> image)
        {
            byte[] array = new byte[image.Height * image.Width];
            Array.Copy(image.Bytes, array, image.Height * image.Width);
            return array;
        }

        public static void SetDoubleArray(this Image<Gray, Byte> image, double[] array)
        {
            if (array.Length == image.Height * image.Width)
            {
                for (int w = 0; w < image.Width; w++)
                {
                    for (int h = 0; h < image.Height; h++)
                    {
                        image.Data[h, w, 0] = (byte)array[w * image.Height + h];
                    }
                }
            }
        }

        public static void SetIntArray(this Image<Gray, Byte> image, int[] array)
        {
            if (array.Length == image.Height * image.Width)
            {
                for (int w = 0; w < image.Width; w++)
                {
                    for (int h = 0; h < image.Height; h++)
                    {
                        image.Data[h, w, 0] = (byte)array[w * image.Height + h];
                    }
                }
            }
        }

        public static void SetByteArray(this Image<Gray, Byte> image, byte[] array)
        {
            if (array.Length == image.Height * image.Width)
            {
                for (int w = 0; w < image.Width; w++)
                {
                    for (int h = 0; h < image.Height; h++)
                    {
                        image.Data[h, w, 0] = (byte)array[w * image.Height + h];
                    }
                }
            }
        }
    }

然后,是如何使用的示例代码

Mat mat = somewhere;

Image<Bgr, Byte> frame = mat.GetBgrImage();

// set something
frame.SetBlue(new Point(x,y), float_num);
// get something
double red = frame.GetRed(new Point(x,y));

// convert image to mat
Mat _mat = frame.ConvertMat();

当然,这个新的拓展方法,主要是针对Bgr,Xyz,Bgra等像素类型的数据使用的,如果你的代码主要处理的二维数组,例如Double类型的Mat,只参考我之前文章的方法已经足够了。

展开阅读全文

没有更多推荐了,返回首页