demiurg_spb 1 September 27 Posted September 27 · Report post Погуглите про медианную фильтрацию - даже в википедии очень доступно изложжено. Формально она начинает работать с окна от 3 элементов и реализация проще когда ширина окна нечётная. Ниже я приведу алгоритм такого фильтра с окном 3 и увидите насколько он ресурсоёмкий. Ну и на больших окнах сортировать можно и нужно лишь N/2+1 элемент. При обработке сырых данных с АЦП медиана прекрасна работает десятилетями в нашем оборудовании. Далее применяется lowpass фильтр с возможностью подстройки частоты среза пользователем. По моему опыту только такая комбинация даёт приемлемый результат при обработе сигналов с датчиков на производстве, где обычно не сильно хорошо с ЭМ обстановкой. Без медианы в таких случаях зачастую возникают систематические ошибки измерения при включении рядом мощного ЭМ генератора (типа частотного привода или клацающего контактора). Всё сильно зависит от задачи. Например идут импульсы с реперного диска и мы считаем частоту оборотов вала. Зачем принимать в расчёт импульс пришедший в 1000 раз ранее ожидаемого и кормить им сглаживающий филтр чтобы потом на экране видеть постоянные флуктуации значения скорости? И у ТС вовсе не с производительностью проблемы. Перечитайте внимательно топик прежде чем пихать свой совет куда не глядя (отвечу вашими же словами)... #define median3(x1, x2, x3) \ ({ \ typeof(x1) a = (x1); \ typeof(x2) b = (x2); \ typeof(x3) c = (x3); \ \ if (a>b) {typeof(b) t=b; b=a; a=t;} /* swap ab */ \ if (b>c) b=c; /* swap bc (max bubble (c) is gone) */ \ \ (a>b)? a:b; \ }) // testcase #include <assert.h> #include <stdio.h> int main(void) { /* Простые случаи, все перестановки */ assert(2 == median3(1,2,3)); assert(2 == median3(1,3,2)); assert(2 == median3(2,1,3)); assert(2 == median3(2,3,1)); assert(2 == median3(3,1,2)); assert(2 == median3(3,2,1)); /* Равные значения */ assert(5 == median3(5,5,5)); assert(5 == median3(5,5,7)); assert(5 == median3(7,5,5)); assert(5 == median3(5,7,5)); /* Отрицательные */ assert(-2 == median3(-1,-2,-5)); assert(-2 == median3(-1,-5,-2)); assert(-2 == median3(-2,-5,-1)); assert(-2 == median3(-2,-1,-5)); assert(-2 == median3(-5,-1,-2)); assert(-2 == median3(-5,-2,-1)); printf("test pass\n"); return 0; } Quote Share this post Link to post Share on other sites More sharing options...
jcxz 342 September 27 Posted September 27 · Report post 2 часа назад, demiurg_spb сказал: Погуглите про медианную фильтрацию - даже в википедии очень доступно изложжено. Может это вам следует "погуглить и почитать википедию", прежде чем советовать это тем, кто знает что это такое и не раз применял? 2 часа назад, demiurg_spb сказал: Формально она начинает работать с окна от 3 элементов и реализация проще когда ширина окна нечётная. Да ладно? Правда что-ли? Вот вам набор данных (массив сэмплов): {64, 128, 64, 128, 64, 128, 64, 128, 64, 128, 64, 128, ...} т.е. - шумят примерно младшие 6 бит. Импульсных помех как видно - нет. Если прогнать это через скользящее среднее по 3 элемента, то получим: {85, 107, 85, 107, 85, 107, 85, 107, 85, 107, ...} Т.е. шумят уже только ~4.5 бита, значит - результат фильтрации имеется. Вывод: Фильтр работает. Если прогнать это через медианный фильтр по 3 элемента, то на выходе получим результат, равный входному массиву: {64, 128, 64, 128, 64, 128, 64, 128, ...} Т.е. ваш медианный фильтр вообще не оказывает никакого фильтрующего воздействия на данную выборку. Вывод: фильтр не работает. 2 часа назад, demiurg_spb сказал: При обработке сырых данных с АЦП медиана прекрасна работает десятилетями в нашем оборудовании. Сочувствую вашим заказчикам. Выше я привёл массив типичных данных с АЦП, не содержащих импульсных помех (к сведению: не все источники данных содержат импульсные помехи!). "Прекрасная работа" вашего метода видна совершенно очевидно. 2 часа назад, demiurg_spb сказал: По моему опыту только такая комбинация даёт приемлемый результат при обработе сигналов с датчиков на производстве, где обычно не сильно хорошо с ЭМ обстановкой. Без медианы в таких случаях зачастую возникают систематические ошибки измерения при включении рядом мощного ЭМ генератора (типа частотного привода или клацающего контактора). Если при перевозке хрупкого груза на телеге по ухабистой дороге, чтобы его не попортить, к телеге нужно приделать рессоры. То это вовсе не означает, что при перевозке того же груза по морю на огромном судне, к этому судну также нужно приделывать амортизаторы. Так и с обработкой сигналов: Не нужно всюду пытаться прикостыливать медианную фильтрацию. Не думая. Даже туда, где от неё пользы столько же, как той телеге от 5-го колеса. 2 часа назад, demiurg_spb сказал: И у ТС вовсе не с производительностью проблемы. Перечитайте внимательно топик прежде чем пихать свой совет куда не глядя (отвечу вашими же словами)... Точно "не с производительностью"? А вы сами топик внимательно читали? Он в самом первом сообщении пишет, что проблема именно с производительностью: В 11.06.2021 в 01:24, whale сказал: при осреднении обработка данных заметно тормозится, 2 часа назад, demiurg_spb сказал: #define median3(x1, x2, x3) \ ({ \ typeof(x1) a = (x1); \ typeof(x2) b = (x2); \ typeof(x3) c = (x3); \ \ if (a>b) {typeof(b) t=b; b=a; a=t;} /* swap ab */ \ if (b>c) b=c; /* swap bc (max bubble (c) is gone) */ \ \ (a>b)? a:b; \ }) Теперь берём в руки калькулятор и считаем (предположим, что код ТС максимально оптимизирован по скорости и выполняется из 0-wait-states памяти на Cortex-M4): По грубой прикидке код ТС из 1-го поста потребует: 1600*(4+2+1+1+1+2)*70 = 1232000 тактов/сек (деление заменено на умножение, CPU имеет write buffer и сделано предположение, что все команды чтения спарены - т.е. предполагаем, что оптимизатор очень умный, и выполнение идёт в идеальных условиях; в реале скорей всего будет гораздо хуже). Ваш код для цикла ТС (в тех же условиях - макс.оптимизация) потребует: 1600*(4+5+3+3+1+1+2)*70 = 2128000 тактов/сек. Т.е. - ваш код тормознее даже кода ТС в ~1.7 раза. Это при том, что он ещё скорее всего выдаст более худший результат, чем даже код ТС. А в худшем случае (при выполнении из медленной памяти без кеша и глупом компиляторе, который не будет использовать команды условного выполнения, а создаст вермишельный код из ветвлений), ваш код будет многократно тормознее, чем скользящее среднее. Quote Share this post Link to post Share on other sites More sharing options...
demiurg_spb 1 September 27 Posted September 27 · Report post 3 hours ago, jcxz said: Теперь всё тоже самое проверьте для ряра данных идущих с датчика положения вала с меткам на валу. С таймера захвата приходят 16битные слова 50000 49990 49995 10 50010 50015... Сильно поможет ваш фильтр без медианы? Почему вы всё время говорите что импульсных помех нет? Если их у вас нет - это не значит что их нет вовсе. И почему вы всё время упираетесь в нехватку производительности? Где об этом вообще разговор? У ТС была бага которая тормозила его софт. У вас я ничего не спрашиваю про ваш конкретный случай где нет пиковых выбросов. Зачем вы мне льёте в уши это? Перечитайте моё предложение ТС. Я изначально предложил ему попробовать двухступенчатаю фильтрацию, а не только медиану. Это хорошо зарекомендовавший себя метод. И вы не можете знать ЗАРАНЕЕ куда будет установлен прибор на машину или корабль в вашей терминологии. Мой вариант будет работать везде. Ваш нет. Всё. Quote Share this post Link to post Share on other sites More sharing options...
jcxz 342 September 27 Posted September 27 · Report post 11 минут назад, demiurg_spb сказал: Теперь всё тоже самое проверьте для ряра данных идущих с датчика положения вала с меткам на валу. С таймера захвата приходят 16битные слова 50000 49990 49995 10 50010 50015... Сильно поможет ваш фильтр без медианы? А может стоит поискать причину - почему у вас прут такие мощные импульсные помехи? Вместо заметания проблемы под ковёр медианным фильтром. В текущем проекте у меня имеется датчик на валу PMSM-мотора. Синус/косинусный. Импульсных помех с него не наблюдаю. Наблюдаю шум в младших разрядах. Подобный тому, что приводил выше. Сильно поможет ваш медианный фильтр? Смотрим внимательно на приведенную выше выборку и пытаемся начать думать. 11 минут назад, demiurg_spb сказал: Почему вы всё время говорите что импульсных помех нет? Если их у вас нет - это не значит что их нет вовсе. Если у вас они есть, это не значит, что у ТС-а они есть. Тема вообще была не об этом. К чему вы так упорно пихаете свой медианный фильтр, если из задачи ТС никак не следует, что он ему нужен и что у него есть эти самые импульсные помехи? Вопрос ТС был об усреднении. И только о нём. 11 минут назад, demiurg_spb сказал: У вас я ничего не спрашиваю про ваш конкретный случай где нет пиковых выбросов. Зачем вы мне льёте в уши это? Можем выдохнем и не будем хамить? 11 минут назад, demiurg_spb сказал: Это хорошо зарекомендовавший себя метод. И вы не можете знать ЗАРАНЕЕ куда будет установлен прибор на машину или корабль в вашей терминологии. Мой вариант будет работать везде. Ваш нет. Очевидная ложь. Я привёл конкретный пример выше. Выборку сэмплов. Покажите: как именно ваш вариант будет работать с этой выборкой? Код и результат в студию! Пока по этому варианту мы видим, что ваш метод не работает, а простое усреднение - работает. Quote Share this post Link to post Share on other sites More sharing options...
EdgeAligned 122 September 28 Posted September 28 · Report post Медианная фильтрация предназначена для отсеивания экстремумов (мин/макс значений), но не для усреднения или сглаживания шума. Для топикстартера вряд ли актуально сегодня, поскольку тема была создана ажно в 2021 году 🙂 1 Quote Share this post Link to post Share on other sites More sharing options...
demiurg_spb 1 September 28 Posted September 28 · Report post On 9/27/2025 at 5:35 PM, jcxz said: Очевидная ложь. Мы даже понятия не имеем что за источник данных у ТС и какого рода там помехи, при этом вы спорите до проблем с ЖКТ что медиана это зло. Повторяю, что игнорирование существования импульсных помех, как минимум, в распределённых системах - глупо! Рядом установили здоровенный контактор, отгнвает экран, сварочные работы, вспышка на солнце, слаботочка в одном лотке с силовыми, ребята забухали - причин их возникновения десятки если не сотни. Для закрепления материала, рассмотрим жизнь измерительного прибор с выносными датчиками в ИП ЖОРИК МКРТЧАН с типовыми сотрудниками типа "ценные кадры из азии" - антиподами "инженерам из NASA". Так вот, очень часто такие "киповцы" не понимают что русский алфавит - основа русских слов и документации на прибор, и вообще, как стоит выбирать, прокладывать и экранировать провода от датчика до прибора. На мой взгляд игнорирать ситуацию "дело было не в бобине" по меньшей степени просто глупо, а разумно минимизировать риски. Благодаря многолетнему опыту продаж и интеграции собственного оборудования на объекты, включая очень ответственные, у меня есть однозначное мнение, что хорошо спроектированный прибор - это прибор, работающий максимально надёжно в разных условиях. Тем более, что сложность программы в данном случае возросла на условные 10 строк кода, и это никак не увеличивает стоимость прибора в серии. Повторяю ещё раз! Я не говорю о том, что медиана должна использоваться одна без следующей стадии фильтрации и не сравниваю её с усреднением и тем более не говорю что она его заменяет! Ваши выкладки из-за неверной трактовки написанного заводят беседу в тупик. Так продолжать бессмысленно. На этом закончиваем трату времени впустую. Удачи! Quote Share this post Link to post Share on other sites More sharing options...