scikit-image 是用于图像处理的 Python 包,使用原生的 NumPy 数组作为图像对象。
本实验译自官方文档 与 这篇笔记
无需密码自动登录,系统用户名shiyanlou
本课程实验环境使用Spyder。首先打开terminal,然后输入以下命令:
spyder -w scientific-python-lectures (-w 参数指定工作目录)
关于Spyder的使用可参考文档:https://pythonhosted.org/spyder/
本实验基本在控制台下进行,可关闭 spyder 中的其余窗口,只保留控制台。如需要调出窗口,可以通过 view->windows and toolbar 调出。比如希望在py文件中编写代码,可以 view->windows and toolbar->Editor 调出编辑器窗口。
模块:skimage.io
from skimage import io
读取图像文件(注:读取与保存都是使用外部图形插件,比如 PIL)
filename = os.path.join(skimage.data_dir, 'camera.png')
camera = io.imread(filename)
还可以从 URL 路径读取图片
logo = io.imread('http://labfile.oss.aliyuncs.com/courses/370/ascii_dora.png')
保存文件
io.imsave('local_logo.png', logo)
图像数组的数据类型可以是整型或者浮点型的。
要小心处理整型数据溢出的情况
camera = data.camera()
camera.dtype
输出:
dtype('uint8')
输入:
camera_multiply = 3 * camera # 溢出
整型8,16,32位,signed,unsigned都有可能,图片处理前建议先检查数据类型。
浮点型的范围是 [-1, 1],scikit-image 的一些图像处理的例程处理的是浮点化的图像,所以可能导致输入是整型数组,输出是浮点数组。
from skimage import filter
camera_sobel = filter.sobel(camera)
camera_sobel.max()
输出:
0.8365106670670005
skimage.util 模组帮助进行数据类型的转换,转换函数有 util.img_as_float
、util.img_as_ubyte
等。
彩色图形的形状可能是(N,M,3)或者(N,M,4)(4是因为可能多了一个 alpha 透明值)
lena = data.lena()
lena.shape
输出:
(512, 512, 3)
skimage.color模块中 color.rgb2hsv
与 color.lab2rgb
可以完成颜色空间的转换。
因为我们是用 numpy 数组来表现图片,不同于一般笛卡尔坐标的(x,y),我们使用(row,col)进行定位。彩色图片或者其它多通道图片还会多一个坐标维度 ch
。如果是 3d 图片的情况,会多一个平面坐标维度,记作 pln
或者 p
。
具体见下表
图像类型 | 坐标 |
---|---|
2D 灰度图 | (row, col) |
2D 多通道图 (比如RGB) | (row, col, ch) |
3D 灰度图 | (pln, row, col) |
3D 多通道图 | (pln, row, col, ch) |
scikit-image 支持几种基础的几何变换:相似,仿射,投射 与 多项式变换
这里举一个相似变换的例子:
import math
import skimage.transform as tf
text = data.text()
tform = tf.SimilarityTransform(scale=1, rotation=math.pi / 4,
translation=(text.shape[0] / 2, -100))
rotated = tf.warp(text, tform)
back_rotated = tf.warp(rotated, tform.inverse)
fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, figsize=(8, 3))
plt.gray()
ax1.imshow(text)
ax1.axis('off')
ax2.imshow(rotated)
ax2.axis('off')
ax3.imshow(back_rotated)
ax3.axis('off')
局部过滤对像素操作依据其相邻像素。
提取轮廓的例子:
from skimage import data, filter
import matplotlib.pyplot as plt
text = data.text()
hsobel_text = filter.hsobel(text)
plt.figure(figsize=(12, 3))
plt.subplot(121)
plt.imshow(text, cmap='gray', interpolation='nearest')
plt.axis('off')
plt.subplot(122)
plt.imshow(hsobel_text, cmap='jet', interpolation='nearest')
plt.axis('off')
plt.tight_layout()
plt.show()
非局部过滤对像素操作依据图像上的大块像素(或是所有像素)
增强对比度的例子:
from skimage import data, exposure
import matplotlib.pyplot as plt
camera = data.camera()
camera_equalized = exposure.equalize(camera)
plt.figure(figsize=(7, 3))
plt.subplot(121)
plt.imshow(camera, cmap='gray', interpolation='nearest')
plt.axis('off')
plt.subplot(122)
plt.imshow(camera_equalized, cmap='gray', interpolation='nearest')
plt.axis('off')
plt.tight_layout()
plt.show()
图像分割(Segmentation)指的是将数字图像细分为多个图像子区域(像素的集合)(也被称作超像素)的过程。图像分割的目的是简化或改变图像的表示形式,使得图像更容易理解和分析。图像分割通常用于定位图像中的物体和边界(线,曲线等)。更精确的,图像分割是对图像中的每个像素加标签的一个过程,这一过程使得具有相同标签的像素具有某种共同视觉特性。
otsu 阀值法是一个简单的启发式方法可以区分出图像的前景和背景
from skimage import data
from skimage import filter
camera = data.camera()
val = filter.threshold_otsu(camera)
mask = camera < val
io.imshow(mask)
对图像连通的部分加标签
n = 20
l = 256
im = np.zeros((l, l))
points = l*np.random.random((2, n**2))
im[(points[0]).astype(np.int), (points[1]).astype(np.int)] = 1
im = ndimage.gaussian_filter(im, sigma=l/(4.*n))
blobs = im > im.mean()
#对连通的部分加标签
all_labels = morphology.label(blobs)
#去掉背景的部分,不为背景加标签
blobs_labels = morphology.label(blobs, background=0)
特征提取有以下作用:
使用 Harris 角点检测检测角点的例子。
from skimage import data
from skimage.feature import corner_harris, corner_subpix, corner_peaks
from skimage.transform import warp, AffineTransform
tform = AffineTransform(scale=(1.3, 1.1), rotation=1, shear=0.7,
translation=(210, 50))
image = warp(data.checkerboard(), tform.inverse, output_shape=(350, 350))
coords = corner_peaks(corner_harris(image), min_distance=5)
coords_subpix = corner_subpix(image, coords, window_size=13)
plt.gray()
plt.imshow(image, interpolation='nearest')
plt.plot(coords_subpix[:, 1], coords_subpix[:, 0], '+r', markersize=15, mew=5)
plt.plot(coords[:, 1], coords[:, 0], '.b', markersize=7)
plt.axis('off')
plt.show()
本作品在 知识共享协议 3.0 下授权发布