OpenCV之矩阵维度和通道详解

版权声明:本文为博主原创文章,未经博主允许不得转载,如果喜欢欢迎收藏。 https://blog.csdn.net/MRZHUGH/article/details/83538805

今天发现对OpenCV的矩阵维度和通道还不太理解,所以有必要花点时间整理一下这两个点。

OpenCV中图像的通道可以是1、2、3和4。其中常见的是1通道和3通道,2通道和4通道不常见。

  • 1通道的是灰度图
  • 2通道的图像是RGB555和RGB565。2通道在程序处理中会用到,如傅里叶变换,可能会用到,一个通道为实数,一个通道为虚数,主要是编程方便。RGB是16位的,2个字节(5+6+5),第一个字节的前5位是R,后三位+第二个字节是G,第二个字节后5位是B,可见对原图进行压缩了。
  • 3通道的是彩色图像,比如RGB图像
  • 4通道的图像是RGBA,是RGB加上一个A通道,也叫alpha通道,表示透明度。PNG图像是一种典型的4通道图像。alpha通道可以赋值0到1,或者0到255,表示透明到不透明。

维度:就是我们平常所说的坐标轴。二维:x,y。。三维:x,y,z。。

通道:就是某一坐标表示的数组有多少个。比如单通道:P[0][0]=10,在坐标(0,0)处只表示一个数组。同理双通道:P[0][0]={10,15},那么就是双通道。我们常用的RBG(255,255,255)就是三通道。

float P[18]={10,15,20,25,30,35,

             40,45,50,55,60,65,

             70,75,80,85,90,95};

//上面是3行6列的数组。

3行6列的数组:通道1指的是:每一个坐标都只有一个值。

                       通道2指的是:每一个坐标上都有两个值。且这两个值是由矩阵的相邻两个数据组成的。

                       通道3指的是:每一个座标上都由矩阵中的三个相邻的数据组成的。例如彩色图像的RGB格式,每一                                             个像素点上都有三个数据,分别代表Red Green Bluen  红绿蓝三种颜色的深浅度 。

那么在opencv下如何表示单通道还是多通道?

cvInitMatHeader(&mat,3,6,CV_32FC1,P); //P就是上面的那个数组

此函数的第四参数:CV_32FC1--------32表示32位,FC表示通道,1表示单通道(若2表示双通道)。

常用的函数如下:

  • cvGet*D,cvSet*D
  • cvGetReal1D,cvGetReal2D,cvGetReal3D,cvGetRealND
  • cvGet1D,cvGet2D,cvGet3D,cvGetND
  • cvSet*D 也有相应的函数系列
  • 这些函数的缺点是:效率低
  • 具有Real的函数只用在单通道。

  • cvGet1D,cvGet2D等。----2D表示维度。只用x、y坐标轴使用cvGet2D;有x、y、z坐标轴就使用cvGet3D。

实例:

单通道:下例用cvGetReal2D进行数据访问:

#include <highgui.h>

int main()
{
	float P[18] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 };

	CvMat mat;
	cvInitMatHeader(&mat, 3, 6, CV_32FC1, P);
	for (int y = 0; y<mat.rows; ++y)
	{
		for (int x = 0; x<mat.cols; ++x)
		{
			float Value = cvGetReal2D(&mat, y, x);
			printf("%f  ", Value);
		}
		printf("\n");
	}
	system("pause");
	return 0;
}

  

多通道:某一坐标的值都由多个数值组成,如颜色图像RGB;下例用cvGet2D对数据进行访问:

#include <highgui.h>

int main()
{
	float P[18] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 };

	CvMat mat;
	cvInitMatHeader(&mat, 3, 3, CV_32FC2, P);

	for (int y = 0; y < mat.rows; y++)
	{
		for (int x = 0; x < mat.cols; x++)
		{
			CvScalar value = cvGet2D(&mat, y, x);
			printf("(%5.2f, %5.2f)   ", value.val[0], value.val[1]);
		}
		printf("\n");
	}
	system("pause");
	return 0;
}

  

补充:用cvGet1D可以访问数据,但是这种方式太慢,因此可以观察数据在内存中的位置而直接访问内存即可:

#include <highgui.h>

int main()
{
	float P[18] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 };

	CvMat mat;
	cvInitMatHeader(&mat, 3, 3, CV_32FC2, P);

	for (int y = 0; y < mat.rows; y++)
	{
		for (int x = 0; x < mat.cols; x++)
		{
			float * pData = (float*)(mat.data.ptr + mat.step * x + y * sizeof(CV_32FC2));
			printf("(%5.2f, %5.2f)   ", pData[0], pData[1]);
		}
		printf("\n");
	}
	getchar();
	return 0;
}

  

至此,对OpenCV矩阵的维度和通道,尤其是通道有了更加深刻的理解,原来通道类比数组还是很好理解的,对其数据访问也算是入门了。

革命尚未成功,同志仍需努力。

猜你喜欢

转载自blog.csdn.net/MRZHUGH/article/details/83538805