二维数组中值滤波

时间:2014-11-11 17:04:31

标签: c arrays algorithm median

我正在尝试编写在二维数组上实现median filtering的代码。 这是一张图片来说明:

IMAGE

程序从数组的开头开始。最大数组大小为100.我知道我可以使用如下数组:

int a[100][100];

存储输入,我可以使用两个for循环迭代这个数组的一部分,如下所示:

for(i=0;i<size_filter;i++)
for(j=0;j<size_filter;j++)
      temp[i][j]=a[i][j]     // not so sure

但是如何让这个代码循环遍历数组中每个元素的邻居,计算它们的中位数,并用中位数替换中心元素?


对于我正在尝试做的一些例子,假设输入是5x5矩阵,因此输入大小为5.我想在其上运行3x3中值滤波器,即每个元素都应该被替换通过围绕它的3x3元素的中位数。

程序从角落索引(0,0)开始。对于此索引,它会扫描其周围的3x3区域(其中只有四个索引实际位于输入数组中),其中包含值0,0,1和0.这些值的中位数为0,因此这就是代码应输出此数组索引。

在下图中, 粗体斜体 中的数字是中心单元格,而纯粗体数字是3x3中的邻居它周围的区域:

0 0 0 0 0
1 0 0 1 0
1 1 0 0 0
0 1 1 0 0
0 0 0 0 0 

这是另一个例子,这次是中心索引(0,1):

0 0 0 0 0
1 0 0 1 0
1 1 0 0 0
0 1 1 0 0
0 0 0 0 0 

这次,3x3区域中的元素(不包括输入数组之外的元素)的值为0,0,0,1,0和0,因此它们的中位数为0。

这是另一个例子,这次是从输入的中间开始,在中心索引(3,2):

0 0 0 0 0
1 0 0 1 0
1 1 0 0 0
0 1 1 0 0
0 0 0 0 0 

这次,3x3区域内的元素的值为1,0,0,1,1,0,0,1和1,因此它们的中位数为1。

最后的例子:

<size of array><size filter> <data>
8
3
0 0 0 0 0 0 0 0
0 5 0 0 6 0 0 0
0 0 0 0 0 7 0 0
0 0 0 0 5 0 0 0
0 0 0 5 6 0 0 0
0 0 8 5 5 0 0 0
0 0 0 7 0 0 9 0
0 0 0 0 0 0 0 0

Output:
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 5 5 0 0 0
0 0 0 5 5 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

2 个答案:

答案 0 :(得分:1)

您似乎正在尝试实施二维median filter。实现这种过滤器的直接方法是使用四个嵌套循环:在整个图像的x和y坐标上有两个外环,在中心像素的邻域上有两个内环。

在代码中比在文本中描述它可能更容易,所以这里有一些Python式的伪代码来说明:

# assumptions:
#  * image is a height x width array containing source pixel values
#  * filtered is a height x width array to store result pixel values in
#  * size is an odd number giving the diameter of the filter region

radius = (size - 1) / 2   # size = 3 -> radius = 1

for y from 0 to height-1:
    top = max(y - radius, 0)
    bottom = min(y + radius, height-1)

    for x from 0 to width-1:
        left = max(x - radius, 0)
        right = min(x + radius, width-1) 
        values = new list

        for v from top to bottom:
            for u from left to right:
                add image[v][u] to values

        filtered[y][x] = median(values)

将此代码翻译成C作为练习。

还可以通过注意到相邻阵列单元的邻域显着重叠来优化该代码,从而可以在外环的连续迭代中重用这些相邻单元的值。由于此算法在现代CPU上的性能基本上受到RAM访问延迟的限制,因此这种重用可以提供显着的加速,特别是对于大型过滤器大小。

答案 1 :(得分:0)

这样:

for(i=0;i<size_filter;i++)
for(j=0;j<size_filter;j++)
      temp[i][j]=a[i][j];

是一个很好的起点。 您只需迭代输入数组的每个像素,确定邻域的中位数并将其写入输出数组。 因此,您需要temp[i][j]=a[i][j];函数来代替WhatEverType calcMedianAt(const WhatEverType a[100][100], int r, int c, int size);

所以你可以致电temp[i][j]=calcMedianAt(a, i,j, 3);

函数本身必须将值提取到列表中(进行适当的边界处理)并找到该列表中的中位数(例如通过调用某个中值函数WhatEverType calcMedian(const WhatEverType* data, int len);并返回它。