非常教程

Scikit image参考手册

指南 | Guide

Image data types and what they mean

skimage,图像是简单的numpy数组,支持各种数据类型[1], “dtypes”。为了避免扭曲图像强度(请参阅调整强度值),我们假设图像使用以下dtype范围:

数据类型

范围

UINT8

0到255

UINT16

0至65535

UINT32

0至232

浮动

-1到1或0到1

INT8

-128至127

INT16

-32768至32767

INT32

-231至231-1

请注意,即使数据类型本身可能超过此范围,浮动图像也应限制在-1到1的范围内; 另一方面,所有的整型数据都具有可以跨越整个数据类型范围的像素强度。除少数例外,不支持64位(u)int图像

函数skimage的设计使它们可以接受任何这些dtype,但为了提高效率,可能会返回不同 dtype 的图像(请参见输出类型)。如果您需要特定的dtype,则skimage提供实用程序函数,用于转换dtypes并适当重新调整图像强度(请参阅输入类型)。你不应该在图像上使用 astype,因为它违反了有关dtype范围的这些假设:

>>> from skimage import img_as_float
>>> image = np.arange(0, 50, 10, dtype=np.uint8)
>>> print(image.astype(np.float)) # These float values are out of range.
[  0.  10.  20.  30.  40.]
>>> print(img_as_float(image))
[ 0.          0.03921569  0.07843137  0.11764706  0.15686275]

输入类型

虽然我们旨在保留输入图像的数据范围和类型,但函数可能仅支持这些数据类型的一个子集。在这种情况下,输入将被转换为所需的类型(如果可能的话),并且如果需要存储器副本,则会向日志打印警告消息。类型要求应在文档中注明。

主包中的以下实用程序功能可供开发人员和用户使用:

函数名称

描述

img_as_float

转换为64位浮点。

img_as_ubyte

转换为8位uint。

img_as_uint

转换为16位uint。

img_as_int

转换为16位整数。

这些功能将图像转换为所需的dtype并正确重新调整其值。如果转换降低图像的精度,则会发出警告:

>>> from skimage import img_as_ubyte
>>> image = np.array([0, 0.5, 1], dtype=float)
>>> img_as_ubyte(image)
WARNING:dtype_converter:Possible precision loss when converting from
float64 to uint8
array([  0, 128, 255], dtype=uint8)

使用上下文管理器可以在本地忽略警告:

>>> import warnings
>>> image = np.array([0, 0.5, 1], dtype=float)
>>> with warnings.catch_warnings():
...     warnings.simplefilter("ignore")
...     img_as_ubyte(image)
array([  0, 128, 255], dtype=uint8)

此外,某些函数preserve_range在范围转换方便但不必要的地方使用参数。例如,插入transform.warp需要float类型的图像,其范围应该为0,1。因此,默认情况下,输入图像将重新缩放到此范围。但是,在某些情况下,图像值代表用户不希望重新缩放的物理测量结果,例如温度或降雨量值。与preserve_range=True,数据的原始范围将被保留,即使输出是浮动图像。然后用户必须确保这个非标准图像被下游功能正确处理,这可能期望0,1的图像。

>>> from skimage import data
>>> from skimage.transform import rescale
>>> image = data.coins()
>>> image.dtype, image.min(), image.max(), image.shape
(dtype('uint8'), 1, 252, (303, 384))
>>> rescaled = rescale(image, 0.5)
>>> (rescaled.dtype, np.round(rescaled.min(), 4),
...  np.round(rescaled.max(), 4), rescaled.shape)
(dtype('float64'), 0.0147, 0.9456, (152, 192))
>>> rescaled = rescale(image, 0.5, preserve_range=True)
>>> (rescaled.dtype, np.round(rescaled.min()),
...  np.round(rescaled.max()), rescaled.shape
(dtype('float64'), 4.0, 241.0, (152, 192))

输出类型

函数的输出类型由函数作者确定,并且为了用户的利益进行记录。虽然这要求用户明确地将输出转换为需要的格式,但它确保不会发生不必要的数据副本。

需要特定类型输出(例如,用于显示目的)的用户可以写出:

>>> from skimage import img_as_uint
>>> out = img_as_uint(sobel(image))
>>> plt.imshow(out)

使用OpenCV

您可能需要使用使用OpenCV创建的图像skimage,反之亦然。OpenCV图像数据可以在NumPy中(并且因此在scikit-image中)被访问(不复制)。OpenCV对彩色图像使用BGR(而不是scikit-image的RGB),默认情况下它的dtype为uint8(请参阅图像数据类型及其含义)。BGR代表蓝绿红。

将BGR转换为RGB,反之亦然

skimageOpenCV中的彩色图像有三个维度:宽度,高度和颜色。RGB和BGR使用相同的颜色空间,但颜色顺序相反。

请注意,scikit-image我们通常引用宽度和高度rowscolumns而不是宽度和高度(请参阅坐标约定)。

以下指令有效地反转颜色的顺序,使行和列不受影响。

>>> image = image[:, :, ::-1]

使用来自OpenCV的图像 skimage

如果cv_image是一个无符号字节数组,skimage默认情况下会理解它。如果你喜欢使用浮点图像,img_as_float()可以用来转换图像:

>>> from skimage import img_as_float
>>> image = img_as_float(any_opencv_image)

使用skimageOpenCV中的图像

反过来可以通过以下方式实现img_as_ubyte()

>>> from skimage import img_as_ubyte
>>> cv_image = img_as_ubyte(any_skimage_image)

图像处理管道

这种dtype行为允许你将任何skimage函数串起来,而不必担心图像dtype。在另一方面,如果你想使用需要特定的D型自定义函数,你应该叫的D型转换函数(在这里,func1func2skimage功能):

>>> from skimage import img_as_float
>>> image = img_as_float(func1(func2(image)))
>>> processed_image = custom_func(image)

更好的是,您可以在内部转换图像并使用简化的处理管道:

>>> def custom_func(image):
...     image = img_as_float(image)
...     # do something
...
>>> processed_image = custom_func(func1(func2(image)))

重新调整强度值

在可能的情况下,函数应该避免盲目地拉伸图像强度(例如,重新缩放浮动图像以使最小和最大强度为0和1),因为这会严重扭曲图像。例如,如果您在黑暗的图像中寻找明亮的标记,则可能存在没有标记存在的图像; 扩展其输入强度以跨越整个范围会使背景噪声看起来像标记。

然而,有时候,你的图像应该跨越整个强度范围,但是没有。例如,某些相机可以存储每像素10,12或14位深度的图像。如果这些图像以dint uint16的形式存储在一个数组中,则图像不会在整个强度范围内延伸,因此会显得比它应该更暗淡。要更正此问题,可以使用该rescale_intensity功能重新缩放图像,以便使用完整的dtype范围:

>>> from skimage import exposure
>>> image = exposure.rescale_intensity(img10bit, in_range=(0, 2**10 - 1))

这里,in_range参数被设置为10位图像的最大范围。默认情况下,rescale_intensity拉伸值in_range以匹配dtype的范围。rescale_intensity还接受字符串作为输入in_rangeout_range,所以上面的例子也可以被写为:

>>> image = exposure.rescale_intensity(img10bit, in_range='uint10')

请注意负值

人们经常使用带符号的dtypes表示图像,尽管它们只是操纵图像的正值(例如,在int8图像中仅使用0-127)。出于这个原因,转换函数仅在无符号dtype的整个范围上传播带符号dtype 的正值。换句话说,从signed变换为unsigned dtypes时,负值将被剪切为0。(在带符号的dtypes之间转换时保留负值。)要防止此剪切行为,应该事先重新调整图像的缩放比例:

>>> image = exposure.rescale_intensity(img_int32, out_range=(0, 2**31 - 1))
>>> img_uint8 = img_as_ubyte(image)

此行为是对称的:无符号dtype中的值分布在签名dtype的正范围上。

参考

1

http://docs.scipy.org/doc/numpy/user/basics.types.html

Scikit image

Scikit-image 是用于图像处理的 Python 包,使用原生的 NumPy 数组作为图像对象。

主页 http://scikit-image.org/
源码 https://github.com/scikit-image/scikit-image
发布版本 0.13.1