2014-11-11 1 views
1

Я пытаюсь написать код, который реализует 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, окружающее его (из которого только 4 индекса фактически лежат внутри входного массива), который содержит значения 0, 0, 1 и 0. Медиана этих значений равна 0, так что это то, что код должен выводиться для этого индекса массива.

В приведенном ниже рисунке, число в жирного курсива является центр ячейки, и простое смелых числа своих соседей в регионе 3х3 вокруг него:

 
00 0 0 0 
10 0 1 0 
1 1 0 0 0 
0 1 1 0 0 
0 0 0 0 0 

Вот еще один пример , на этот раз с индексом центра (0,1):

 
000 0 0 
100 1 0 
1 1 0 0 0 
0 1 1 0 0 
0 0 0 0 0 

на этот раз, элементы в области 3х3 (за исключением трет шланги вне входного массива) имеют значения 0, 0, 0, 1, 0 и 0, и, следовательно, их медиана равна 0.

Вот еще один пример, на этот раз с середины ввода, на индекс центр (3,2):

 
0 0 0 0 0 
100 1 0 
110 0 0 
011 0 0 
0 0 0 0 0 

на этот раз элементы в пределах области 3х3 имеют значения 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 
+0

Я попытался отредактировать ваш вопрос, чтобы сделать его более читабельным и грамматическим, но мне иногда было трудно сказать, что вы пытались сказать. Пожалуйста, проверьте, чтобы я не вводил никаких ошибок и исправлял если вы найдете какой-либо. Спасибо! –

+0

Спасибо, @IlmariKaronen –

ответ

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 остается в качестве упражнения.

Также можно оптимизировать этот код, отметив, что окрестности соседних ячеек массива перекрываются значительно, так что значения этих соседних ячеек могут быть повторно использованы при последовательных итерациях внешних контуров. Поскольку производительность этого алгоритма на современных процессорах существенно ограничена задержкой доступа к ОЗУ, такое повторное использование может обеспечить значительное ускорение, особенно для больших размеров фильтра.

+0

Как я могу преобразовать? Что нового? Что такое values.add –

+0

'li st.add (value) '- это то, как вы добавляете новое значение в список (переменной длины) на многих объектно-ориентированных языках. Я отредактировал ответ, чтобы записать его на английском языке. В C вы можете просто выделить массив элементов 'size * size' и повторно использовать его, хотя вам придется отслеживать, сколько фактических значений оно содержит. –

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); и вернуть его.