opencv深入学习(3)-- Mat格式的几个参数以及几种元素存取方法的讨论

来源:互联网 发布:黎明杀机移动速度数据 编辑:程序博客网 时间:2024/06/04 18:09
#include "stdafx.h"#include <core.hpp>#include <highgui.hpp>#include <iostream>#include <fstream>using namespace cv;using namespace std;#pragma comment(lib,"opencv_core220d.lib")#pragma comment(lib,"opencv_highgui220d.lib")int _tmain(int argc, _TCHAR* argv[]){ofstream outFile;outFile.open("pixel_32f.txt");char name[100] = "d://picture//lena.jpg";namedWindow("show", CV_WINDOW_AUTOSIZE);{Mat pnm = imread(name, -1);if (pnm.empty()){cout<<"read error"<<endl;return -1;}Mat temp;pnm.convertTo(temp, CV_32FC3);vector<Mat> vec;split(temp, vec);cout<<"pnm.channels = "<<pnm.channels()<<endl;cout<<"pnm.depth = "<<pnm.depth()<<endl;cout<<"pnm.dims = "<<pnm.dims<<endl;cout<<"pnm.elemsize = "<<pnm.elemSize()<<endl;cout<<"pnm.elemsize1 = "<<pnm.elemSize1()<<endl;for (int k=0; k<pnm.dims;++k){cout<<"pnm.step = "<<pnm.step[k]<<endl;}cout<<"pnm.step1 = "<<pnm.step1()<<endl;cout<<"pnm.type = "<<pnm.type()<<endl;cout<<"pnm.total = "<<pnm.total()<<endl;cout<<"pnm.rows*cols = "<<pnm.cols*pnm.rows<<endl;cout<<"pnm.rows = "<<pnm.rows<<endl;cout<<"pnm.cols = "<<pnm.cols<<endl;cout<<endl;cout<<"temp.channels = "<<temp.channels()<<endl;cout<<"temp.depth = "<<temp.depth()<<endl;cout<<"temp.dims = "<<temp.dims<<endl;cout<<"temp.elemsize = "<<temp.elemSize()<<endl;cout<<"temp.elemsize1 = "<<temp.elemSize1()<<endl;for (int m=0; m<temp.dims; ++m){cout<<"temp.step = "<<temp.step[m]<<endl;}cout<<"temp.step1 = "<<temp.step1()<<endl;cout<<"temp.type = "<<temp.type()<<endl;cout<<"temp.total = "<<temp.total()<<endl;cout<<"temp.rows = "<<temp.rows<<endl;cout<<"temp.cols = "<<temp.cols<<endl;cout<<endl;int i,j;////////////////////////======section1======//////////////////////////int64 beg = cvGetTickCount();vector<Mat> spl;split(temp, spl);for (i=0; i<temp.rows; ++i){float *pt = spl[0].ptr<float>(i);for (j=0; j<temp.cols; ++j){float mm = pt[j];//if(i<6)//outFile<<mm<<",";mm = mm/(float)20.6;}//outFile<<endl;}merge(spl, temp);int64 second = cvGetTickCount();cout<<(second-beg)/cvGetTickFrequency()<<endl;outFile<<(second-beg)/cvGetTickFrequency()<<endl;//////////////////////////=========section2=========////////////////////////////////int64 secbeg = cvGetTickCount();for (i=0; i<temp.rows; ++i){for (j=0; j<temp.cols; ++j){float *mm = &(temp.ptr<float>(i)[3*j]);//if(i<6)//outFile<<*mm<<",";*mm = *mm/(float)20.6;}//outFile<<endl;}int64 third = cvGetTickCount();cout<<(third-secbeg)/cvGetTickFrequency()<<endl;outFile<<(third-secbeg)/cvGetTickFrequency()<<endl;//////////////////////////============section3==========//////////////////////////////int64 thridbeg = cvGetTickCount();int col=temp.cols, row = temp.rows;if (temp.isContinuous()){col*=row;row =1;}for (i=0; i<row; ++i){const float *pt = temp.ptr<float>(i);for (j=0; j<col;++j){float mm=pt[3*j];//outFile<<mm<<",";mm = mm/(float)20.6;}//outFile<<endl;}int64 four = cvGetTickCount();cout<<(four-thridbeg)/cvGetTickFrequency()<<endl;outFile<<(four-thridbeg)/cvGetTickFrequency()<<endl;///////////////////////////===========section4===============/////////////////////////////////int64 fourbeg = cvGetTickCount();int step0=temp.step[0],step1=temp.step[1];for (i=0; i<temp.rows; ++i){for (j=0; j<temp.cols; ++j){float *pix = (float *)(temp.data+i*step0+j*step1);//if(i<6)//outFile<<*pix<<",";*pix = *pix/(float)20.6;}//outFile<<endl;}int64 fifth = cvGetTickCount();cout<<(fifth-fourbeg)/cvGetTickFrequency()<<endl;outFile<<(fifth-fourbeg)/cvGetTickFrequency()<<endl;//////////////////////////============section5==========//////////////////////////////int64 fifthbeg = cvGetTickCount();int step00=temp.step[0],step01=temp.step[1];int col2=temp.cols, row2 = temp.rows;if (temp.isContinuous()){col2*=row2;row2 =1;}for (i=0; i<row2; ++i){for (j=0; j<col2;++j){float *mm= (float *)(temp.data+i*step00+j*step01);//outFile<<mm<<",";*mm = *mm/(float)20.6;}//outFile<<endl;}int64 sixth = cvGetTickCount();cout<<(sixth-fifthbeg)/cvGetTickFrequency()<<endl;outFile<<(sixth-fifthbeg)/cvGetTickFrequency()<<endl;outFile.close();imshow("show", pnm);waitKey(0);}return 0;}


 

下面是某次的运行结果以及对于Mat的几个参数的分析。
//////////////////////////////////////////////////////////////////////////////////
pnm.channels = 3 ------------------通道数。
pnm.depth = 0 ------------------矩阵元素的基础元素类型,CV_8U(uchar), CV_32F(float)...等.
pnm.dims = 2 ------------------矩阵的维数,图像一般为2维的;
pnm.elemsize = 3 ------------------矩阵每个元素的大小(所占字节数)=channel×sizeof(elemsize1);
pnm.elemsize1 = 1 ------------------矩阵每个元素的基础元素大小=sizeof(uchar, float......等);
pnm.step = 1536 [0]---------------矩阵每行所占的字节数,包括用于字节对齐的字节,如果不用补齐字节则=cols*elemsize;
pnm.step = 3 [1]---------------矩阵中每个元素所占字节数,对于2维矩阵=elemsize。
pnm.step1 = 1536 ------------------return normalized step; =step[0]/elemsize1,即每行的步长,it can be useful for fast access to arbitrary matrix element;
pnm.type = 16 ------------------返回flags中表示每个元素类型,即CV_8UC3,CV_32FC1等表示的整数
pnm.total = 262144 ------------------=rows*cols
pnm.rows*cols = 262144
pnm.rows = 512
pnm.cols = 512

temp.channels = 3
temp.depth = 5
temp.dims = 2
temp.elemsize = 12
temp.elemsize1 = 4
temp.step = 6144
temp.step = 12
temp.step1 = 1536
temp.type = 21
temp.total = 262144
temp.rows = 512
temp.cols = 512

37098.3
34995
4189.36
6048.81
5776.15
//////////////////////////////////////////////////////////////////////////////////////////////////
最后的几个运行结果每次是不一样的,但是基本可以肯定的是前两种是差不多的,第三种最少,第四和第五不相上下,但是第三种的缺点是丢失了原始的行列信息,对于不计较元素位置的处理来说是首选,正如opencv2.2的手册中所说,在存储结构中没有gap,计算不是太复杂时,可以提升10%-20%的效率。而对于多通道下的需要处理行列信息的计算来说,个人偏好第四种,也就是opencv1.x的方式,直接使用原始指针操作,习惯上用着方便。第一二种方法是C++API的新的获取方式,当然还有使用迭代器方式的存取等,详细的见手册或者cheet_sheet中提供的方法。
当然上面只是对于元素类型是CV_32FC3的进行的测试,对于基础的CV_8UC1/3没有测试。
------后记-------
对于第四种费了很长时间才搞明白,开始的时候没弄清楚,取出的数据不是不对就是直接出现访问异常。对于新的Mat结构所有的有效像素数据都是存储在uchar* data中,所以取用时需要自己显式的转换类型,开始时没有意识到在内存中存储的是uchar类型,直接使用了*(temp.data+i*step0+j*step1)来获取数据,结果总是取到错误的数据,后来意识到存储的是float数据,需要转换,就直接在前面加了(float)结果还是不行,最后仔细分析之后终于发现问题了====*(temp.data+i*step0+j*step1)是按照uchar将数据取出,转换为uchar型的数据,如果在前面加上float转换,只是将uchar提升为了float而不是取出的是float,原来如此,将其改为(float *)(temp.data+i*step0+j*step1),也就是按照float的形式取出,也就是一次取出4个字节作为一个数据,这样就可以了。