#filter #imagemagick #pixel #rank #median
#Фильтр #imagemagick #пиксельный #ранг #медиана
Вопрос:
При применении рангового фильтра с помощью ImageMagick, такого как erode, delate или median, он принимает минимальное ( erode
), максимальное ( dilate
) или среднее ( median
) значение всех пикселей в пределах определенного радиуса или пользовательской формы вокруг каждого исходного пикселя.
Возможно ли также получить пользовательский ранг окружающих значений пикселей? Например, при использовании квадрата 5×5 с помощью фильтров erode
или dilate
или median
, соответственно, берется наименьшее, наибольшее или среднее значение из 25 пикселей, окружающих каждый пиксель. То, что я ищу, — это способ взять, например, 8-е или 23-е значение.
Возможно, это можно было бы выразить в виде процентиля, например, взять 20%-ное значение процентиля произвольной области, окружающей каждый пиксель. Который в случае квадрата 7×7 был бы 0.2*7*7 = 9-е значение из общего числа 49 по порядку.
erode
, dilate
и median
фильтры будут соответствовать процентилям 0%, 100% и 50% соответственно.
Комментарии:
1. Я обновил свой ответ, если вы хотите взглянуть еще раз.
Ответ №1:
Я не могу придумать способ легко сделать это в ImageMagick — кроме компиляции в вашем собственном «модуле процесса». Лучшее введение в это от snibgo
и фактически для Windows — смотрите sortpixels.c
пример здесь
Одним из инструментов, который может сделать это просто из командной строки, является libvips со своей im_rank()
функцией.
Итак, если вам нужен индекс 8 из отсортированного списка соседей 5×5, вы могли бы сделать:
vips im_rank input.png result.png 5 5 8
Я провел быстрый тест, сгенерировав случайное изображение с помощью ImageMagick и выбрав последовательно большие значения для index
, и выходные изображения последовательно становились ярче — но это был итог моего тестирования. У меня нет оснований полагать, что это не сработает — это отличная библиотека, очень быстрая и экономичная.
Если вы можете работать с Python, вы можете сделать это:
#!/usr/bin/env python3
import numpy as np
from PIL import Image
from scipy.ndimage import generic_filter
from scipy import stats
# Modal filter
def modal(P):
"""
We receive P[0]..P[8] with the pixels in the 3x3 surrounding window
Sort neighbours and take N'th in list
"""
N = 3
P.sort()
return P[N]
# Open image and make into Numpy array
im = Image.open('image.png').convert('L')
im = np.array(im)
# Run modal filter, change filter size here
result = generic_filter(im, modal, (3, 3))
# Save result
Image.fromarray(result).save('result.png')
Вы можете изменить размер / форму фильтра, скажем, на 5×5, изменив эту строку:
result = generic_filter(im, modal, (5, 5))
И как бы то ни было, он займет третье наименьшее соседнее значение, поскольку отсчет начинается с 0. Итак, используйте, N=0
если вам нужен минимум в районе 3×3 или N=8
если вам нужен максимум в районе 3×3.
Другим вариантом может быть использование CImg, который является простой в использовании библиотекой C только для заголовков (без файлов DLL / libXXX.a / libXXX.so), которая фактически может читать и записывать файлы PGM изначально, не требуя ничего внешнего. Таким образом, вы могли бы запустить команду ImageMagick и заставить ее записать файл PGM в stdout
и прочитать его с помощью CImg, обработать его и записать снова отфильтрованным. Вероятно, это было бы проще, чем написать ImageMagick «модуль процесса», и вам не нужно было бы создавать ImageMagick из исходного кода заново для каждого выпуска.
Ключевые слова: ImageMagick, vips, libvips, фильтр, ранг, ранжирование, медиана, расширение, размывание, окно, 3×3, 5×5, NxN, процентиль, Python, PIL, подушка, изображение, обработка изображений.