在OpenCV C ++中转换数据表示

时间:2014-04-30 07:55:17

标签: c++ opencv

我已经加载了一个图像(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数据表示?

2 个答案:

答案 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);