您的位置:首页 > 运维架构

opencv由Mat相乘想到的几个问题

2015-11-03 16:21 495 查看
最近在做一个实验,需要对X∗XTX*X^T求取特征值,所以需要进行矩阵相乘操作。

我的Mat是以灰度方式读取图片得来。

数据获取的代码如下:

vector<Mat> images;
vector<int> labels;
string imgPath;

for (int i = 1; i <= 15; i++)
for (int j = 1; j <= 8; j++)
{
if (i<10)
imgPath = format("D:/database/orl/orl_00%d_00%d.bmp", i, j);
else
imgPath = format("D:/database/orl/orl_0%d_00%d.bmp", i, j);
cout << imgPath << endl;
Mat img = imread(imgPath.c_str(), CV_LOAD_IMAGE_GRAYSCALE);
Mat resizedImg;
resize(img, resizedImg, Size(30,30));

Mat imgNorm;
cv::normalize(resizedImg, imgNorm, 0, 255, NORM_MINMAX, CV_8UC1);
images.push_back(imgNorm);
labels.push_back(i);
}
int featureDim = images[0].cols*images[0].rows;
Mat pcaMat(images.size(), featureDim, CV_8UC1);
for (int i = 0; i < images.size(); i++)
{
memcpy((uchar*)pcaMat.data + i*featureDim, (uchar*)images[i].data, sizeof(uchar)*featureDim);
}


当我进行如下操作的时候报错了!

Mat pcaM = pcaMat*pcaMat.t();(pcaMat.t()为pcaMat的转置。)



从错误可以看出,A*B矩阵相乘要求

A,B两矩阵类型要相同

矩阵的类型要是图中所示的4种类型

于是我产生了两个问题:

Mat的type有哪些呢?我如何判断我的Mat的类型呢?这个问题主要是针对转置运算,因为我想知道转置之后矩阵的类型是否进行了变换。

如何对矩阵的数据类型进行转换呢?我想从8UC1转换成上述类型,该怎么做呢?这样转换会出现什么问题吗?

Mat的type

Mat的所有类型可以参考这里

~~~

uchar a[8] = {1, 2, 3, 4, 5, 6, 7, 8};

Mat mat1(2,4, CV_8UC1);

memcpy(mat1.data, a, sizeof(uchar)*8);

cout << "type " << mat1.type() << endl;
cout << "depth " <<mat1.depth() << endl;
cout << "channels " << mat1.channels() << endl;


ConvertTo的使用

读取图片是8UC1,转化成64FC1会出现什么问题呢?

如下所示

Mat img = imread("D:/database/orl/orl_001_001.bmp", CV_LOAD_IMAGE_GRAYSCALE);
imshow("beforConvert", img);
img.convertTo(img, CV_64FC1);
imshow("afterConvert", img);
waitKey(0);


结果为:



为什么会这样呢?

因为颜色空间在整数上是0~255,在浮点数上则是在0~1之间,也就是说img转换成CV_64FC1之后,我们显示图片,只会显示0~1的值,而那些大于1的值则直接就不显示了,所以变成了白色。

来输出一下转换前后mat的第一行的值,值是相同的:



convertTo函数它的使用具体是怎样的呢?

opencv的doc可以在doc这里根据版本具体查看。

我看的是2.4.10版本的,里边对这个函数的描述如下:

void ocl::oclMat::convertTo(oclMat& m, int rtype, double alpha=1, double beta=0) const
/*
Parameters:
m – the destination matrix. If it does not have a proper size or type before the operation, it will be reallocated.
rtype – the desired destination matrix type, or rather, the depth (since the number of channels will be the same with the source one). If rtype is negative, the destination matrix will have the same type as the source.
alpha – optional scale factor.
beta – optional delta added to the scaled values.
*/


m就是目的矩阵,rtype就是数据转换后的类型,也就是CV_16SC1之类的。

至于alpha,beta,我用α,β\alpha,\beta来表示

它们的作用是这样的,比如对于m中的一个像素m(i,j)=m(i,j)∗α+βm(i,j) = m(i,j)*\alpha+\beta。

所以上面图像转换出的问题就在于使用默认的缩放参数等价于没有对数值做变化,只是变了数据的类型,就像是1,从uchar的1变成了double的1。

现在我修改一下参数,注意是1/255.0这样才是double值,如果写出1/255其实就是0了!:

img.convertTo(img, CV_64FC1, 1/255.0);


现在就可以顺利地显示啦



Mat相乘

两个Mat相乘挺简单的,只需要写成A*B就可以了。

可是*对矩阵的数据类型进行了限制,所以要事先转化成32F或64F来计算。

下面进行一段演示:

int a[8] = {1, 2, 3, 4, 5, 6, 7, 8};
int b[4] = {1, 2, 3, 4};
Mat mat1(2,4, CV_32SC1);
Mat mat2(4,1, CV_32SC1);
memcpy(mat1.data, a, sizeof(int)*8);
memcpy(mat2.data, b, sizeof(int)*4);
mat1.convertTo(mat1, CV_64FC1);
mat2.convertTo(mat2, CV_64FC1);

Mat mat3 = mat1*mat2;
cout << "Mat1\n " << mat1 << endl;
cout << "Mat2\n " << mat2 << endl;
cout << "Mat3\n " << mat3 << endl;


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: