标准化 0 到 1 之间的像素值

Posted

技术标签:

【中文标题】标准化 0 到 1 之间的像素值【英文标题】:Normalize pixel values between 0 and 1 【发布时间】:2013-06-27 14:31:33 【问题描述】:

我希望使用 C++/OpenCV 将图像的像素值标准化为 [0..1] 范围。但是,当我使用 image *= 1./255 或 normalize 函数进行归一化时,像素值会向下舍入为零。我尝试将图像设置为输入CV_32FC3

下面是我的代码:

  Mat image;
  image = imread(imageLoc, CV_LOAD_IMAGE_COLOR | CV_LOAD_IMAGE_ANYDEPTH);

  Mat tempImage;

  // (didn't work) tempImage *= 1./255;

  image.convertTo(tempImage, CV_32F, 3);
  normalize(image, tempImage, 0, 1, CV_MINMAX);

  int r = 100;
  int c = 150;

  uchar* ptr = (uchar*)(tempImage.data + r * tempImage.step);
  Vec3f tempVals;
  tempVals.val[0] =  ptr[3*c+1];
  tempVals.val[1] =  ptr[3*c+2];
  tempVals.val[2] =  ptr[3*c+3];
  cout<<" temp image - "<< tempVals << endl;

  uchar* ptr2 = (uchar*)(image.data + r * image.step);
  Vec3f imVals;
  imVals.val[0] =  ptr2[3*c+1];
  imVals.val[1] =  ptr2[3*c+2];
  imVals.val[2] =  ptr2[3*c+3];
  cout<<" image - "<< imVals << endl;

这会在控制台中产生以下输出:

temp image - [0, 0, 0]
image - [90, 78, 60]

【问题讨论】:

【参考方案1】:

你可以让convertTo()为你做标准化:

image.convertTo(tempImage, CV_32FC3, 1.f/255);

您将3 传递给convertTo(),大概是作为通道计数,但那不是the correct signature。

【讨论】:

这也会产生一个整数输出 你为什么这么说?请尝试使用cv::Mat::at&lt;float&gt;(row,col) 方法访问像素。 我正在向控制台输出一些像素值,以尝试验证转换是否符合我的预期。使用 at(r,c) 访问值的方法给了我预期的结果。谢谢。 255.5 是错字吗? 是的 - 已修复。改为1.f/255【参考方案2】:

我使用了normalize 函数并且它有效(Java):

Core.normalize(src,dst,0.0,1.0,Core.NORM_MINMAX,CvType.CV_32FC1);

您应该为目标图像使用 32F 深度。我相信这样做的原因是,由于您需要获取十进制值,因此您应该使用非整数 OpenCV 数据类型。根据这个table,浮点类型对应于32F深度。我选择通道数为 1 并且它起作用了; CV_32FC1

还请记住,它不太可能在图像中发现任何视觉差异。 最后,由于您的图像中可能有数千个像素,您的控制台可能看起来只打印零。但是由于数据量很大,请尝试使用CTRL+F 看看发生了什么。希望这会有所帮助。

【讨论】:

请edit你的答案解释为什么“你应该使用CV_32FC1类型”。 为什么不使用 float64?

以上是关于标准化 0 到 1 之间的像素值的主要内容,如果未能解决你的问题,请参考以下文章

如何标准化图像中的像素值并保存

OpenCV:标准化图像的像素值

numpy.ndarray 如何标准化?

数据标准化

标准化从 0 - 1 的任何数字的函数

如何标准化 0 和 1 之间的 Pearson 相关性?