2

我想在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)。谢谢。

4

4 回答 4

1

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

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

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

@NateKohl 在他的回答中提出的索引将修复它,因为他将行位置乘以行的长度,然后简单地沿着列走。

于 2013-01-16T15:34:41.093 回答
1

一些想法:


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


根据opencv 文档,有一个模板化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 矩阵)并使用它来帮助调试您的代码。

于 2013-01-16T15:38:18.257 回答
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;
        }
    }

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

于 2013-01-16T16:13:59.573 回答
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;

它应该可以正常工作。

于 2013-01-16T16:28:42.757 回答