我正在使用sci-kit图像中的平均过滤器。但是,它似乎将浮点图像的dtype
更改为uint8
,这再次将其传递给其他过滤器功能时会导致问题。
作为插图,请考虑以下代码。
import numpy as np
from skimage import filters
from skimage.morphology import square
def mean_filter(img):
selem = square(3)
print(img.dtype)
print(img.max(), img.min())
fi = filters.rank.mean(img, selem=selem)
print(fi.dtype)
print(fi.max(), fi.min())
return fi
arr = np.array([[.1, .2, .3],
[.4, .5, .6],
[.7, .8, .9]], dtype='float64')
m = mean_filter(arr)
给出以下输出。
float64
0.9 0.1
uint8
178 76
但是,根据文档,返回类型应与输入类型相同。这里发生了什么?
Scikit-Image的rank
过滤器仅针对uint8
和uint16
数据类型定义。这就是为什么它将转换为uint8
的原因,即您获得结果的类型。例如。文档等级。表示:
图像:2-D数组(UINT8,UINT16)
因此,如果您输入uint8
或uint16
,则会在结果中保留该数据类型。否则,它将尝试将您的图像转换为引擎盖下的一个。
您可以做的是使用scipy
:
>>> from scipy.ndimage import uniform_filter
>>> size = 3
>>> result = uniform_filter(arr, size)
或者如果您喜欢创建自己的过滤器:
>>> from scipy.ndimage import convolve1d
>>> size = 3
>>> kernel = np.ones(size, arr.dtype) / size
>>> result = convolve1d(convolve1d(arr, kernel, axis=0), kernel, axis=1)
注意:以上称为可分离卷积。它通过将图像与两个一维过滤器进行卷积,首先在y
轴上,然后在x
轴上(顺序无关紧要)。尽管它看起来很丑陋(因为您必须两次卷动图像),但是当您的内核(过滤器)是可分离的时,运行两个一维卷积的数量级比运行单个2D卷积快。Scipy的uniform_filter
在场景后面做到这一点。它每轴一次调用uniform_filter1d
。