ImageMagick:自定义排名过滤器?像侵蚀或扩张或中位数但等级不同,例如'percentile' 过滤器?

ImageMagick: custom rank filter? Like erode or dilate or median but a different rank, e.g. a 'percentile' filter?

当使用 ImageMagick 应用等级过滤器时,例如侵蚀或延迟或中值,它采用最小 (erode) 或最大 (dilate) 或中间 (median) 值每个源像素周围特定半径或自定义形状内的所有像素。

是否也可以对周围的像素值进行自定义排名?例如,当使用 5x5 正方形时,使用 erodedilatemedian 过滤器,分别采用每个像素周围 25 个像素的最低值、最高值和中间值。例如,我正在寻找一种获取第 8 个或第 23 个值的方法。

也许这可以表示为百分位数,例如取每个像素周围任意区域的 20% 百分位值。如果是 7x7 正方形,则 0.2*7*7 = 总共 49 个中的第 9 个值。

erodedilatemedian 过滤器分别对应于 0%、100% 和 50% 的百分位数。

我想不出在 ImageMagick 中轻松做到这一点的方法 - 除了自己编译 "process module".最好的介绍是 snibgo,实际上是 Windows - 请参阅 sortpixels.c 示例 here


一个可以简单地从命令行执行此操作的工具是 libvips 及其 im_rank() 功能。

所以,如果你想从 5x5 邻居的排序列表中找到索引 8,你可以这样做:

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

您可以通过更改此行将过滤器 size/shape 更改为 5x5:

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

实际上,它将采用第三小的邻居,因为从 0 开始计数。因此,如果您想要 3x3 邻域中的最小值,请使用 N=0,或者如果您需要 N=8想要 3x3 邻域中的最大值。


另一种选择可能是使用 CImg,它是一个易于使用、仅包含头文件的 C++ 库(没有 DLLs/libXXX.a/libXXX.so 文件),它实际上可以本地读取和写入 PGM 文件,无需任何外部操作。所以你可以 运行 一个 ImageMagick 命令并让它在 stdout 上写一个 PGM 文件并使用 CImg[=53= 读取它],对其进行处理并再次过滤后写出。这可能比编写 ImageMagick "process module" 更容易,而且您不需要构建 ImageMagick 每次发布都从源头重新获取。

关键词: ImageMagick, vips, libvips, filter, rank, ranking, median, dilate, erode, window, 3x3, 5x5, NxN, percentile, Python, PIL, Pillow, 图像, 图像处理。