ImageMagick: пользовательский фильтр ранга? Например, размывание, расширение или медиана, но другого ранга, например, фильтр «процентиль»?

#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, подушка, изображение, обработка изображений.