MATLAB: быстрое сглаживание двухмерных изображений с большой сигмой

У меня есть программа, которая обрабатывает большие наборы двухмерных изображений в оттенках серого и в настоящее время использует imgaussfilt() несколько раз при обработке каждого изображения (Matlab 2015b). Это оказывается очень затратным с точки зрения времени выполнения. У меня есть несколько случаев больших значений сигмы, которые кажутся более дорогостоящими (например, imgaussfilt (изображение, [1,40])... imgaussfilt (изображение, [10,15])).

Кто-нибудь знает какие-либо более быстрые версии/методы сглаживания по Гауссу?

Я пытался использовать метод FFT/IFFT, но это, похоже, занимает значительно больше времени, чем родная функция MATLAB imgaussfilt().

Также пробовал запускать сглаживание по Гауссу последовательно по X, а затем по Y, но это занимает немного больше времени, чем встроенная функция imgaussfilt().

Другой метод сглаживания также может работать нормально, есть ли другие методы, которые значительно быстрее? (пробовал imboxfilt()... только немного быстрее и не так хорошо).

заранее спасибо


person user3470496    schedule 23.08.2016    source источник
comment
Вы пытались использовать imfilter с ядром Гаусса? imfilter использует интегрированные примитивы производительности Intel для эффективной фильтрации.   -  person rayryeng    schedule 23.08.2016
comment
Зачем нужно применять этот фильтр несколько раз при обработке одного изображения? возможно, вы можете использовать его только один раз в начале с соответствующим размером   -  person Amitay Nachmani    schedule 23.08.2016
comment
@rayryeng Я попробовал imfilter с гауссовским ядром - он был довольно быстрым, но все же немного медленнее, чем imgaussfilt()   -  person user3470496    schedule 23.08.2016
comment
@amitay Я выполняю разные этапы обработки / извлекаю разные характеристики из одного и того же изображения (я могу обрезать несколько imgaussfilts и тоже работаю над этим, но большинство из них необходимы для моих целей)   -  person user3470496    schedule 23.08.2016
comment
Может быть, попробовать выполнить некоторую обработку, используя изображения меньшего размера? с помощью пирамид?   -  person Amitay Nachmani    schedule 23.08.2016
comment
Влияет ли уменьшение изображения на ваши результаты? Если вам нужно выполнить множество проходов с различными настройками фильтра, даже небольшое уменьшение размера может дать вам желаемое ускорение.   -  person Pikalek    schedule 23.08.2016
comment
Спасибо за все ответы, изменение размера изображения помогло, и мои результаты по-прежнему выглядят довольно хорошо ... не знаю, почему я не подумал об этом, спасибо за простое исправление!   -  person user3470496    schedule 24.08.2016


Ответы (2)


Судя по вашему описанию, вы используете сильно анизотропные фильтры, здесь [1,40] или [10,15]. Если это действительно так, так что каждый из ваших фильтров не связан с другим, я рекомендую использовать усреднение изображений с помощью интегральных изображений. Соответствующими функциями Matlab являются IntegerImage и Integerfilter. Это не сглаживание по Гауссу, а блочный фильтр. Однако, однажды вычисленное для входного изображения, интегральное изображение может быть повторно использовано для многих различных фильтров, а сила эффекта фильтра не зависит от размера ядра (!), что, вероятно, не относится к imgaussfilter. Однако, возможно, вам следует позаботиться об эффектах на границах изображения.

person C. Rahn    schedule 24.08.2016
comment
Выбрав правильный размер рамочного фильтра, вы можете аппроксимировать эффекты размытия по Гауссу. Хорошее наблюдение с предложением фильтра коробки. +1. - person rayryeng; 25.08.2016

Один из самых дешевых методов сглаживания, который я могу придумать, — просто взять среднее значение соседних пикселей:

A(i,j) = (A(i-1,j) + A(i+1,j) + A(i,j-1) + A(i,j+1) + w*A(i,j))/(4+w);

где w=4 — некоторый весовой коэффициент по вашему выбору. Вы можете сдвинуть массив с помощью circshift:

A(i-1,j) = circshift(A(i,j), [1 0]);

и поэтому, предполагая, что вы храните все N ваших изображений в массиве A(x,y,N), полная команда Matlab:

A = (w*A + circshift(A, [-1 0 0]) + circshift(A, [1 0 0]) + circshift(A, [0 -1 0]) + circshift(A, [0 1 0]))/(4+w);
person Airidas Korolkovas    schedule 23.08.2016