我想在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)。感谢。
答案 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;
}
}
是否需要将uchar
和input
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;
它应该可以正常工作。