|
вычисление медианы массива (или произвольной моды), 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, 18:33
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Плохой алгоритм - через полную сортировку медиану считает.  Осмелюсь предложить алгоритм собственного сочинения. Содержимое массива не трогает, копий с него не снимает. Для МК (когда мало памяти) - самое оно. Опять же STL-библитека ему не нужна, ибо никаких функций он не вызывает и никаких FIFO-буферов не использует. Код datatype median( datatype array, int length) // массив и его длина { int slit = length/2; for( int i=0; i < length; i++) { int s1=0, s2=0; datatype val = array[i]; for( int j=0; j < length; j++) { if( array[j] < val) { if( ++s1 > slit) goto nexti; } else if( array[j] > val) { if( ++s2 > slit) goto nexti; } } return val; nexti: } return 0; // чистая формальность, досюда исполнение никогда не доходит } А если хранить переменные s1, s2, slit и val в регистрах, то скорость совсем хороша. Алгоритм основан на последовательной проверке точек массива на их "медианность". Проверка состоит в сравнении точки со всеми остальными - подсчетом двух сумм (s1 и s2) - количества точек, которые оказались больше данной, и количества тех, которые оказались меньше нее. Превышение показания хотя бы одного из счетчиков свыше половины длины массива (slit) бракует данную точку ДОСРОЧНО и переходит к проверке следующей (переход на nexti). До полного перебора всех точек обычно не доходит, т.к. подходящая точка находится раньше (где-то в середине массива), т.е. тоже ДОСРОЧНО. P.S. datatype - произвольный тип данных, для которого определены операции > и <. При желании можно хоть через template все это обобщить. P.P.S. Готова сразиться по скорости с мострообразным алгоритмом Клена.
|
|
|
|
|
Jul 28 2013, 21:12
|

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

|
Цитата(Xenia @ Jul 28 2013, 22:33)  Плохой алгоритм - через полную сортировку медиану считает.  плохой или не плохой это понятно, но полную сортировку не делает! http://www.cplusplus.com/reference/algorithm/nth_element/"Rearranges the elements in the range [first,last), in such a way that the element at the nth position is the element that would be in that position in a sorted sequence. The other elements are left without any specific order, except that none of the elements preceding nth are greater than it, and none of the elements following it are less. The elements are compared using operator< for the first version, and comp for the second." Цитата P.P.S. Готова сразиться по скорости с мострообразным алгоритмом Клена.   я согласен, тока я ручками попишу сам  , STL это был "вброс"  время мерил осцилографом.
|
|
|
|
Сообщений в этой теме
klen вычисление медианы массива (или произвольной моды) Jul 28 2013, 16:50  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 Forger Я для таких целей использую фильтр - скользящее ср... Jul 28 2013, 19:49 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
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|