Применять фильтры к изображениям, когда нет пикселей данных

У меня есть изображение, которое содержит много пикселей без данных. Изображение представляет собой массив 2d numpy, а значения без данных равны «Нет». Всякий раз, когда я пытаюсь применить к нему фильтры, кажется, что значения none учитываются в ядре и заставляют мои пиксели исчезать.

Например, у меня есть это изображение:

Я попытался применить к нему фильтр lee с помощью этой функции (взято из Speckle (Lee Filter) в Python):

from scipy.ndimage.filters import uniform_filter
from scipy.ndimage.measurements import variance

def lee_filter(img, size):
    img_mean = uniform_filter(img, (size, size))
    img_sqr_mean = uniform_filter(img**2, (size, size))
    img_variance = img_sqr_mean - img_mean**2

    overall_variance = variance(img)

    img_weights = img_variance / (img_variance + overall_variance)
    img_output = img_mean + img_weights * (img - img_mean)
    return img_output

но результаты выглядят так:

с предупреждением:

UserWarning: Предупреждение: преобразование замаскированного элемента в nan. дв = np.float64 (self.norm.vmax) - np.float64 (self.norm.vmin)

Я также пытался использовать библиотеку findpeaks.


from findpeaks import findpeaks
import findpeaks
#lee enhanced filter
image_lee_enhanced = findpeaks.lee_enhanced_filter(img, win_size=3, cu=0.25)

но я получаю такое же пустое изображение. Когда я использовал медианный фильтр на том же изображении, с ndimage проблем не возникло.

Мой вопрос: как я могу запустить эти фильтры на изображении, не позволяя значениям None прерывать результаты?

изменить: я предпочитаю не устанавливать значение пикселей равным 0, потому что значение диапазона пикселей находится в диапазоне от -50 до 1 (это значения индекса). Кроме того, я боюсь, что если я изменю его на любое другое значение, например, 9999), это также повлияет на фильтр (я ошибаюсь?)

Редактировать 2: Я прочитал ответ Криса Луенго и попытался применить что-то подобное с медианным фильтром scipy.ndimage, поскольку понял, что результат также искажен.

Это исходное изображение:

Я попытался замаскировать значения Null:


idx = np.ma.masked_where(img,img!=None)[:,1]
median_filter_img = ndimage.median_filter(img[idx].reshape(491, 473), size=10)
zeros = np.zeros([img.shape[0],img.shape[1]])

zeros[idx] = median_filter_img

Результат выглядит так (цвет темнее, чтобы увидеть проблему по краям):

Как видно, кажется, что значения ребер зависят от значений None. Я сделал это также с img! = 0, но получил ту же проблему.

(просто добавить: значения пикселей находятся в диапазоне от 1 до -35)

нельзя ли значения none заменить на 0 или это будет мешать работе фильтра? Кроме того, какова ваша основная цель здесь?

sai 10.12.2020 16:59

@sai У меня не может быть нуля. моя цель - сгладить изображение и избавиться от шума (также в других изображениях, которые имеют больше шума, чем это)

Reut 10.12.2020 17:00

1. заменить пустые значения на 0, 2. создать маску пустых пикселей, 3. скопировать пустую область, 4. применить фильтр к изображению с 0, 5. снова установить маскированные значения на 0

Grzegorz Krug 16.12.2020 08:18

@GrzegorzKrig Я боюсь, что изменение незначащих значений на 0 прервет результаты. Кроме того, я считаю, что сделал что-то похожее на вашу идею (появляется в сообщении)

Reut 16.12.2020 11:49
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
4
916
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Кажется, что простое решение - установить незначащие значения на ноль. Я не знаю, как бы вы обошли это, потому что большинство ядер обработки изображений требуют, чтобы вы применяли какое-то значение. a[numpy.argwhere(a==None)] = 0

Для фильтра не обязательно требовать некоторые значения. Это зависит от реализации

Mark Jeronimus 10.12.2020 17:03

@byshiny, пожалуйста, смотрите исходный пост, я отредактировал свой пост относительно этого

Reut 10.12.2020 17:03
Ответ принят как подходящий

Если вы хотите применить фильтр линейного сглаживания, вы можете использовать Normalized Convolution.

Основной рецепт таков:

  1. Создайте изображение маски, которое равно 1 для пикселей с данными и 0 для пикселей без данных.
  2. Присвойте пикселям без данных любое число, например 0. NaN недействителен, поскольку он распространяется при вычислениях.
  3. Примените фильтр линейного сглаживания к изображению, умноженному на маску.
  4. Примените фильтр линейного сглаживания к маске.
  5. Разделите два результата.

По сути, мы нормализуем результат фильтра линейного сглаживания (свертки) по количеству пикселей с данными в окне фильтра.

В областях, где сглаженная маска равна 0 (далеко от данных), мы будем делить 0 на 0, поэтому там нужно соблюдать особую осторожность.

Обратите внимание, что нормализованная свертка может использоваться также для сомнительных данных, когда изображение маски получает значения в диапазоне от 0 до 1, что указывает на нашу уверенность в каждом пикселе. Например, пиксели, считающиеся зашумленными, могут иметь значение ближе к 0, чем другие пиксели.


Приведенный выше рецепт действителен только для линейных сглаживающих фильтров. Нормализованная свертка может быть выполнена с другими линейными фильтрами, например фильтрами производных, но в результате получается другой рецепт. См., например, здесь уравнение для нормализованной свертки для вычисления производной.


Для нелинейных фильтров необходимы другие подходы. Фильтры нелинейного сглаживания, например, часто не затрагивают края, поэтому они будут хорошо работать с изображениями с отсутствующими данными, если отсутствующие пиксели установлены на 0 или какое-либо значение далеко за пределами диапазона данных. Концепция сохранения изображения маски, которое указывает, какие пиксели имеют данные, а какие нет, всегда является хорошей идеей.

Спасибо за ваш ответ, я думаю, что пробовал что-то похожее на то, что вы предлагаете, но у меня все еще проблема с краями, вы можете прочитать отредактированную часть моего исходного сообщения, основанную на вашем ответе.

Reut 13.12.2020 10:02

@Reut: медианный фильтр не является линейным фильтром, это не свертка. Средний фильтр является линейным. Фильтр сглаживания Гаусса является линейным. Какую проблему ты пытаешься решить? Убрать спекл-шум? Вы пробовали двусторонний фильтр с маленькой тональной сигмой и маленькой пространственной сигмой? Вы можете установить пиксели без выборки на 200 и просто запустить фильтр.

Cris Luengo 13.12.2020 15:54

спасибо за ваш ответ, я попробую двусторонний фильтр. так как я новичок в этом хочу спросить - почему в данной ситуации работают только линейные фильтры?

Reut 16.12.2020 11:50

@Reut: Потому что иначе математика не работает. Линейный сглаживающий фильтр представляет собой средневзвешенное значение. Нормализованная свертка изменила веса, используемые при усреднении, чтобы они были равны нулю для пикселей, не входящих в маску.

Cris Luengo 16.12.2020 15:51

Другие вопросы по теме