我已经加载了一个图像(cv :: mat),并且所有像素似乎都存储为无符号字符。我需要将它们转换为32位浮点类型,以便我可以执行一些数学运算。 我试过了:
Mat M;
M = imread("path\\to\\image", CV_LOAD_IMAGE_COLOR);
cvtColor( M, M, CV_RGB2GRAY);
M.convertTo(M,CV_32F);
以及如此初始化:
Mat test = Mat(100,100,CV_32F);
但他们似乎没有做任何事情,数据仍然表示为无符号字符。如何转换cv :: mat数据表示?
答案 0 :(得分:3)
图像数据始终由unsigned char* Mat::data
指向,即使它具有非uchar格式。您的转换是正常的,您需要注意的是,要访问float
数据,您需要从data
指针强制转换。一些例子:
1)访问第i个数据行
float * row_i = M.ptr<float>(i);
2)访问(i,j)
元素:
float x_ij = M.at<float>(i,j)
或(更有效率):
float x_ij = (M.ptr<float>(i))[j]
BTW ,您应该在BGR2GRAY
中使用RGB2GRAY
代替cvtColor
:
cvtColor( M, M, CV_BGR2GRAY);
答案 1 :(得分:1)
我用来在C ++中加载灰度图像的代码是:
cv::Mat matInput;
{
cv::Mat matTmp = cv::imread("path\\to\\image", CV_LOAD_IMAGE_GRAYSCALE);
matTmp.convertTo(matInput, CV_32FC1, 1.0/0xff);
}
将图像加载为灰度,然后将结果转换为标准化在0.0和1.0之间的32位浮点格式(因为图像通常存储的值介于0和0xff之间)。如果您正在使用浮点图像,您可能希望将值标准化为0.0到1.0之间,convertTo本身只是更改类型。在将图像写回文件之前,请记住乘以0xff,否则您可能只会得到一张黑色图像。
我添加了额外的括号,以确保转换完成后临时矩阵超出范围,从而释放内存。如果您使用的是x64机器,我还建议使用double(CV_64FC1),我发现计算速度要快得多。
例如,您还可以执行以下操作:
double Fitness(cv::Mat& mat1, cv::Mat& mat2)
{
cv::Mat matImg1, matImg2;
if (mat1.type() == CV_8UC1) mat1.convertTo(matImg1, CV_64FC1, 1.0/0xff);
else matImg1 = mat1;
if (mat2.type() == CV_8UC1) mat2.convertTo(matImg2, CV_64FC1, 1.0/0xff);
else matImg2 = mat2;
// Select the region of IMG2 the same size as IMG1
cv::Mat matReg2(matImg2, cv::Rect(cv::Point(0, 0), matImg1.size()));
// Compute the RMS value
cv::pow(matImg1 - matReg2, 2.0, matImg1);
return pow(cv::mean(matImg1)[0], 0.5);
}
或者只是访问单个值(假设CV_64FC1):
matInput.at<double>(0, 0) = 0.5;
std::cout << matInput.at<double>(1, 2);