【问题标题】:accessing image pixels as float array将图像像素作为浮点数组访问
【发布时间】:2013-01-17 00:28:42
【问题描述】:

我想在 opencv 中以浮点数组的形式访问图像像素。我做了以下事情:

Mat input = imread("Lena.jpg",CV_LOAD_IMAGE_GRAYSCALE);
int height = input.rows;
int width = input.cols;

Mat out;
input.convertTo(input, CV_32FC1);
copyMakeBorder(input, input, 3, 3, 3, 3, 0);

out = Mat(height, width, input.type());

float *outdata = (float*)out.data;
float *indata = (float*)input.data;

for(int j = 0; j < height; j++){
    for(int i =0; i < width; i++){
        outdata[j*width + i] = indata[(j* width + i)];
    }
}


normalize(out, out,0,255,NORM_MINMAX,CV_8UC1);

imshow("output", out);
waitKey();

这应该在“out”中返回原始图像,但是,我得到了一些奇怪的图像。任何人都可以解释代码有什么问题。我想我需要使用一些步长(widthStep)。谢谢。

【问题讨论】:

  • 假设数组代表二维数据,如何通过例如索引它们outdata[j*width + i]?
  • 试过了。没有得到正确的结果:(
  • 更多代码,请:outinput的类型是什么?
  • 二维图像。 CV_32FC1。垫子。
  • 您想将图像转换为包含浮点数据类型元素的二维数组吗?

标签: c++ image-processing opencv


【解决方案1】:

一行

    copyMakeBorder(input, input, 3, 3, 3, 3, 0);

改变输入的尺寸,它给图像增加了 6 行和 6 列。这意味着当您定义 out 并尝试遍历输入值时,您的 height 和 width 变量持有错误的值。

如果您将顺序更改为

copyMakeBorder(input, input, 3, 3, 3, 3, 0);

int height = input.rows;
int width = input.cols;

它应该可以正常工作。

【讨论】:

    【解决方案2】:

    一些想法:


    outdata[j*width + i] 这样的东西是这类事情的更标准模式。


    根据the opencv documentation,有一个模板化的Mat::at(int y, int x) 方法允许您访问矩阵的各个元素。

    float f = input.at<float>(0, 0); 
    

    注意,这要求您的基础矩阵类型为 float - 它不会为您进行转换。


    或者,您可以逐行访问数据,如本例所示,该示例将 M 类型为 double 的矩阵的正元素相加:

    double sum=0;
    for(int i = 0; i < M.rows; i++)
    {
        const double* Mi = M.ptr<double>(i);
        for(int j = 0; j < M.cols; j++)
            sum += std::max(Mi[j], 0.);
    }
    

    如果这些都不起作用,我建议创建一个具有已知值的小矩阵(例如,具有 1 个黑色像素和 3 个白色像素的 2x2 矩阵)并使用它来帮助调试您的代码。

    【讨论】:

    • 嗨,我已经用完整的代码更新了帖子。我知道 outdata[j*width + i] 是一种标准方式,但是,我不知道为什么这不起作用。
    • float f = input.at(0, 0);工作正常,但这不是我需要的... :-/
    • 如果at 工作,它是否像在rotating_image 的答案中那样循环工作?如果是这样,为什么这不是您所需要的?
    【解决方案3】:

    要真正弄清楚问题所在,请想象一张 16 x 16 的图像。现在想想线性表示中的像素数 17。

    17 是质数。如果行或列宽为 16,则没有j*i 将在像素 17 处索引您的源图像。因此,17、19、23 等元素将未初始化或最多为 0,从而导致“奇怪”输出.

    线性表示中的像素 8 怎么样?相比之下,你的循环会被你的循环击中四次,即 1x8、2x4、4x2 和 8x1!

    @NateKohl 在他的回答中提出的索引将解决这个问题,因为他将行位置乘以行的长度,然后简单地沿着列走。

    【讨论】:

      【解决方案4】:

      你可以试试这个循环...

          for(int row=0;row<height;row++)
          {
              for(int col=0;col<width;col++)
              {
                  float float_data = input.at<float>(row,col);
                  // do some processing with value of float_data
                  out.at<float>(row,col) = float_data;
              }
          }
      

      是否需要将 inputout Mats 的 uchar 指针转换为浮点指针?

      【讨论】:

      • 这确实有效,因为我已经在@Nate Kohl's answer的评论中指定了它,但我需要将它作为浮点数组访问。
      猜你喜欢
      • 2012-11-15
      • 1970-01-01
      • 2012-02-25
      • 2013-05-21
      • 1970-01-01
      • 2021-03-29
      • 2017-09-12
      • 1970-01-01
      • 2014-05-18
      相关资源
      最近更新 更多