ImageMagick: пользовательский фильтр ранга?Как эрозия или расширение или медиана, но другого ранга, например, процентильный фильтр? - PullRequest
1 голос
/ 07 апреля 2019

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

Можно ли взять пользовательский ранг значений окружающих пикселей? Например, при использовании квадрата 5x5 с фильтрами erode или dilate или median берется соответственно самое низкое, максимальное среднее значение из 25 пикселей, окружающих каждый пиксель. Например, я ищу способ взять 8-е или 23-е значение.

Возможно, это можно выразить как процентиль, например, возьмите 20% процентиль произвольной области, окружающей каждый пиксель. Что в случае квадрата 7x7 будет 0,2 * 7 * 7 = 9-е значение из общего числа 49 в порядке.

Фильтры erode, dilate и median будут соответствовать процентилям 0%, 100% и 50% соответственно.

1 Ответ

2 голосов
/ 07 апреля 2019

Я не могу придумать способ сделать это легко в ImageMagick - кроме компиляции в вашем "модуле процесса" . Лучшее введение в это - snibgo и фактически для Windows - см. sortpixels.c пример здесь


Одним из инструментов, который может сделать это просто из командной строки, является libvips с его функцией im_rank().

Итак, если вам нужен индекс 8 из отсортированного списка соседей 5x5, вы можете сделать:

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')

Вы можете изменить размер / форму фильтра, скажем, 5x5, изменив эту строку:

result = generic_filter(im, modal, (5, 5))

И как таковой, он займет третьего наименьшего соседа, так как отсчет начинается с 0. Итак, используйте N=0, если вы хотите минимум в окрестности 3x3, или N=8, если вы хотите максимум в 3x3 окрестности.


Другим вариантом может быть использование CImg , который представляет собой простую в использовании библиотеку C ++ только для заголовков (без файлов DLL / libXXX.a / libXXX.so), которая может фактически читать и записывать PGM файлы изначально без необходимости внешнего. Таким образом, вы можете запустить команду ImageMagick и заставить ее записать PGM-файл в stdout и прочитать его при использовании CImg , обработать его и снова записать отфильтрованный. Вероятно, это было бы проще, чем написать ImageMagick «модуль процесса» , и вам не нужно будет собирать ImageMagick из исходного кода заново для каждого выпуска.

Ключевые слова : ImageMagick, vips, libvips, фильтр, ранг, ранжирование, медиана, расширение, разрушение, окно, 3x3, 5x5, NxN, процентиль, Python, PIL, Pillow, изображение, обработка изображений.

...