将图像像素作为浮点数组访问

时间:2013-01-16 15:01:56

标签: c++ image-processing opencv

我想在opencv中将图像像素作为float数组访问。我做了以下事情:

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)。感谢。

4 个答案:

答案 0 :(得分:1)

要想明白问题是什么,想象一下16乘16的图像。现在想一想线性表示中的像素数17。

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

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

索引@NateKohl在他的回答中将会修复它,因为他将行位置乘以行的长度然后只是沿着列行走。

答案 1 :(得分:1)

一些想法:


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矩阵)并使用它来帮助调试代码。

答案 2 :(得分:1)

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

    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;
        }
    }

是否需要将ucharinput Mats的out指针转换为浮动指针?

答案 3 :(得分:1)

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

更改输入的尺寸,它为图像添加6行和6列。这意味着当您定义并尝试循环输入值时,您的高度和宽度变量将保持错误的值。

如果您将订单更改为

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

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

它应该可以正常工作。