如何使用指针加载附近的像素

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-&gt;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价值观! 在这方面你是对的。我将编辑那部分,但其余部分我是对的。

以上是关于如何使用指针加载附近的像素的主要内容,如果未能解决你的问题,请参考以下文章

如何访问指向 QWidget 像素的指针 [重复]

OpenCV用像素指针构建图像

如何从 OpenGL 中的帧缓冲区纹理中采样像素?

Xcode:如何制作可以显示附近位置的地图?

如何使用 UIImage 加载 16 位图像?

用opencv如何提取像素点的RGB分量