|
вычисление медианы массива (или произвольной моды), stm32f4 + STL |
|
|
|
Jul 28 2013, 16:50
|

бессмертным стать можно тремя способами
    
Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912

|
Здравствуйте. Пришлось пововырятся данным сабжем, решил поделится результатом чтоб в случае необходимости ув. коллеги могли рассмотреть решение задачи предлагаемым способом. 1. Итак, была проблема со съемом сигнала с потенциометра "крутилка рукой"- заказчик не захотел энкодеры ;( . в силу независящих от меня причин оказалось на резистеоре определенное количество шума в виде импульсных выбросов. попросили их "вырезать". проц - STM32F405RGT 168MHz 2. После анализа хар-к помехи пришла мысль выдернуть ее медианным фильтром. 3. дока по быстрому вычислению мод масивом прилагается http://klen.org/Files/Dosc/math/median.pdf4. Как всегда захотелось решить задачу в общем виде. поэтому был пременен код STL в реализации GCC 4.9.0. был нарисован шаблонный класс который реализует фифо и вычисляет текущую медиану, оформлено в виде заголовка С++: CODE /* * moda.h * * Created on: 24 июля 2013 г. * Author: klen * URL: klen.org */
#ifndef __MODA_H__ #define __MODA_H__
#include <vector> #include <algorithm>
//--------------------------------------------------------------------------------------------- template <typename T> class TModaFilterContainer { private: protected: public:
std::vector<T> vals; // входная последовательность std::vector<T> gist; // копия входной последовательности для сортировки и поиска моды
TModaFilterContainer () {}; TModaFilterContainer (size_t size) { vals.resize(size); }; ~TModaFilterContainer() {}; void Add(T val) {vals.push_front(val); } void Remove () {vals.pop_back(); } void Clear() { vals.clear(); } void Resize(size_t size) {vals.resize(size); } void Update(T val) { vals.pop_back(); vals.insert(vals.begin(), val); } };
//--------------------------------------------------------------------------- template <typename T> class TMedianFilterSort : public TModaFilterContainer<T> { public: TMedianFilterSort():TModaFilterContainer<T>() {}; TMedianFilterSort(size_t size):TModaFilterContainer<T>(size) {}; ~TMedianFilterSort() {};
T Find() { this->gist = this->vals; div_t divresult; divresult = div( this->gist.size() , 2 ); size_t n = divresult.quot; sort(this->gist.begin(), this->gist.end()); if ( divresult.rem ) return this->vals[n]; else return (this->vals[n-1] + this->vals[n]) / static_cast<T>(2); }
}; //-------------------------------------------------------------------------- template <typename T> class TMedianFilterNth : public TModaFilterContainer<T> { public: TMedianFilterNth():TModaFilterContainer<T>() {}; TMedianFilterNth(size_t size):TModaFilterContainer<T>(size) {}; ~TMedianFilterNth() {};
T Find() { this->gist = this->vals; size_t n = this->gist.size() / 2; nth_element(this->gist.begin(), this->gist.begin() + n, this->gist.end()); return this->gist[n]; } };
// EXAMPLE #if 0
#include "median.h"
typedef TMedianFilterNth<int16_t> median_t; volatile int16_t mediana;
median_t m(8);
mediana = m.Find();
m.Update(8); mediana = m.Find(); m.Update(9); mediana = m.Find(); m.Update(10); mediana = m.Find(); m.Update(8); mediana = m.Find(); m.Update(10); mediana = m.Find(); m.Update(11); mediana = m.Find(); m.Update(0); mediana = m.Find(); m.Update(1); mediana = m.Find(); m.Update(2); mediana = m.Find(); m.Clear();
// результат работы:
0 0 0 0 0 0 0 0 mediana:0 8 0 0 0 0 0 0 0 mediana:0 9 8 0 0 0 0 0 0 mediana:0 10 9 8 0 0 0 0 0 mediana:0 8 10 9 8 0 0 0 0 mediana:8 10 8 10 9 8 0 0 0 mediana:8 11 10 8 10 9 8 0 0 mediana:9 0 11 10 8 10 9 8 0 mediana:9 1 0 11 10 8 10 9 8 mediana:9 2 1 0 11 10 8 10 9 mediana:9
#endif
#endif /* __MODA_H__ */ результаты по быстродействию при спецификации шаблона типом uint16_t на STM32F405RGT 168MHz : Код размер буфера добавления элемента в фифо+ вычисление медианы(максимальное значение) 4 4,2мкс 16 10мкс 32 16мкс 128 56мкс размер кода потянутого шаблонами и алгоритмами ( класс vector + алгоритм thh ) ~1100 байт 5. можно вектор заменить на двухсвязанную очередь deque - по идее должно работать быстрее при добавлении елемента. можно ручками чтоб ваще быстро было - но это время разработки! 6. компилял компиллером из своей сборки http://electronix.ru/forum/index.php?showt...0&start=8707. это должно работать на любом вменяемом С++ компиллере и наличии стандартной библиотеки шаблонов STL надюсь с пользой запостил.
Сообщение отредактировал IgorKossak - Aug 1 2013, 06:36
|
|
|
|
|
 |
Ответов
|
Jul 28 2013, 19:49
|

Профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831

|
Я для таких целей использую фильтр - скользящее среднее, ресурсов жрет минимум, считает оч. быстро. Минус - если фильтр уж оч. большой, то возникает заметная задержка на любое изменение. Код template <typename Sample, unsigned int WIDTH> class FilterAverage { public: FilterAverage(void) { for (unsigned index = 0; index < WIDTH; ++index) samples[index] = 0; totalSum = 0; currentSampleIndex = 0; }
Sample evaluate(Sample sample) { totalSum = totalSum - samples[currentSampleIndex]; samples[currentSampleIndex] = sample; totalSum = totalSum + sample; Sample averageSample = totalSum / WIDTH; if (++currentSampleIndex >= WIDTH) currentSampleIndex = 0; return(averageSample); }
unsigned int getWidth(void) const { return(WIDTH); }
private: Sample samples[WIDTH]; Sample totalSum; // TODO: нужен соотв. тип, иначе переполнение при счете !!!!! unsigned int currentSampleIndex; }; Пользовать проще простого: объявляем экзэмпляр: Код FilterAverage<signed short, TEMPERATURE_FILTER_WIDTH> temperatureFilter; пользуем: Код signed short temperature = temperatureFilter.evaluate(temperature); У меня есть проект, где ширина окна (тут WIDTH) достигала 500 отчетов, поскольку там медианный фильтр и даже рекурсивный почти не давали толку - ну, неустранимый шум, размазанный по всему спектру. А эта штука одинаково быстро считает как для больших, так и для крохотных фильтров (разумеется, если тип отчета одинаковый).
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
Сообщений в этой теме
klen вычисление медианы массива (или произвольной моды) Jul 28 2013, 16:50 Xenia Плохой алгоритм - через полную сортировку медиану ... Jul 28 2013, 18:33 klen Цитата(Xenia @ Jul 28 2013, 22:33) Плохой... Jul 28 2013, 21:12  Xenia Цитата(klen @ Jul 29 2013, 01:12) я сог... Jul 28 2013, 21:36   klen Цитата(Xenia @ Jul 29 2013, 01:36) Было б... Jul 28 2013, 22:09    demiurg_spb А вот мой боевой вариант для uint16_t данных.
Кодs... Jul 29 2013, 06:58 neiver Цитата(Xenia @ Jul 28 2013, 22:33) Плохой... Jul 30 2013, 13:15 AlexandrY Цитата(Xenia @ Jul 28 2013, 21:33) P.P.S.... Jul 30 2013, 16:03  Xenia Цитата(AlexandrY @ Jul 30 2013, 20:03) Вы... Jul 30 2013, 16:35   demiurg_spb Цитата(Xenia @ Jul 30 2013, 20:35) Обычно... Jul 31 2013, 07:25    Tanya Цитата(demiurg_spb @ Jul 31 2013, 11:25) ... Jul 31 2013, 08:41     demiurg_spb Цитата(Tanya @ Jul 31 2013, 12:41) Кроме ... Jul 31 2013, 10:07      Tanya Цитата(demiurg_spb @ Jul 31 2013, 14:07) ... Jul 31 2013, 10:59       demiurg_spb Цитата(Tanya @ Jul 31 2013, 14:59) Не все... Jul 31 2013, 11:06        Tanya Цитата(demiurg_spb @ Jul 31 2013, 15:06) ... Jul 31 2013, 12:06         Axel Цитата(Tanya @ Jul 31 2013, 15:06) Недост... Jul 31 2013, 12:30    Xenia Цитата(demiurg_spb @ Jul 31 2013, 11:25) ... Jul 31 2013, 11:50 AlexandrY Цитата(klen @ Jul 28 2013, 19:50) результ... Jul 28 2013, 19:01 AlexandrY Цитата(Forger @ Jul 28 2013, 22:49) Я для... Jul 28 2013, 20:29 Golikov A. а как насчет экспоненциального фильтра? Быстрый, б... Jul 29 2013, 13:29 RabidRabbit По моему личному представлению всяческие скользящи... Jul 29 2013, 14:18 neiver Ура мерение длинной скоростью кода!!! ... Jul 30 2013, 07:02 Altemir Добавлю свои 5 копеек. Со времён LPC2132 использую... Jul 30 2013, 11:43 Axel Мне тоже стало интересно... Попробовал фильтр Ekst... Jul 31 2013, 05:02 KRS А ведь если фильтр скользящий, на этапе добавление... Jul 31 2013, 11:22 demiurg_spb Цитата(KRS @ Jul 31 2013, 15:22) А ведь е... Jul 31 2013, 14:10 AlexandrY Ну что, пришло время подвести некоторые итоги.
... Jul 31 2013, 13:14 KRS Цитата(AlexandrY @ Jul 31 2013, 17:14) Ка... Jul 31 2013, 14:19  demiurg_spb Цитата(KRS @ Jul 31 2013, 18:19) Но как в... Jul 31 2013, 14:28  Tanya Цитата(KRS @ Jul 31 2013, 18:19) Но как в... Jul 31 2013, 16:04   AlexandrY Цитата(Tanya @ Jul 31 2013, 19:04) ... Aug 1 2013, 07:45    Tanya Цитата(AlexandrY @ Aug 1 2013, 11:45) Гов... Aug 1 2013, 08:13     AlexandrY Цитата(Tanya @ Aug 1 2013, 11:13) Какой и... Aug 1 2013, 09:09      demiurg_spb Ещё можно попробовать сортировать пузырём, но не в... Aug 1 2013, 09:17      Tanya Цитата(AlexandrY @ Aug 1 2013, 13:09) Мы ... Aug 1 2013, 09:44       AlexandrY Цитата(Tanya @ Aug 1 2013, 12:44) Может..... Aug 1 2013, 10:23      neiver Цитата(AlexandrY @ Aug 1 2013, 13:09) Алг... Aug 1 2013, 10:20       AlexandrY Цитата(neiver @ Aug 1 2013, 13:20) Кстати... Aug 1 2013, 10:54        Altemir Цитата(AlexandrY @ Aug 1 2013, 14:54) Да,... Aug 1 2013, 11:09         AlexandrY Цитата(Altemir @ Aug 1 2013, 14:09) Упс.
... Aug 1 2013, 11:22      Altemir AlexandrY
Могу скромно попросить на той же платфор... Aug 1 2013, 10:36 Altemir AlexandrY
"Number of samplles" - это дли... Jul 31 2013, 14:03 AlexandrY Цитата(Altemir @ Jul 31 2013, 17:03) Alex... Jul 31 2013, 14:10 KRS Для определенных измерений его еще можно улучшить,... Jul 31 2013, 14:37 Altemir AlexandrY
Огромное спасибо! Как и ожидал - у м... Aug 1 2013, 11:24 VAI Я опоздал, все результаты посчитаны, да и алгоритм... Aug 1 2013, 18:45 AlexandrY Цитата(VAI @ Aug 1 2013, 21:45) ... и выл... Aug 5 2013, 08:18 VAI Херовый у меня алгоритм.. :-( Aug 5 2013, 11:59 p_v Тема старая, но очень годная. Спасибо за тесты, оч... Aug 1 2018, 16:07 p_v https://pastebin.com/xpLbyWN6 - двухпроходный вари... Aug 3 2018, 15:16
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|