Медіанний фільтр (Median Filter)

Програми для ARDUINO DUE
Аватар користувача
radioman
Site Admin
Повідомлень: 134
З нами з: 28 вересня 2020, 12:01
Звідки: Тернопіль
Дякував (ла): 8 разів
Подякували: 6 разів

Re: Медіанний фільтр (Median Filter)

Повідомлення radioman »

pawa писав: 27 січня 2021, 07:48... Так:...
Прикро, але код модифікує масив. На малюнку у першому стовпчику вміст "динамічного" масиву при включеному сортуванні; у другому - лише циклічне заповнення масиву (симуляція вхідних даних):
Симуляція надходження і сортування даних
Симуляція надходження і сортування даних
PS. Я допустився помилки - Ваш код теж потребує копіювання масиву, адже це модифікація сортування включенням (Insertion sort); на даний час Ваша модифікація найшвидша - 6 мікросекунд з копіюванням масиву.

PPS. Як буде час порівняю час виконання в залежності від розташування елементів в масиві.
Аватар користувача
radioman
Site Admin
Повідомлень: 134
З нами з: 28 вересня 2020, 12:01
Звідки: Тернопіль
Дякував (ла): 8 разів
Подякували: 6 разів

Re: Медіанний фільтр (Median Filter)

Повідомлення radioman »

Допиляв код. 8-) Так як є бажання динамічно змінювати довжину масиву, зіткнувся з перепоною - розмір масиву не може бути заданий змінною; це пов'язано з тим, що розмір глобального масиву повинен бути відомим до початку роботи програми.
Але розмір локального масиву (у функції) можна задати змінною, тому що локальний масив виділяється з динамічної пам'яті та може бути будь якого розміру.
Тому масив для сортування розміщено у функції:

Код: Виділити все

/* функція розрахунку медіани*/
int MedianFilter(int *window, int intArrSize)      	// аргументами функції є посилання на масив та довжина масиву
{
  int newArray[intArrSize];                             // масив для функції
Копіювання масиву за топомогою memcpy(newArray, window, intArrSize); у функції чомусь не працює, тому повернувся до "перезапису" (можна попробувати зробити "вхідне" сортування та подивитись чи буде виграш у часі виконання):

Код: Виділити все

 /* копіювання масиву */
  //memcpy(newArray, window, intArrSize);
  /**/
  byte c;
  for (c = 0; c < intArrSize; c++)
  {
    newArray[c] = window[c];
  }
У такій реалізації найкращі результати показала модифікація алгоритму сортування включенням (Insertion sort) від pawa:

Код: Виділити все

 /* сортування включенням (Insertion sort) */
  int counter = 0;
  for (int i = 1; i < intArrSize; i++) 
  {
    for (int j = i; j > 0 && *(newArray + j - 1) > *(newArray + j); j--) 
    {
      counter++;
      int tmp = *(newArray + j - 1);
      *(newArray + j - 1) = *(newArray + j);
      *(newArray + j) = tmp;
    }
  }
Інший код, практично, без змін.

PS. Можна відмовитись від посилання на масив вхідних даних в аргументі функції. Варто у функцію передавати лише потік даних, а записувати їх у "материнський" масив вже у самій функції.
PPS. У додадому архіві тестовий скетч сортування включенням (Insertion sort) на довільний розмір вікна:
MedianFilter_pawa_210128-1x1.7z
Сортування включенням (Insertion sort)
(1.39 Кіб) Завантажено 2925 разів
pawa
Повідомлень: 75
З нами з: 28 вересня 2020, 20:26
Дякував (ла): 1 раз
Подякували: 5 разів

Re: Медіанний фільтр (Median Filter)

Повідомлення pawa »

Можна зробити масив максимальної довжини (буфер), а використовувати стільки елементів скільки буде потрібно.
Аватар користувача
radioman
Site Admin
Повідомлень: 134
З нами з: 28 вересня 2020, 12:01
Звідки: Тернопіль
Дякував (ла): 8 разів
Подякували: 6 разів

Re: Медіанний фільтр (Median Filter)

Повідомлення radioman »

Так і є:

Код: Виділити все

/* медіана pawa_radioman */
/* https://radioman.com.ua */
int intFilterLengthWdi = 6;
int window[] = {};
Але, для отримання медіани, потрібно задавати довжину масиву. Вхідний потік записується по лічильнику у "материнський" (буферний) масив (в симуляції - з тестового масиву):

Код: Виділити все

window[interruptCtr] = window0[interruptCtr]; 
 if ( interruptCtr++ >= intFilterLengthWdi - 1 )                                 // лічильник для симуляції
  {
    interruptCtr = 0;
  }
PS. Ви можете переглянути весь скетч за допомогою блокноту.
Відповісти