9. 图像调整:转换图像内容#
9.1. 颜色操作#
大多数用于操作颜色通道的函数位于子模块 skimage.color
中。
9.1.1. 颜色模型之间的转换#
彩色图像可以使用不同的 颜色空间 表示。最常见的颜色空间之一是 RGB 空间,其中图像具有红色、绿色和蓝色通道。但是,其他颜色模型被广泛使用,例如 HSV 颜色模型,其中色调、饱和度和亮度是独立的通道,或者用于印刷的 CMYK 模型。
skimage.color
提供实用程序函数,用于将图像转换为不同的颜色空间并从不同的颜色空间转换图像。整数类型数组可以通过转换操作转换为浮点类型
>>> # bright saturated red
>>> red_pixel_rgb = np.array([[[255, 0, 0]]], dtype=np.uint8)
>>> color.rgb2hsv(red_pixel_rgb)
array([[[ 0., 1., 1.]]])
>>> # darker saturated blue
>>> dark_blue_pixel_rgb = np.array([[[0, 0, 100]]], dtype=np.uint8)
>>> color.rgb2hsv(dark_blue_pixel_rgb)
array([[[ 0.66666667, 1. , 0.39215686]]])
>>> # less saturated pink
>>> pink_pixel_rgb = np.array([[[255, 100, 255]]], dtype=np.uint8)
>>> color.rgb2hsv(pink_pixel_rgb)
array([[[ 0.83333333, 0.60784314, 1. ]]])
9.1.2. 从 RGBA 到 RGB 的转换 - 通过 Alpha 混合移除 Alpha 通道#
通过使用背景对 RGBA 图像进行 Alpha 混合来将 RGBA 图像转换为 RGB 图像,可以使用 rgba2rgb()
实现
>>> import skimage as ski
>>> img_rgba = ski.data.logo()
>>> img_rgb = ski.color.rgba2rgb(img_rgba)
9.1.3. 颜色值和灰度值之间的转换#
将 RGB 图像转换为灰度图像可以使用 rgb2gray()
实现
>>> img = ski.data.astronaut()
>>> img_gray = ski.color.rgb2gray(img)
rgb2gray()
使用颜色通道的非均匀加权,因为人眼对不同颜色的敏感度不同。因此,这种加权确保从 RGB 到灰度级的 亮度保留
>>> red_pixel = np.array([[[255, 0, 0]]], dtype=np.uint8)
>>> ski.color.rgb2gray(red_pixel)
array([[ 0.2125]])
>>> green_pixel = np.array([[[0, 255, 0]]], dtype=np.uint8)
>>> ski.color.rgb2gray(green_pixel)
array([[ 0.7154]])
使用 gray2rgb()
将灰度图像转换为 RGB 只需将灰度值复制到三个颜色通道上。
9.1.4. 图像反转#
反转图像也称为互补图像。对于二值图像,True 值变为 False,反之亦然。对于灰度图像,像素值被替换为数据类型的最大值与实际值之间的差值。对于 RGB 图像,对每个通道执行相同的操作。此操作可以使用 skimage.util.invert()
实现
>>> import skimage as ski
>>> img = ski.data.camera()
>>> inverted_img = ski.util.invert(img)
9.1.5. 用标签绘制图像#
label2rgb()
可用于使用标签数组来对灰度图像叠加颜色,以对要使用相同颜色表示的区域进行编码。
9.2. 对比度和曝光度#
图像像素可以采用由图像的 dtype
决定的值(参见 图像数据类型及其含义),例如 uint8
图像的 0 到 255 或浮点图像的 [0, 1]
。但是,大多数图像要么具有更窄的值范围(由于对比度差),要么具有集中在可访问值子范围内的大多数像素值。 skimage.exposure
提供函数,这些函数可以将强度值分布在更大的范围内。
第一类方法计算强度的非线性函数,该函数与特定图像的像素值无关。此类方法通常用于校正已知的传感器非线性或受体(如人眼)的非线性。一个众所周知的例子是 伽马校正,在 adjust_gamma()
中实现。
其他方法根据图像的直方图重新分配像素值。像素值的直方图使用 skimage.exposure.histogram()
计算
>>> import numpy as np
>>> import skimage as ski
>>> image = np.array([[1, 3], [1, 1]])
>>> ski.exposure.histogram(image)
(array([3, 0, 1]), array([1, 2, 3]))
histogram()
返回每个值箱的像素数量以及箱的中心。因此,histogram()
的行为略微不同于 numpy.histogram()
,后者返回箱的边界。
最简单的对比度增强 rescale_intensity()
包括使用线性变换将像素值拉伸到整个允许范围内
>>> import skimage as ski
>>> text = ski.data.text()
>>> text.min(), text.max()
(10, 197)
>>> better_contrast = ski.exposure.rescale_intensity(text)
>>> better_contrast.min(), better_contrast.max()
(0, 255)
即使图像使用整个值范围,有时值范围的末端也几乎没有权重。在这种情况下,使用图像百分位数来剪切像素值会提高对比度(以损失一些信息为代价,因为一些像素在这种操作中会饱和)
>>> moon = ski.data.moon()
>>> v_min, v_max = np.percentile(moon, (0.2, 99.8))
>>> v_min, v_max
(10.0, 186.0)
>>> better_contrast = ski.exposure.rescale_intensity(moon, in_range=(v_min, v_max))
函数 equalize_hist()
将像素值的累积分布函数 (cdf) 映射到线性 cdf 上,确保值范围的所有部分都在图像中得到同等表示。结果,在对比度差的大区域中增强细节。作为进一步细化,直方图均衡可以在图像的子区域中使用 equalize_adapthist()
执行,以校正图像上的曝光梯度。请参见示例 直方图均衡。