Opencv:Mat 和VDMA数据位数以及VGA数据位数的关系

September 8, 2016
作者:dengshuai_super
出处:http://blog.csdn.net/dengshuai_super/article/details/52468505
声明:转载请注明作者及出处。


1.Mat的各项属性


A.total() //元素的个数
A.elemSize() //元素的大小,如果是8UC3的话,返回3*sizeof(uchar)
A.elemSize1() //如果是8UC3的话,返回sizeof(uchar)
A.type() //元素的数据类型
A.depth()//元素的位数
A.channels()//矩阵的通道数
A.step1() //矩阵的每一行元素的个数,A.step/A.elemSize1
A.size() //矩阵的尺寸
//注意以下是成员变量不是成员函数
A.step //矩阵的一行的字节数
A.rows //矩阵的行数,即高
A.cols //矩阵的列数,即宽

A.isContinuous(); // 返回bool类型表示是否连续存储
data  uchar型的指针。Mat类分为了两个部分:矩阵头和指向矩阵数据部分的指针,data就是指向矩阵数据的指针。

dims 矩阵的维度,例如5*6矩阵是二维矩阵,则dims=2,三维矩阵dims=3.

rows  矩阵的行数

cols   矩阵的列数

size 矩阵的大小,size(cols,rows),如果矩阵的维数大于2,则是size(-1,-1)

channels 矩阵元素拥有的通道数,例如常见的彩色图像,每一个像素由RGB三部分组成,则channels = 3
下面的几个属性是和Mat中元素的数据类型相关的。

type 
表示了矩阵中元素的类型以及矩阵的通道个数,它是一系列的预定义的常量,其命名规则为CV_(位数)+(数据类型)+(通道数)。具体的有以下值: 
CV_8UC1 CV_8UC2 CV_8UC3 CV8UC4
CV_8SC1 CV_8SC2 CV_8SC3 CV_8SC4
CV_16UC1 CV_16UC2 CV_16UC3 CV_16UC4
CV_16SC1 CV_16SC2 CV_16SC3 CV_16SC4
CV_32SC1 CV_32SC2 CV_32SC3 CV_32SC4
CV_32FC1 CV_32FC2 CV_32FC3 CV_32FC4
CV_64FC1 CV_64FC2 CV_64FC3 CV_64FC4
这里U(unsigned integer)表示的是无符号整数,S(signed integer)是有符号整数,F(float)是浮点数。 
例如:CV_16UC2,表示的是元素类型是一个16位的无符号整数,通道为2. 
C1C2C3C4则表示通道是1,2,3,4 
type一般是在创建Mat对象时设定,如果要取得Mat的元素类型,则无需使用type,使用下面的depth

depth 
矩阵中元素的一个通道的数据类型,这个值和type是相关的。例如 typeCV_16SC2,一个2通道的16位的有符号整数。那么,depth则是CV_16S。depth也是一系列的预定义值, type的预定义值去掉通道信息就是depth值: 
CV_8U CV_8S CV_16U CV_16S CV_32S CV_32F CV_64F

elemSize 
矩阵一个元素占用的字节数,例如:typeCV_16SC3,那么elemSize = 3 * 16 / 8 = 6 bytes

elemSize1 
矩阵元素一个通道占用的字节数,例如:typeCV_16CS3,那么elemSize1 = 16  / 8 = 2 bytes = elemSize / channels
一般的图像文件格式使用的是 Unsigned 8bits吧,CvMat矩阵对应的参数类型就是
CV_8UC1,CV_8UC2,CV_8UC3。
(最后的123表示通道数,譬如RGB3通道就用CV_8UC3)

而float32位的,对应CvMat数据结构参数就是:CV_32FC1,CV_32FC2,CV_32FC3...
double64bits,对应CvMat数据结构参数:CV_64FC1,CV_64FC2,CV_64FC3等。

变换这种矩阵单位类型,Mat里有一个函数convertTo可以办到:
C++:void Mat::convertTo(OutputArray m, int rtype, double alpha=1, double beta=0 )
rtype 参数就是上述单位类型。

OpenCV中存储像素的方法,如下,灰度图(单通道)存储按行列存储,

这里写图片描述

三通道RGB存储方式如下,每列含有三个通道,

这里写图片描述

为了加快访问的速度,openCV往往会在内存中将像素数据连续地存储成一行,isContinus()函数的作用就是用于判断是否连续存储成一行。存储成一行有什么好处呢?给定这行的头指针p,则只要使用p++操作就能逐个访问数据。

因此当判断存放在一行的时候,可以通过数据指针++很容易遍历图像像素:

long nRows = M.rows * M.channels();  // channels()也是Mat中一个常用的函数,用于获取通道数(RGB=3,灰度=1)
long nCols = M.cols;
uchar *p = M.data;  // 数据指针
if(M.isContinuous())
{
    nCols *= nRows;
    for (long i=0; i < nCols; i++) {
        *p++ = ...; // 像素赋值或读取操作
    }       
}

2.VDMA、VGA位数设置

这里写图片描述

这里写图片描述

这里写图片描述


3.VDMA位数与Mat的关系

这里写图片描述

-- OV7670 : Expand 16-bit RGB (5:6:5) to 32-bit RGBA (8:8:8:8)
m_axis_tdata <="11111111"  & d_latch(4 downto 0) & d_latch(0) & d_latch(0) & d_latch(0) & d_latch(10 downto 5) & d_latch(5) & d_latch(5) & d_latch(15 downto 11) & d_latch(11) & d_latch(11) & d_latch(11);

--VGA OUTPUT :  24-bit RGB (8:8:8) to 16-bit RGB (5:6:5)
rgb_reg[4:0] <= s00_axis_vga_tdata[7:3];//RED Channel
rgb_reg[10:5] <= s00_axis_vga_tdata[15:10]; //GREEN Channel
rgb_reg[15:11] <= s00_axis_vga_tdata[23:19]; //BLUE Channel

--create a new 640x480 image
Mat dst_rgb(480, 640, CV_8UC4);//RGBA4通道
IplImage dst = dst_rgb;
memcpy((uchar *)dst.imageData,(uchar *)vdmaflVirtualAddressout , 640 * 480 * 4);
imwrite("output_640x480.bmp", dst_rgb); 

--Mat_<uchar>对应的是CV_8U,Mat_<uchar>对应的是CV_8U,Mat_<char>对应的是CV_8S,Mat_<int>对应的是CV_32S,Mat_<float>对应的是CV_32F,Mat_<double>对应的是CV_64F,对应的数据深度如下:

• CV_8U - 8-bit unsigned integers ( 0..255 )

• CV_8S - 8-bit signed integers ( -128..127 )

• CV_16U - 16-bit unsigned integers ( 0..65535 )

• CV_16S - 16-bit signed integers ( -32768..32767 )

• CV_32S - 32-bit signed integers ( -2147483648..2147483647 )

• CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )

• CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章