当前位置: 首页 > news >正文

EmguCV学习笔记 C# 2.2 Matrix类

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

EmguCV学习笔记目录 Vb.net

EmguCV学习笔记目录 C#

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

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

2.2 Matrix类

Matrix类是EmguCV中的一个矩阵类,它可以用来存储和处理矩阵数据,可以处理任意维度的矩阵。与Mat类相比,Matrix类提供了更多的矩阵运算方法,如矩阵加减、乘法、逆矩阵等,也更加灵活,而且底层实现也更加高效。

通常而言,Matrix类应为Matrix<数据类型> 的形式,其中数据类型指明了该矩阵中元素的存储类型,包括byteintfloat等。

2.2.1 构造函数

为了显示Matrix结果,请在窗体上放置一个MatrixBox控件。该控件位于【工具箱】|【Emgu.CV】下面。另外,

1、使用一维数组初始化Matrix

【代码位置:frmChapter2_1】Button1_Click

        //Matrix构造函数:一维数组初始化Matrix

        private void Button1_Click(object sender, EventArgs e)

        {

            byte[] inputBytes = new Byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

            Matrix<byte> matr = new Matrix<byte>(inputBytes);

            MatrixBox1.Matrix = matr;

        }

显示结果如下:

 

图2-2 一维数组初始化Matrix

2、使用二维数组初始化Matrix

【代码位置:frmChapter2_1】Button2_Click

        //Matrix构造函数:二维数组初始化Matrix

        private void Button2_Click(object sender, EventArgs e)

        {

            byte[,] inputBytes = new byte[,] { { 1, 2, 3 }, { 3, 4, 5 }, { 5, 6, 7 }, { 7, 8, 9 } };

            Matrix<byte> matr = new Matrix<byte>(inputBytes);

            MatrixBox1.Matrix = matr;

        }

显示结果如下:

 

图2-3 二维数组初始化Matrix

3、指定大小初始化Matrix,然后写入值:

【代码位置:frmChapter2_1】Button3_Click

        //Matrix构造函数:初始化矩阵的大小(Size

        //注意使用size的话,width是列,height是行,列在前,行灾后

        //以下创建的是一个24行的矩阵

        private void Button3_Click(object sender, EventArgs e)

        {

            byte[] inputBytes = new Byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

            Matrix<byte> matr = new Matrix<byte>(new Size(2, 4));

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

                for (int j = 0; j <= 3; j++)

                    matr[j, i] = inputBytes[i * 4 + j];

            MatrixBox1.Matrix = matr;

        }

先是初始化一个2列(Width)4行(Height)的矩阵,然后使用循环,将数组的数据写入矩阵。

显示结果如下:

 

图2-4 指定大小初始化Matrix

也可以通过SetValue方法设置相同的值:

【代码位置:frmChapter2_1】Button4_Click

        //Matrix构造函数:初始化矩阵的大小(Size

        private void Button4_Click(object sender, EventArgs e)

        {

            Matrix<byte> matr = new Matrix<byte>(new Size(2, 4));

            //将所有元素 设置相同的指定值

            matr.SetValue(new MCvScalar(20));

            MatrixBox1.Matrix = matr;

        }

显示结果如下:

 

图2-5 对Matrix的元素设置相同的值

4、指定行、列、通道初始化Matrix,并将向每个通道写入相同的值:

【代码位置:frmChapter2_1】Button5_Click

        //Matrix构造函数:行、列、通道初始化矩阵

        private void Button5_Click(object sender, EventArgs e)

        {

            //row是行,col是列,行在前,列在后

            //以下创建的是一个243通道的矩阵

            Matrix<byte> matr = new Matrix<byte>(4, 3, 3);

            //设置各个通道的元素的值

            matr.SetValue(new MCvScalar(20, 30, 40));

            MatrixBox1.Matrix = matr;

     }

显示结果如下:

 

图2-6 对多通道Matrix的元素设置相同的值

注意:这个构造函数和通过Size方式初始化Matrix的构造函数有所区别的是,行和列出现的先后不同。Size(列,行),而这个是行、列、通道。

这里对Matrix元素的每个通道设置了值,在MatrixBox控件中可以在channel处下拉选择查看不同通道的值。

5、指定行、列、通道初始化Matrix,并将每个通道的值设置为0:

【代码位置:frmChapter2_1】Button6_Click

        //Matrix元素的值全部设置为0(多通道设置每个通道为0

        private void Button6_Click(object sender, EventArgs e)

        {

            Matrix<byte> matr = new Matrix<byte>(4, 3, 3);

            matr.SetZero();

            MatrixBox1.Matrix = matr;

     }

显示结果如下:

 

图2-7 设置多通道Matrix的元素的值为0

2.2.2 获取Matrix元素的值

在以下代码中提供了3种方法来获取Matrix指定位置(,)的值。

【代码位置:frmChapter2_1】Button7_Click

        private void Button7_Click(object sender, EventArgs e)

        {

            byte[,] inputBytes = new byte[,] { { 1, 2, 3 }, { 3, 4, 5 }, { 5, 6, 7 }, { 7, 8, 9 } };

            Matrix<byte> matr = new Matrix<byte>(inputBytes);

            MatrixBox1.Matrix = matr;

            //方法1:直接使用Matrix(,)进行输出,使用时需要注意行列的顺序

            for(int i= 0;i< matr.Rows;i++)

            {

                for (int j = 0; j < matr.Cols; j++)

                    //通过matr[i,j]获得值的方式只适用于单通道矩阵

                    TextBox1.Text += matr[i, j] + " ";

                TextBox1.Text += "\r\n";

            }

            TextBox1.Text += "====================" + "\r\n";

            //方法2:先读取到一维数组,再输出

            byte[] outputBytes1;

            outputBytes1 = matr.Bytes;

            int height = matr.Rows;

            int width = matr.Cols;

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

            {

                for (int j = 0; j < width; j++)

                    TextBox1.Text += outputBytes1[i * width + j] + " ";

                TextBox1.Text += "\r\n";

            }

            TextBox1.Text += "====================" + "\r\n";

            //方法3:先读取到二维数组,再输出

            byte[,] outputBytes2;

            outputBytes2 = matr.Data;

            //这里是二维数组,所以返回2

            int outputBytesRank = outputBytes2.Rank;

            for (int i = 0; i < outputBytes2.GetLength(0); i++)

            {

                for (int j = 0; j < outputBytes2.GetLength(1); j++)

                    TextBox1.Text += outputBytes2[i, j] + " ";

                TextBox1.Text += "\r\n";

            }

    }

注意:只适合单通道Matrix。对于多通道Matrix需要将其分解成多个单通道Matrix再进行处理。

显示结果如下:

 

图2-8 读取单通道矩阵元素的值

2.2.3 Matrix的拆分

使用MatrixSplit方法将多通道矩阵拆分为单通道矩阵。

【代码位置:frmChapter2_1】Button8_Click

        //将多通道Matrix拆分为多个单通道Matrix

        private void Button8_Click(object sender, EventArgs e)

        {

            Matrix<byte> matr = new Matrix<byte>(4, 2, 3);

            matr.SetValue(new MCvScalar(20, 30, 40));

            Matrix<byte>[] arrMatr;

            //使用Split方法拆分多通道矩阵到矩阵数组。

            arrMatr = matr.Split();

            //显示第一个通道的值

            MatrixBox1.Matrix = arrMatr[0];

        }

显示结果如下:

 

图2-9 Matrix第一个通道的值

2.2.4 Matrix的运算

2.2.4.1 加法

1、加一个数值

【代码位置:frmChapter2_1】Button9_Click

        //Matrix的加法1:增加一个固定值

        private void Button9_Click(object sender, EventArgs e)

        {

            byte[,] inputBytes = new byte[,] { { 1, 2, 3 }, { 3, 4, 5 }, { 5, 6, 7 }, { 7, 8, 9 } };

            Matrix<byte> matr1 = new Matrix<byte>(inputBytes);

            Matrix<byte> matr2;

            //方法1

            matr2 = matr1 + 30;

            //方法2

            //matr2 = matr1.Add(30);

            MatrixBox1.Matrix = matr2;

     }

显示结果如下:

 

图2-10 Matrix增加一个固定值

2、两个单通道矩阵相加

【代码位置:frmChapter2_1】Button10_Click

        //Matrix的加法2:两个单通道矩阵相加

        private void Button10_Click(object sender, EventArgs e)

        {

            byte[,] inputBytes1 = new byte[,] { { 1, 2, 3 }, { 3, 4, 5 }, { 5, 6, 7 }, { 7, 8, 9 } };

            byte[,] inputBytes2 = new byte[,] { { 3, 4, 5 }, { 5, 6, 7 }, { 7, 8, 9 }, { 9, 10, 11 } };

            Matrix<byte> matr1=new Matrix<byte>(inputBytes1);

            Matrix<byte> matr2 = new Matrix<byte>(inputBytes2);

            Matrix<byte> matr3 = new Matrix<byte>(4, 3, 1);

            //方法1

            matr3 = matr1 + matr2;

            //方法2

            //matr3 = matr1.Add(matr2);

            //方法3

            //CvInvoke.Add(matr1, matr2, matr3);

            MatrixBox1.Matrix = matr3;

     }

显示结果如下:

 

图2-11 两个单通道矩阵相加

注意:如果使用方法3,那么必须初始化matr3,否则可以不用初始化,即:

Matrix<byte> matr3

下同。

3、两个多通道矩阵相加

【代码位置:frmChapter2_1】Button11_Click

        //Matrix的加法3:两个多通道矩阵相加

        private void Button11_Click(object sender, EventArgs e)

        {

            Matrix<byte> matr1 = new Matrix<byte>(4, 3, 3);

            matr1.SetValue(new MCvScalar(20, 30, 40));

            Matrix<byte> matr2 = new Matrix<byte>(4, 3, 3);

            matr2.SetValue(new MCvScalar(50, 20, 240));

            Matrix<byte> matr3 = new Matrix<byte>(4, 3, 3);

            //方法1

            matr3 = matr1 + matr2;

            //方法2

            ///matr3 = matr1.Add(matr2);

            //方法3

            //CvInvoke.Add(matr1, matr2, matr3);

            MatrixBox1.Matrix = matr3;

        }

显示结果如下:

 

图2-12 两个多通道矩阵相加

2.2.4.2 减法

1、减一个数值

【代码位置:frmChapter2_1】Button12_Click

        //Matrix的减法1:减去一个固定值

        private void Button12_Click(object sender, EventArgs e)

        {

            byte[,] inputBytes= new byte[,] { { 1, 2, 3 }, { 3, 4, 5 }, { 5, 6, 7 }, { 7, 8, 9 } };

            Matrix<byte> matr1 = new Matrix<byte>(inputBytes);

            Matrix<byte> matr2;

            //方法1

            matr2 = matr1-3;

            //方法2

            //matr2 = matr1.Sub(3);

            MatrixBox1.Matrix = matr2;

        }

显示结果如下:

 

图2-13 Matrix减去一个固定值

还有一个反向减法的方法,读者可以测试将以上代码中的

matr2 = matr1.Sub(3);

替换为:

matr2 = matr1.SubR(30);

进行测试。

2、两个单通道矩阵相减

【代码位置:frmChapter2_1】Button13_Click

        //Matrix的减法2:两个单通道矩阵相减

        private void Button13_Click(object sender, EventArgs e)

        {

            byte[,] inputBytes1 = new byte[,] { { 1, 2, 3 }, { 3, 4, 5 }, { 5, 6, 7 }, { 7, 8, 9 } };

            byte[,] inputBytes2 = new byte[,] { { 3, 4, 5 }, { 5, 6, 7 }, { 7, 8, 9 }, { 9, 10, 21 } };

            Matrix<byte> matr1 = new Matrix<byte>(inputBytes1);

            Matrix<byte> matr2 = new Matrix<byte>(inputBytes2);

            Matrix<byte> matr3 = new Matrix<byte>(4, 3, 1);

            //方法1

            matr3 = matr2 - matr1;

            //方法2

            //matr3 = matr2.Sub(matr1);

            //方法3

            //CvInvoke.Subtract(matr2, matr1, matr3);

            MatrixBox1.Matrix = matr3;

        }

显示结果如下:

 

图2-14 两个单通道矩阵相减

3、两个多通道矩阵相减

【代码位置:frmChapter2_1】Button14_Click

        //Matrix的减法3:两个多通道矩阵相减

        private void Button14_Click(object sender, EventArgs e)

        {

            Matrix<byte> matr1 = new Matrix<byte>(4, 3, 3);

            matr1.SetValue(new MCvScalar(20, 30, 40));

            Matrix<byte> matr2 = new Matrix<byte>(4, 3, 3);

            matr2.SetValue(new MCvScalar(50, 20, 240));

            Matrix<byte> matr3 = new Matrix<byte>(4, 3, 3);

            //方法1

            matr3 = matr2 - matr1;

            //方法2

            //matr3 = matr2.Sub(matr1);

            //方法3

            //CvInvoke.Subtract(matr2, matr1, matr3);

            MatrixBox1.Matrix = matr3;

        }

显示结果如下:

 

图2-15 两个多通道矩阵相减

2.2.4.3 乘法

1、乘以一个数值

【代码位置:frmChapter2_1】Button15_Click

        //Matrix的乘法1:乘以一个固定值

        private void Button15_Click(object sender, EventArgs e)

        {

            byte[,] inputBytes = new byte[,] { { 1, 2, 3 }, { 3, 4, 5 }, { 5, 6, 7 }, { 7, 8, 9 } };

            Matrix<byte> matr1 = new Matrix<byte>(inputBytes);

            Matrix<byte> matr2 ;

            //方法1

            matr2 = matr1 * 3;

            //方法2

            //matr2 = matr1.Mul(3);

            MatrixBox1.Matrix = matr2;

        }

显示结果如下:

 

图2-16 Matrix乘以一个数值

2、两个单通道矩阵相乘

注意:两个矩阵相乘必须满足一定条件

1、第一个Matrix的列数应等于第二个Matrix的行数,生成结果为

列数=第二个Matrix的列数

行数=第一个Matrix的行数

2、数据类型要一致,整数型数据(包括byteintLongInt16Int32Int64等)不能进行乘法运算,浮点型数据(SinglefloatDouble)可以参与运算。

【代码位置:frmChapter2_1】Button16_Click

        //Matrix的乘法2:两个单通道矩阵相乘

        private void Button16_Click(object sender, EventArgs e)

        {

            //42

            Single[,] inputBytes1 = new Single[,] { { 1, 2, 3, 4 }, { 3, 4, 5, 6 } };     

            //34

            Single[,] inputBytes2 = new Single[,]{ { 1, 2, 3 }, { 3, 4, 5 }, { 5, 6, 7 }, { 7, 8, 9 } };

            Matrix<Single> matr1 = new Matrix<Single>(inputBytes1);

            Matrix<Single> matr2 = new Matrix<Single>(inputBytes2);

            //生成32

            Matrix<Single> matr3;

            //方法1

            matr3 = matr1 * matr2;

            //方法2

            //matr3 = matr1.Mul(matr2);

            MatrixBox1.Matrix = matr3;

        }

显示结果如下:

 

图2-17 两个单通道矩阵相乘

3、两个多通道矩阵相乘

两个多通道矩阵似乎不能直接相乘

4、两个矩阵对应元素相乘

这个方法将两个矩阵对应坐标位置的元素相乘,有别于标准的矩阵乘法。

【代码位置:frmChapter2_1】Button17_Click

        //Matrix的乘法3:行列对应元素相乘,不同于普通的矩阵乘法

        private void Button17_Click(object sender, EventArgs e)

        {

            byte[,] inputBytes1 = new byte[,] { { 1, 2, 3 }, { 3, 4, 5 }, { 5, 6, 7 }, { 7, 8, 9 } };

            byte[,] inputBytes2 = new byte[,] { { 3, 4, 5 }, { 5, 6, 7 }, { 7, 8, 9 }, { 9, 10, 11 } };

            Matrix<byte> matr1 = new Matrix<byte>(inputBytes1);

            Matrix<byte> matr2 = new Matrix<byte>(inputBytes2);

            matr1._Mul(matr2);

            MatrixBox1.Matrix = matr1;

        }

显示结果如下:

 

图2-18 两矩阵对应元素相乘

2.2.4.4 除法

【代码位置:frmChapter2_1】Button18_Click

        //Matrix的除法

        private void Button18_Click(object sender, EventArgs e)

        {

            Single[,] inputBytes = new Single[,] { { 1, 2, 3 }, { 3, 4, 5 }, { 5, 6, 7 }, { 7, 8, 9 } };

            Matrix<Single> matr1 = new Matrix<Single>(inputBytes);

            Matrix<Single> matr2;

            matr2 = matr1 / 3;

            MatrixBox1.Matrix = matr2;

        }

显示结果如下:

 

图2-19 Matrix除以一个数值

2.2.4.5 Not运算

【代码位置:frmChapter2_1】Button19_Click

        //矩阵的Not

        private void Button19_Click(object sender, EventArgs e)

        {

            byte[,] inputBytes1 = new byte[,] { { 1, 2, 3 }, { 3, 4, 5 }, { 5, 6, 7 }, { 7, 8, 9 } };

            Matrix<byte> matr1 = new Matrix<byte>(inputBytes1);

            matr1._Not();

            MatrixBox1.Matrix = matr1;

        }

显示结果如下:

 

图2-20 Matrix的Not运算

读者可自行对比byte数据类型和short、int等类型生成的结果。

2.2.5 Matrix拼接

Matrix提供了ConcateHorizontalConcateVertical方法将两个矩阵拼接为一个矩阵。

  1. ConcateHorizontal:水平方向拼接,必须具备相同行数。
  2. ConcateVertical垂直方向拼接,必须具备相同列数

【代码位置:frmChapter2_1】Button20_Click

        //矩阵的水平方向拼接,必须具备相同行数

        private void Button20_Click(object sender, EventArgs e)

        {

            byte[,] inputBytes1 = new byte[,] { { 1, 2, 3 }, { 3, 4, 5 }, { 5, 6, 7 }, { 7, 8, 9 } };

            byte[,] inputBytes2 = new byte[,] { { 3, 4 }, { 5, 6 }, { 7, 8 }, { 9, 10 } };

            Matrix<byte> matr1 = new Matrix<byte>(inputBytes1);

            Matrix<byte> matr2 = new Matrix<byte>(inputBytes2);

            Matrix<byte> matr3;

            matr3 = matr1.ConcateHorizontal(matr2);

            MatrixBox1.Matrix = matr3;

        }

显示结果如下:

 

图2-21 Matrix水平方向拼接

【代码位置:frmChapter2_1】Button21_Click

        //矩阵的垂直方向拼接,必须具备相同列数

        private void Button21_Click(object sender, EventArgs e)

        {

            byte[,] inputBytes1 = new byte[,] { { 1, 2, 3 }, { 3, 4, 5 }, { 5, 6, 7 }, { 7, 8, 9 } };

            byte[,] inputBytes2 = new byte[,] { { 3, 4, 5 }, { 5, 6, 7 }, { 7, 8, 9 } };

            Matrix<byte> matr1 = new Matrix<byte>(inputBytes1);

            Matrix<byte> matr2 = new Matrix<byte>(inputBytes2);

            Matrix<byte> matr3;

            matr3 = matr1.ConcateVertical(matr2);

            MatrixBox1.Matrix = matr3;

        }

显示结果如下:

 

图2-22 Matrix垂直方向拼接

2.2.6 随机矩阵

Matrix类提供了SetRandNormal方法来生成指定大小、类型和均值方差的随机矩阵。该方法声明如下:

public void SetRandNormal(MCvScalar mean, MCvScalar std)

其中参数:

  1. mean:均值,表示随机矩阵的平均值。在正态分布中,均值是分布的中心位置。均值越大,生成的随机矩阵的像素值越偏向于均值。
  2. std:标准差,表示随机矩阵的离散程度。在正态分布中,标准差越大,生成的随机矩阵的像素值越分散。标准差越小,生成的随机矩阵的像素值越接近于均值。

可以通过调整均值和标准差的值来控制生成的随机矩阵的像素值分布。例如,当均值为0,标准差为1时,生成的随机矩阵的像素值符合标准正态分布。当均值为0,标准差为0.5时,生成的随机矩阵的像素值分布更加集中,更接近于均值。

使用SetRandNormal方法生成随机矩阵:

【代码位置:frmChapter2_1】Button22_Click

        //随机矩阵

        private void Button22_Click(object sender, EventArgs e)

        {

            Matrix<byte> matr = new Matrix<byte>(2, 4, 3);

            matr.SetRandNormal(new MCvScalar(12, 33, 123), new MCvScalar(134, 12, 222));

            MatrixBox1.Matrix = matr;

        }

显示结果如下:

 

图2-23 随机矩阵

注意:SetRandNormal方法只能生成正态分布的随机矩阵,不能生成其他分布的随机矩阵。

2.2.7 最大值和最小值

Matrix类提供了MinMax方法获得矩阵内最大值、最小值以及对应的坐标位置。

【代码位置:frmChapter2_1】Button23_Click

        //最大最小值

        private void Button23_Click(object sender, EventArgs e)

        {

            byte[,] inputBytes1 = new byte[,] { { 1, 2, 3 }, { 3, 4, 9 }, { 5, 6, 7 }, { 7, 8, 9 } };

            Matrix<byte> matr1 = new Matrix<byte>(inputBytes1);

            MatrixBox1.Matrix = matr1;

            //最小值

            Double minValue;

            //最大值

            Double maxValue;

            //最小值坐标:有多个最小值时,只返回第一个的坐标

            Point minPoint;

            //最大值坐标:有多个最大值时,只返回第一个的坐标

            Point maxPoint;

            matr1.MinMax(out minValue, out maxValue, out minPoint, out maxPoint);

            TextBox1.Text += minValue + "\r\n";

            TextBox1.Text += maxValue + "\r\n";

            TextBox1.Text += minPoint.X + " " + minPoint.Y + "\r\n";

            TextBox1.Text += maxPoint.X + " " + maxPoint.Y;

        }

显示结果如下:

 

图2-24 最大值最小值以及对应坐标

2.2.8 类型转换

Matrix类提供了Convert方法实现矩阵类型的转换。

【代码位置:frmChapter2_1】Button24_Click

        //类型转换

        private void Button24_Click(object sender, EventArgs e)

        {

            Double[,] inputBytes1 = new Double[,] { { 1.2, 2.2, 3.3 }, { 3.3, 4.4, 5.5 }, { 5.5, 6.6, 7.7 }, { 7.7, 8.8, 9.9 } };

            Matrix<Double> matr1 = new Matrix<Double>(inputBytes1);

            Matrix<byte> matr2 = new Matrix<byte>(matr1.Size);

            //小数转整数会四舍五入

            matr2 = matr1.Convert<byte>();

            MatrixBox1.Matrix = matr2;

        }

显示结果如下:

 

图2-25 从Double转Byte

2.2.9 获得指定范围的子矩阵

Matrix类提供了Convert方法实现获得指定范围的子矩阵。其中参数是一个Rectangle类型,指定了子矩阵的开始位置、列数、行数。

【代码位置:frmChapter2_1】Button25_Click

       //获得子矩阵

        private void Button25_Click(object sender, EventArgs e)

        {

            byte[,] inputBytes1 = new byte[,] { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, { 10, 11, 12 } };

            Matrix<byte> matr1 = new Matrix<byte>(inputBytes1);

            Matrix<byte> matr2 = new Matrix<byte>(3, 2);

            //获得从指定位置(1,1)开始,列数为2,行数为3的子矩阵

            matr2 = matr1.GetSubRect(new Rectangle(1, 1, 2, 3));

            MatrixBox1.Matrix = matr2;

        }

显示结果如下:

 

图2-26 获得指定范围的子矩阵

2.2.10 其他方法

Matrix类还提供了以下常用方法,由于比较简单,不再这里赘述:

  1. Clone:复制Matrix,目标矩阵和源矩阵具有相同的行、列和通道数,元素的值也相同。
  2. CopyBlank:复制Matrix,目标矩阵和源矩阵具有相同的行、列和通道数,但里面元素的值都为0。
  3. GetCol:从源矩阵得到其中一列,并生成新的子矩阵。
  4. GetCols:从源矩阵得到几列的子矩阵。
  5. GetRow:从源矩阵得到其中一行,并生成新的子矩阵。
  6. GetRows:从源矩阵得到几行的子矩阵。
  7. RemoveCols:删除几列的后生成子矩阵。
  8. RemoveRows:删除几行的后生成子矩阵。

相关文章:

EmguCV学习笔记 C# 2.2 Matrix类

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 EmguCV学习笔记目录 Vb.net EmguCV学习笔记目录 C# 笔者的博客网址&#xff1a;VB.Net-CSDN博客 教程相关说明以及如何获得pdf教…...

[Windows CMD] 查看网络连接状态 netstat -na | findstr “TCP“

在 Windows 系统中&#xff0c;我们可以使用 netstat 命令来查看网络连接状态&#xff0c;并使用 findstr 命令来过滤出 TCP 和 UDP 的连接。 查看所有网络连接的状态 netstat -na netstat -na: 显示所有网络连接的状态&#xff0c;-n 表示显示数字地址而非域名&#xff0c;…...

「OC」视图控制器的懒加载策略

「OC」视图控制器的懒加载策略 文章目录 「OC」视图控制器的懒加载策略懒加载懒加载的优点常见的懒加载实现方法使用懒加载的注意事项 控制器的懒加载参考资料 懒加载 懒加载&#xff08;Lazy Loading&#xff09;是一种设计模式&#xff0c;其核心思想是在需要时才进行对象的…...

android studio 中 .gitignore 文件改动后 忽略的文件夹或文件无效

问题原因&#xff1a;已跟踪文件的缓存问题&#xff1a; 如果之前已经跟踪了这些文件&#xff08;即它们已经被 Git 加入到版本控制中&#xff09;&#xff0c;即使你在 .gitignore 文件中添加了忽略规则&#xff0c;Git 仍然会显示这些文件。你需要先从 Git 中移除这些文件&am…...

鸿蒙 next 实现摄像头视频预览编码(一)

鸿蒙 next 即将发布&#xff0c;让我们先喊3遍 遥遥领先~ 遥遥领先~ 遥遥领先~ 作为一门新的系统&#xff0c;本人也是刚入门学习中&#xff0c;如果对于一些理解有问题的&#xff0c;欢迎即使指出哈 首先这里要讲一下&#xff0c;在鸿蒙 next 中&#xff0c;要实现摄像头预览…...

YOLO-V3

一、概述 最大的改进就是网络结构&#xff0c;使其更适合小目标检测特征做的更细致&#xff0c;融入多持续特征图信息来预测不同规格物体先验框更丰富了&#xff0c;3种scale&#xff0c;每种3个规格&#xff0c;一共9种softmax改进&#xff0c;预测多标签任务 先验框&#xf…...

golang提案,内置 Go 错误检查函数

先来狠狠吐个槽 要吐槽 Go1 的 error &#xff0c;那咱得先整明白大家为啥都猛喷它的错误处理做得不咋地。在 Go 语言里头&#xff0c;error 本质上其实就是个 Error 的接口&#xff1a; type error interface {Error() string }实际的应用场景如下&#xff1a; func main()…...

零售业务产品系统应用架构设计(三)

智慧物业依据《住房和城乡建设部等部门关于推动物业服务企业加快发展线上线下生活服务的意见建房〔2020〕99号》,推动物业管理公司广泛运用5G、互联网、物联网、云计算、大数据、区块链和人工智能等技术,建设智慧物业管理服务平台,对接城市信息模型(CIM)和城市运行管理服务…...

【GD32】从零开始学GD32单片机 | PMU电源管理单元+深度睡眠和待机例程(GD32F470ZGT6)

1. 简介 PMU电源管理单元通俗讲就是用来管理MCU的电源域的&#xff0c;它主要有两个功能——电压监测和低功耗管理。在GD32中一共有3个电源域——VDD/VDDA域、1.2V域和备份域。 VDD/VDDA域主要供PMU控制器、ADC、DAC等外设使用&#xff1b;1.2V域就是大部分外设都会使用的电源域…...

公司员工电脑桌面太乱如何解决?桌面管理软件一招解决!

“工欲善其事&#xff0c;必先利其器。” 在数字化管理的时代背景下&#xff0c;选择合适的桌面管理软件就如同为企业网络管理装上了一双慧眼。 员工的电脑桌面往往因为长时间的使用而变得杂乱无章&#xff0c;这不仅影响了工作效率&#xff0c;还可能给企业信息安全带来隐患。…...

leetcode:2119. 反转两次的数字(python3解法)

难度&#xff1a;简单 反转 一个整数意味着倒置它的所有位。 例如&#xff0c;反转 2021 得到 1202 。反转 12300 得到 321 &#xff0c;不保留前导零 。 给你一个整数 num &#xff0c;反转 num 得到 reversed1 &#xff0c;接着反转 reversed1 得到 reversed2 。如果 reverse…...

5.vue中axios封装工程化

vue工程化中axios封装 视频演示地址&#xff1a;https://www.bilibili.com/video/BV121egeQEHg/?vd_source0f4eae2845bd3b24b877e4586ffda69a 通常我们封装需要封装request.js基础的发送请求工具类&#xff0c;再根据业务封装service类&#xff0c;service类是具体业务的接口…...

实验六:动态数码管实验

实验结果图,从右到左0-7,从左到右7-0,来回滚动。 硬件接线图: 具体看图,不说了,前面讲过,自己查资料就可以,资料得慢慢查,熟练就好了,不浪费时间和版面了 main.c代码 #include<reg52.h>typedef unsigned int u16; typedef unsigned char u8;#define SMG P0 …...

《Cloud Native Data Center Networking》(云原生数据中心网络设计)读书笔记 -- 05网络虚拟化

本章帮助网络工程师或架构师回答如下问题&#xff1a; 什么是网络虚拟化?网络虚拟化有哪些用途?网络虚拟化领域内有哪些不同的技术方向?网络虚拟化的控制面有哪些选择?当使用 VXLAN 时如何进行桥接和路由&#xff1f; 什么是网络虚拟化&#xff1f; 网络虚拟化可以让网络…...

奥威BI数据可视化展示:如何充分发挥数据价值

奥威BI数据可视化展示&#xff1a;如何充分发挥数据价值 在大数据时代&#xff0c;数据已成为企业最宝贵的资产之一。然而&#xff0c;仅仅拥有海量数据并不足以带来竞争优势&#xff0c;关键在于如何有效地挖掘、分析和展示这些数据&#xff0c;从而转化为有价值的洞察和决策…...

jenkins工具配置

上一篇&#xff08;https://blog.csdn.net/abc666_666/article/details/141207741&#xff09;文章我们介绍了基于docker安装jenkins的过程&#xff0c;本文将介绍如何配置jenkins的相关全局工具如maven、 jdk以及git等 配置的页面如下&#xff1a; 打开后的页面如下&#xff…...

VAuditDemo文件漏洞

目录 VAuditDemo文件漏洞 一、首页文件包含漏洞 包含图片马 利用伪协议phar:// 构造shell.inc被压缩为shell.zip&#xff0c;然后更改shell.zip 为 shell.jpg上传 二、任意文件读取漏洞 avatar.php updateAvatar.php logCheck.php 任意文件读取漏洞利用 VAuditDemo文件…...

[Meachines] [Medium] poison LFI+日志投毒+VNC权限提升

信息收集 IP AddressOpening Ports10.10.10.84TCP:22,80 $ nmap -p- 10.10.10.84 --min-rate 1000 -sC -sV 22/tcp open ssh OpenSSH 7.2 (FreeBSD 20161230; protocol 2.0) | ssh-hostkey: | 2048 e3:3b:7d:3c:8f:4b:8c:f9:cd:7f:d2:3a:ce:2d:ff:bb (RSA) | 256 …...

EtherCAT运动控制器上位机开发之Python+Qt(三):PDO配置与SDO读写

ZMC408CE控制器硬件介绍 ZMC408CE是正运动推出的一款多轴高性能EtherCAT总线运动控制器&#xff0c;具有EtherCAT、EtherNET、RS232、CAN和U盘等通讯接口&#xff0c;ZMC系列运动控制器可应用于各种需要脱机或联机运行的场合。 ZMC408CE支持8轴运动控制&#xff0c;最多可扩展…...

MyBatis源码系列1(使用JDBC查询数据)

使用原生jdbc进行查询数据步骤. 1、加载驱动2、获取数据库连接3、创建Statement对象4、占位符赋值5、执行脚本6、解析结果7、关闭资源 代码示例 public class T0 {public static void main(String[] args) throws Exception {String sql "SELECT id,name FROM goods WH…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

腾讯云V3签名

想要接入腾讯云的Api&#xff0c;必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口&#xff0c;但总是卡在签名这一步&#xff0c;最后放弃选择SDK&#xff0c;这次终于自己代码实现。 可能腾讯云翻新了接口文档&#xff0c;现在阅读起来&#xff0c;清晰了很多&…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测

uniapp 中配置 配置manifest 文档&#xff1a;manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号&#xff1a;4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

Kafka主题运维全指南:从基础配置到故障处理

#作者&#xff1a;张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1&#xff1a;主题删除失败。常见错误2&#xff1a;__consumer_offsets占用太多的磁盘。 主题日常管理 …...

[特殊字符] 手撸 Redis 互斥锁那些坑

&#x1f4d6; 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作&#xff0c;想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁&#xff0c;也顺便跟 Redisson 的 RLock 机制对比了下&#xff0c;记录一波&#xff0c;别踩我踩过…...

webpack面试题

面试题&#xff1a;webpack介绍和简单使用 一、webpack&#xff08;模块化打包工具&#xff09;1. webpack是把项目当作一个整体&#xff0c;通过给定的一个主文件&#xff0c;webpack将从这个主文件开始找到你项目当中的所有依赖文件&#xff0c;使用loaders来处理它们&#x…...

算法刷题-回溯

今天给大家分享的还是一道关于dfs回溯的问题&#xff0c;对于这类问题大家还是要多刷和总结&#xff0c;总体难度还是偏大。 对于回溯问题有几个关键点&#xff1a; 1.首先对于这类回溯可以节点可以随机选择的问题&#xff0c;要做mian函数中循环调用dfs&#xff08;i&#x…...

深入解析 ReentrantLock:原理、公平锁与非公平锁的较量

ReentrantLock 是 Java 中 java.util.concurrent.locks 包下的一个重要类,用于实现线程同步,支持可重入性,并且可以选择公平锁或非公平锁的实现方式。下面将详细介绍 ReentrantLock 的实现原理以及公平锁和非公平锁的区别。 ReentrantLock 实现原理 基本架构 ReentrantLo…...