【问题标题】:Two dimensional array median filtering二维数组中值滤波
【发布时间】:2015-01-08 07:46:28
【问题描述】:

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

程序从数组的开头开始。最大数组大小为 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

【问题讨论】:

  • 我已尝试编辑您的问题以使其更具可读性和语法性,但有时我很难说出您想说什么。请检查我没有引入任何错误,如果发现任何错误,请修复它们。谢谢!
  • 谢谢你@IlmariKaronen

标签: c arrays algorithm median


【解决方案1】:

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

用代码描述它可能比用文本更容易,所以这里有一些 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 访问延迟的限制,因此这种重用可以显着提高速度,尤其是对于较大的过滤器尺寸。

【讨论】:

  • 如何转换?什么是新清单?什么是 values.add
  • list.add(value) 是在许多面向对象语言中向(可变长度)列表添加新值的方式。我已经编辑了答案以用英语拼写出来。在 C 中,您可以分配一个 size*size 元素数组并重用它,但您必须自己跟踪它包含多少实际值。
【解决方案2】:

这个:

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-07
    • 2016-03-07
    • 2015-06-09
    • 2011-06-02
    • 2017-06-10
    相关资源
    最近更新 更多