您的位置:首页 > 健康 > 养生 > EmguCV学习笔记 C# 2.5 Mat类、Matrix类和Image类的相互转换

EmguCV学习笔记 C# 2.5 Mat类、Matrix类和Image类的相互转换

2024/12/22 18:02:12 来源:https://blog.csdn.net/UruseiBest/article/details/141257174  浏览:    关键词:EmguCV学习笔记 C# 2.5 Mat类、Matrix类和Image类的相互转换

 版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。

EmguCV学习笔记目录 Vb.net

EmguCV学习笔记目录 C#

笔者的博客网址:VB.Net-CSDN博客

教程相关说明以及如何获得pdf教程和代码(博客上的教程内容会和pdf教程一致,教程中也会包含所有代码),请移步:EmguCV学习笔记

2.5 Mat类、Matrix类和Image类的相互转换

Mat类、Matrix类和Image类的联系:

1、Mat和Image都可以用于存储图像数据,但Image只能用于存储具有颜色和深度信息的图像数据。

2、Mat和Image都可以进行图像的基本操作,如剪裁、缩放、旋转等。

3、Matrix和Mat都可以用于存储矩阵数据,并可以进行矩阵的基本操作,如转置、逆运算、矩阵乘法等。

4、此外,Cvinvoke类提供的方法,既支持Mat也支持Image,例如Add方法。

Mat类、Matrix类和Image类的区别:

1、Mat可以存储任意类型的图像数据,包括单通道和多通道的数据;而Image只能用于存储具有颜色和深度信息的图像数据。

2、Matrix只能用于存储矩阵数据,不能用于存储图像数据。

在使用时,我们应该根据实际需求选择合适的类来处理图像和矩阵数据。如果只是简单的图像处理,可以使用Image类;如果需要进行更复杂的矩阵运算,可以使用Mat类;而如果需要更高效、更灵活的矩阵运算,可以使用Matrix类。

Mat类、Matrix类和Image类的相互转换

Mat、Image和Matrix都是表示图像和矩阵数据的类。它们之间可以通过一些方法相互转换。

下面的小节将说明如何在Mat、Image、Matrix以及.Net提供的Bitmap类之间相互转换。

2.5.1 Image到Mat的转换

直接使用Image类的Mat属性。

【代码位置:frmChapter2_4】Button1_Click、outputMatInfo、outputMatdata8U1CAfter

       //ImageMat

        private void Button1_Click(object sender, EventArgs e)

        {

            Image<Gray, byte> img = new Image<Gray, byte>(new Size(3, 4));

            img.SetValue(new MCvScalar(200));

            //注意,此时mIsContinuous属性是false,也就是数据不连续

            Mat m;

            m = img.Mat;

            outputMatInfo(m);

            outputMatdata8U1CAfter(m);

        }

    //输出Mat信息

    private void outputMatInfo(Mat m)

        {

            Console.WriteLine("Cols" + m.Cols);

            Console.WriteLine("Rows" + m.Rows);

            Console.WriteLine("Depth" + m.Depth);

            Console.WriteLine("ElementSize" + m.ElementSize);

            Console.WriteLine("Height" + m.Height);

            Console.WriteLine("Width" + m.Width);

            Console.WriteLine("NumberOfChannels" + m.NumberOfChannels);

            Console.WriteLine("Step" + m.Step);

            Console.WriteLine("Width*Height" + m.Size.Width + "*" + m.Size.Height);

            Console.WriteLine("IsContinuous" + m.IsContinuous);

            Console.WriteLine("=====================");

        }

       //修改后的方法(考虑数据不连续的情况)

        //输出矩阵,为简化说明,这里参数为8U单通道Mat

        private void outputMatdata8U1CAfter(Mat m)

        {

            int colcount = m.Cols;

            int rowcount = m.Rows;

            int matstep = m.Step;

            //每次读取数据时候的指针位置

            IntPtr pos = IntPtr.Zero;

            for (int i = 0; i < rowcount; i++)

            {

                //检查指针位置,

                //如果是第一次循环,即pos初始为0,那么指针位置为mat的指针位置

                //否则,应该将指针位置增加step

                if (pos == IntPtr.Zero)

                    pos = m.DataPointer;

                else

                    pos += matstep;

                int bufferSize = colcount;

                byte[] buffer = new byte[bufferSize];

                //每次循环从新的指针位置拷贝数据,拷贝的数量为mat的列数。

                System.Runtime.InteropServices.Marshal.Copy(pos, buffer, 0, bufferSize);

                for (int col = 0; col < colcount; col++)

                    Console.Write(buffer[col] + " ");

                Console.WriteLine();

            }

        }

运行后如下图所示:

 

图2-75 Image转Mat后的信息

注意:上述代码运行后返回的信息:

Step:4

IsContinuous:False

这是因为在EmguCV中,Image类的Data属性表示图像数据的指针。对于一个M*N的单通道图像,其Data属性的大小本应该是M*N个字节。但是,由于内存对齐的原因(通常是按照4个字节来对齐),实际上分配给图像数据的内存大小可能会大于M*N个字节。

针对上述代码,其中创建了一个3*4的单通道图像img,该图像的深度为Byte,每个像素占用1个字节。因此,该图像的总共应该占用3*4=12个字节。但是,由于内存对齐的原因,这里总共分配了16个字节给该图像数据。

2.5.2 Matrix转Mat

直接使用Matrix类的Mat属性。

在【2.3.1 构造函数】中已经讲解过,这里不再赘述。

2.5.3 Image转Matrix

使用Image类的CopyTo方法。

【代码位置:frmChapter2_4】Button2_Click

       //灰度Imagematrix

        private void Button2_Click(object sender, EventArgs e)

        {

            Image<Gray, byte> img = new Image<Gray, byte>("C:\\learnEmgucv\\lena.jpg");

            //分配Matrix大小

            Matrix<byte> matr = new Matrix<byte>(img.Size);

            img.CopyTo(matr);

            //matrix不能直接转图片

            Mat mDst;

            mDst = matr.Mat;

            //这里使用.NetPictureBox,使用Mat转为了Bitmap

            PictureBox1.Image = mDst.ToBitmap();

        }

运行后如下图所示:

 

图2-76 灰度图像转matrix后的显示

【代码位置:frmChapter2_4】Button3_Click

       //彩色Imagematrix

        private void Button3_Click(object sender, EventArgs e)

        {

            //由于使用Image<Bgr, byte>,后面的matr必须指明通道数(3

            Image<Bgr, byte> img = new Image<Bgr, byte>("C:\\learnEmgucv\\lena.jpg");

            //分配Matrix大小,注意,这里指明了3通道

            Matrix<byte> matr = new Matrix<byte>(img.Rows, img.Cols, 3);

            img.CopyTo(matr);

            //matrix不能直接转图片

            Mat mDst = matr.Mat;

            //这里使用.NetPictureBox,使用Mat转为了Bitmap

            PictureBox1.Image = mDst.ToBitmap();

        }

运行后如下图所示:

 

图2-77 彩色图像转matrix后的显示

2.5.4 Mat转Matrix

使用Mat类的CopyTo方法。

【代码位置:frmChapter2_4】Button4_Click

        //MatMatrix

        private void Button4_Click(object sender, EventArgs e)

        {

            Mat m = new Mat("C:\\learnEmgucv\\lena.jpg", Emgu.CV.CvEnum.ImreadModes.Grayscale);

            //需要注意通道数

            Matrix<byte> matr = new Matrix<byte>(m.Size);

            //MatCopyTo方法

            m.CopyTo(matr);

            Mat mDst = matr.Mat;

            PictureBox1.Image = mDst.ToBitmap();

        }

运行后如下图所示:

 

图2-78 Mat转matrix后的显示

2.5.5 Image转Bitmap

使用Image类的ToBitmap方法。

【代码位置:frmChapter2_4】Button5_Click

       //ImageBitmap

        private void Button5_Click(object sender, EventArgs e)

        {

            Image<Bgr, byte> img = new Image<Bgr, byte>("C:\\learnEmgucv\\lena.jpg");

            Bitmap bmp = img.ToBitmap();

            PictureBox1.Image = bmp;

        }

运行后如下图所示:

 

图2-79 Image转Bitmap后的显示

2.5.6 Bitmap转Image

使用BitmapExtension类的ToImage方法进行转换。

【代码位置:frmChapter2_4】Button6_Click

       //BitmapImage

        private void Button6_Click(object sender, EventArgs e)

        {

            Bitmap bmp = new Bitmap("C:\\learnEmgucv\\lena.jpg");

            Image<Bgr, byte> img;

            img = BitmapExtension.ToImage<Bgr, byte>(bmp);

            //如果转灰度,应将Bgr修改为Gray,如下代码:

            //Image<Bgr, byte> img;

            //img = BitmapExtension.ToImage<Gray, byte>(bmp);

            PictureBox1.Image = img.ToBitmap();

        }

运行后如下图所示:

 

图2-80 Bitmap转Image后的显示

2.5.7 Mat转Bitmap

使用Mat类的ToBitmap方法。

【代码位置:frmChapter2_4】Button7_Click

        //MatBitmap

        private void Button7_Click(object sender, EventArgs e)

        {

            Mat m = new Mat("C:\\learnEmgucv\\lena.jpg", Emgu.CV.CvEnum.ImreadModes.Color);

            Bitmap bmp = m.ToBitmap();

            PictureBox1.Image = bmp;

        }

运行后如下图所示:

 

图2-81 Mat转Bitmap后的显示

2.5.8 Bitmap转Mat

1、使用BitmapExtension的ToMat方法

【代码位置:frmChapter2_4】Button8_Click

        //BitmapMat1

        private void Button8_Click(object sender, EventArgs e)

        {

            Bitmap bmp = new Bitmap("C:\\learnEmgucv\\lena.jpg");

            Mat m = new Mat();

            m = BitmapExtension.ToMat(bmp);

            PictureBox1.Image = m.ToBitmap();

        }

运行后如下图所示:

 

图2-82 Bitmap转Mat后的显示

2、使用BitmapData

【代码位置:frmChapter2_4】Button9_Click

        //BitmapMat2

        private void Button9_Click(object sender, EventArgs e)

        {

            Bitmap bmp = new Bitmap("C:\\learnEmgucv\\lena.jpg");

            BitmapData bmpdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

            //需要计划好Mat的大小、深度、通道数、步长

            Mat m = new Mat(bmp.Height, bmp.Width, Emgu.CV.CvEnum.DepthType.Cv8U, 3, bmpdata.Scan0, bmpdata.Stride);

            bmp.UnlockBits(bmpdata);

            PictureBox1.Image = m.ToBitmap();

        }

运行后如下图所示:

 

图2-83 Bitmap转Mat后的显示

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com