如何使用指针加载附近的像素
Posted
技术标签:
【中文标题】如何使用指针加载附近的像素【英文标题】:How to load nearby pixels using pointer 【发布时间】:2011-10-26 19:25:23 【问题描述】:假设我有一个图像矩阵,并且我在一个特定的像素 [比如 4],如下所示:
0 1 2
3 `4` 5
6 7 8
我正在尝试循环遍历所有像素并尝试访问 0、1、2、3、5 6、7、8,我将其值存储在名为 Pixel
的数组中。这是我的尝试使用 OpenCV,请告诉我哪里出错了。
我正在使用指针temp_ptr
来访问IplImage image
。
uchar* temp_ptr=0 ;
CvScalar Pixel[3][3];
int rows=image->height,cols=image->width,row,col;
for( row = 0; row < rows-2; ++row)
for ( col = 0; col < cols-2; ++col)
temp_ptr = &((uchar*)(image->imageData + (image->widthStep*row)))[col*3];
for (int krow = -1 ; krow <= 1; krow++)
for (int kcol = -1; kcol <= 1; kcol++)
temp_ptr = &((uchar*)(image->imageData + (image->widthStep*row+krow)))[(col+kcol)*3];
for(int i=0; i < 3; i++)
for(int j=0; j < 3; j++)
for(int k=0; k < 3; k++)
Pixel[i][j].val[k]=temp_ptr[k];
我不确定如何使用temp_ptr
加载周围的像素,请帮帮我。
【问题讨论】:
有六个嵌套的 for 循环几乎肯定是你出错的地方。您需要循环遍历所有像素还是只循环那些可以拥有所有八个“邻居”的像素? 只有那些可以有 8 个邻居的人......也是我以同样的方式访问所有像素的方式,我将通过计算所有像素的平均值并存储来自 Color 的新值来存储值[RBG] 数组Pixel
...进入中心,即4
像素。
你有很多有用的提示。最重要的是您永远不会将结果写回图像中。而且,我不想听起来很苛刻,但正如有人所说“开始学习编程 - 你的代码完全是一团糟”。每个人的代码一开始都是一团糟,我认为你应该尝试自己解决这个问题,并尝试理解你在做什么。你没有 OpenCV 的麻烦。您在编写算法时遇到了麻烦。一旦你把它到位 - 你会没事的! :-)
@danbystrom - 我认为你错了,我的算法很好,是的,我知道我应该将值写回像素,我只是放错了大括号......
【参考方案1】:
好吧,先生,听起来您想进行卷积,当您触手可及 OpenCV 时这样做有点像在意大利面条上敲开开罐器以用钝力将其爆开。
事实上,你所做的几乎就是cv::blur(src, dst, cv::Size(3,3))
的输出,除了它还包括平均中心像素。
如果您想排除中心像素,那么您可以创建一个自定义内核 - 只是一个具有适当权重的矩阵:
[.125 .125 .125
.125 0 .125
.125 .125 .125 ]
并使用cv::filter2d(src, dst, -1, kernel)
将其应用于图像。
【讨论】:
【参考方案2】:假设image->imageData
是RGB格式,所以每个像素有3个字节,你可以这样做:
int rows = image->height;
int cols = image->width;
uchar* temp_ptr = 0;
CvScalar pixels[8];
for (int col = 0; col < image->height - 2; col++)
temp_ptr = image->imageData + image->width * col + 1;
for (int row = 0; row < image->width - 2; row++)
temp_ptr += row * 3;
pixels[0].val = temp_ptr - width * 3 - 3; // pixel 0 from your example
pixels[1].val = temp_ptr - width * 3; // 1
pixels[2].val = temp_ptr - width * 3 + 3; // 2
pixels[3].val = temp_ptr - 3; // 4
pixels[4].val = temp_ptr + 3; // etc...
pixels[5].val = temp_ptr + width * 3 - 3;
pixels[6].val = temp_ptr + width * 3;
pixels[7].val = temp_ptr + width * 3 + 3;
// calculate averages here and store them somewhere (in a vector perhaps)
注意我没有测试这段代码。
【讨论】:
我不知道opencv。例如,我只是猜测 CvScalar.val 的类型是 uchar[3]。我只是想给你一个想法,而不是可编译的现成代码:)【参考方案3】:首先你必须开始学习一些编程。你的完整代码是一团糟。 我很快就发现了一些主要问题:
首先,您必须从 1 开始前两个 for 循环(因为您在应用窗口时会递减 -1),最终会读取一些未分配的内存地址。 第二个第一个 temp_ptr = &((uchar*)(image->imageData + (image->widthStep*row)))[col*3] 没用,可以去掉。另一个
temp_ptr = &((uchar*)(image->imageData + (image->widthStep*row+krow)))[(col+kcol)*3];
有个小问题,运算符优先级,应该是:
temp_ptr = &((uchar*)(image->imageData + image->widthStep*(row+krow))[(col+kcol)*3];
您不需要其他 3 个内部循环
也不清楚你想做什么,你想获得特定像素的邻域(然后你不需要循环)或者你想对图像中的每个像素应用一个内核。
【讨论】:
alinoz 你的答案是错误的,我不知道谁赞成它......应该知道数据类型 CvScalar 是一个结构,其中包含一个名为val
的数组,您可以在其中存储 RBG
价值观!
在这方面你是对的。我将编辑那部分,但其余部分我是对的。以上是关于如何使用指针加载附近的像素的主要内容,如果未能解决你的问题,请参考以下文章