初学者指南: 使用NumPy数组进行图像处理
由于图像也可以被视为由数组组成,因此我们也可以使用NumPy执行不同的图像处理任务。在本文中,我们将了解使用 NumPy 执行的图像处理任务。
大多数情况下,我们在需要对不同大小的数组执行数学和逻辑运算,这时候使用NumPy会事半功倍。由于图像也可以被视为由数组组成,因此我们使用NumPy的数组功能进行不同的图像处理。本文将有助于初学者从最基本的方面了解图像处理。本文作为 <<神经网络的数学基础:张量运算>>的拓展,有意系统学习人工智能编程的同学,可以参考一下,加深对基本概念和数组的理解。
我们从导入库和加载随机图像开始。本文使用PyCharm作为代码编写测试的IDE工具。
1、加载图像
随便找一张图片,从加载图片开始。
import matplotlib.pylab as plt
image = plt.imread("src/pics-old/guv0.png")
plt.imshow(image)
# 依次表示数组的维度,形状,数组本身
print(image.ndim, image.shape, image)
plt.show()
输出如下,
注意:不同的图片格式,数组内容可能会不一样,我加载的这张图片,数据是0255的值:
3 (768, 1280, 3) [[[0.9882353 0.09411765 0.3764706 ]
[0.9882353 0.09411765 0.3764706 ]
[0.9882353 0.09411765 0.3764706 ]
…
[0.30588236 0.99607843 0.3254902 ]
[0.30980393 0.99607843 0.32941177]
[0.3137255 0.99607843 0.33333334]]]
2、裁剪图像
加载图像后,我们可以对图像执行基本的裁剪操作。对于 NumPy,可以通过数组的切片操作来执行裁剪操作。
import matplotlib.pylab as plt
image = plt.imread("src/pics-old/guv0.png")
# 只是一个:表示这个维度保持不变,410: 表示从0~1280这个轴的index=410 处切一刀
crop_img = image[:, 410:, :]
print(image.shape, crop_img.shape)
plt.imshow(crop_img)
plt.show()
在这里,我们可以看到我们已经裁剪了图像。现在我们可以继续下一个图像处理步骤
3、分离颜色
因为我们知道每个图像都是由像素值组成的,这些像素值代表三个整数或小数,称为其颜色的 RGB 值。为了将这些颜色的图像分开,我们需要拉出图像数组的正确切片。
import numpy as np
import matplotlib.pylab as plt
image = plt.imread("src/pics-old/guv0.png")
# 使用plot创建一个1行3列的尺寸为(12,8)的绘图区,相当每个是6英寸宽,4英寸高。
fig, axs = plt.subplots(nrows=1, ncols=3, figsize=(12, 8))
for c, ax in zip(range(3), axs):
# 造一个与image数组一样结构,初始值为0的数组
# 如果你图片数据值是0~255,类型设为unit8,如果是0~1,设置为float64
rgb_img = np.zeros(image.shape, dtype="float64")
# 读取image某一通道的值
# RGB只拷贝C位,按循环依次取值为0,1,2
rgb_img[:, :, c] = image[:, :, c]
ax.imshow(rgb_img)
ax.set_axis_off()
plt.show()
在输出中,我们可以看到我们已经分离了图像的 RGB,让我们进入图像处理的下一步
4、转换
在此步骤中,我们将执行颜色转换。为此,我们可以将图像像素视为空间中的一个点。以这种方式处理图像像素使我们能够对色点进行转换。旋转色点可以是上述语句的一个例子。在这里,我们应用了 Numpy 的爱因斯坦符号函数,这是一种将旋转矩阵逐像素应用于图像的方法。
import numpy as np
import matplotlib.pylab as plt
def rotation_matrix(theta):
return np.c_[
[1, 0, 0],
[0, np.cos(theta), -np.sin(theta)],
[0, np.sin(theta), np.cos(theta)]
]
image = plt.imread("src/pics-old/guv0.png")
img_rot = np.einsum("ijk,lk->ijl", image, rotation_matrix(np.pi))
plt.imshow(img_rot)
plt.show()
在输出中,我们可以看到将 sigmoid 应用于颜色空间是有效的,并且我们正在连续应用像素颜色的旋转。现在在下一步中,我们将看看如何将图像转换为灰度图像
5、灰度转换
我们还可以使用 NumPy 将图像转换为灰度图像。通过取图像RGB值的加权平均值,我们可以执行此操作。
import numpy as np
import matplotlib.pylab as plt
image = plt.imread("src/pics-old/guv0.png")
rgb_weights = [0.2989, 0.5870, 0.1140]
grayscale_image = np.dot(image[..., :3], rgb_weights)
plt.imshow(grayscale_image)
plt.show()
这是我们灰度转换过程输出的图像。让我们继续下一步的图像处理
6、图像分割
这是我们分割图像不同区域的最常用的图像处理步骤之一。有多种方法可以做到这一点,例如前景和背景。例如,在本文中,我们将了解如何通过将图像转换为灰度并找到阈值来执行分割。图像中高于阈值的像素位于一个区域中,而其他像素位于另一个区域中
import numpy as np
import matplotlib.pylab as plt
image = plt.imread("src/pics-old/guv0.png")
image = image*255
def simple_threshold(img, threshold=128):
return ((img > threshold) * 255).astype("uint8")
thresholds = [100, 120, 128, 138, 150]
fig, axs = plt.subplots(nrows=1, ncols=len(thresholds), figsize=(20, 5))
rgb_weights = [0.2989, 0.5870, 0.1140]
gray_im = np.dot(image[..., :3], rgb_weights)
# gray_im = to_grayscale(image)
for t, ax in zip(thresholds, axs):
ax.imshow(simple_threshold(gray_im, t), cmap='Greys')
ax.set_title("Threshold: {}".format(t), fontsize=20)
ax.set_axis_off()
plt.show()
输出:
在上面的输出中,我们可以看到我们使用不同的阈值将图像分割成两个区域
结语
在本文中,我们讨论了使用 NumPy 库执行的图像处理的不同任务。此外,我们还使用 matplotlib 库在处理后对图像进行可视化。通过查看上述几点,我们可以说,我们也可以通过使用其他一些逻辑来执行其他任务