在数据科学和科学计算领域,NumPy库因其在线性代数、傅里叶变换、矩阵运算等方面的应用而广受欢迎。它同样在图像处理领域扮演着重要角色,尤其是在数据科学领域。NumPy数组相较于Python列表在速度上有显著优势。
可能已经听说过一些图像处理库,如OpenCV、Python图像库(PIL)、Scikit-Image等。如果想了解更多关于Python图像处理库的信息,请务必查看相关文章。
对于更多与机器学习和Python相关的文章,请点击。
可能想知道NumPy也用于图像处理。基本原理是知道图像由NumPy的ndarray构成。因此,可以操作这些数组并处理图像。希望这篇博客能为提供关于NumPy在图像处理中的广泛应用的概览。
在Anaconda Prompt中输入以下命令,所有所需库将被安装。
pip install numpy
pip install matplotlib
pip install Pillow
将使用numpy、matplotlib和Python图像库(PIL)进行进一步分析。
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image, ImageOps
使用PIL Image模块中的open()方法打开图像。同样,可以使用matplotlib库读取和显示图像。它使用image模块处理图像,并提供两个有用的方法:imread()和imshow()。
img = np.array(Image.open('emma_stone.jpg'))
plt.figure(figsize=(8,8))
plt.imshow(img)
plt.show()
在本分析中,使用imshow()方法显示图像。
在本节中,将查看图像的维度、形状和数据类型。要检查图像的大小,使用Image.size属性。
print('# of dims: ',img.ndim) # 图像的维度
print('Img shape: ',img.shape) # 图像的形状
print('Dtype: ',img.dtype)
print(img[20, 20]) # [R, G, B]通道的像素值
print(img[:, :, 2].min()) # 通道B的最小像素值
输出结果将显示图像的维度、形状、数据类型以及特定像素值和通道的最小像素值。
要将ndarray保存为图像,使用Image.save()方法。
path = 'emma.jpg'
pil_img = Image.fromarray(img)
pil_img.save(path)
将从零开始旋转图像,而不使用PIL库。如果想使用PIL旋转图像,则可以使用Image.rotate()方法。
degrees = 90
img = np.array(Image.open('emma_stone.jpg'))
# img = img.sum(2) / (255*3) # 转换为灰度图像
fig = plt.figure(figsize=(10, 10))
fig.add_subplot(1, 2, 1)
plt.imshow(img)
plt.title("original")
img0 = img.copy()
for _ in range(degrees // 90):
img0 = img0.transpose(1, 0, 2)
for j in range(0, img0.shape[1] // 2):
c = img0[:, j, :].copy()
img0[:, j, :] = img0[:, img0.shape[1]-j-1, :]
img0[:, img0.shape[1]-j-1, :] = c
fig.add_subplot(1, 2, 2)
plt.imshow(img0)
plt.title("rotated")
以上代码将图像逆时针旋转90度。
将彩色图像转换为负片图像非常简单。只需要对图像的每个像素执行3个步骤。首先,获取像素的RGB值;然后,使用R = 255 – R, G = 255 – G, B = 255- B计算新的RGB值;最后,将新的RGB值保存在像素中。
fig = plt.figure(figsize=(10, 10))
img_grey = 255*3 - img_grey # 255 * 3因为之前沿通道轴进行了加法
fig.add_subplot(1, 2, 1)
plt.imshow(img_grey)
plt.title('Negative of Grey image')
img = 255 - img
fig.add_subplot(1, 2, 2)
plt.imshow(img)
plt.title('Negative of RGB image')
要向图像周围添加黑色填充,可以使用以下代码:
img = np.array(Image.open('emma_stone.jpg'))
img_grey = img.sum(2) / (255*3)
img0 = img_grey.copy()
img0 = np.pad(img0, ((100,100),(100,100)), mode='constant')
plt.imshow(img0)
要将图像分割成每种RGB颜色,可以使用以下代码:
img = np.array(Image.open('emma_stone.jpg'))
img_R, img_G, img_B = img.copy(), img.copy(), img.copy()
img_R[:, :, (1, 2)] = 0
img_G[:, :, (0, 2)] = 0
img_B[:, :, (0, 1)] = 0
img_rgb = np.concatenate((img_R,img_G,img_B), axis=1)
plt.figure(figsize=(15, 15))
plt.imshow(img_rgb)
可以根据需要减少颜色强度。查看以下代码以减少颜色。
img = np.array(Image.open('emma_stone.jpg'))
# 通过先除以//得到整数,然后乘以相同的因子使像素值离散
img_0 = (img // 64) * 64
img_1 = (img // 128) * 128
img_all = np.concatenate((img, img_0, img_1), axis=1)
plt.figure(figsize=(15, 15))
plt.imshow(img_all)
可以使用NumPy中的数组切片来修剪图像。查看以下代码以使用Python修剪图像。
img = np.array(Image.open('emma_stone.jpg'))
fig = plt.figure(figsize=(10, 10))
fig.add_subplot(1, 2, 1)
plt.imshow(img)
plt.title('Original')
img0 = img[128:-128, 128:-128, :]
fig.add_subplot(1, 2, 2)
plt.imshow(img0)
plt.title('Trimmed')
可以将图像的一部分粘贴到另一张图像上。查看以下Python代码以将图像的一部分粘贴到另一张图像上。
src = np.array(Image.open('emma_stone.jpg').resize((128, 128)))
dst = np.array(Image.open('emma_stone.jpg').resize((256, 256))) // 4
dst_copy = dst.copy()
dst_copy[64:128, 128:192] = src[32:96, 32:96]
fig = plt.figure(figsize=(10, 10))
fig.add_subplot(1, 2, 1)
plt.imshow(src)
plt.title('Original')
fig.add_subplot(1, 2, 2)
plt.imshow(dst_copy)
plt.title('Pasted with slice')
还可以使用NumPy对图像进行二值化。查看以下代码以对图像进行二值化。
img = np.array(Image.open('emma_stone.jpg'))
img_64 = (img > 64) * 255
img_128 = (img > 128) * 255
fig = plt.figure(figsize=(15, 15))
img_all = np.concatenate((img, img_64, img_128), axis=1)
plt.imshow(img_all)
查看以下代码以翻转图像。
img0 = img.copy()
for i in range(img0.shape[0] // 2):
c = img0[i, :, :].copy()
img0[i, :, :] = img0[img0.shape[0] - i - 1, :, :]
img0[img0.shape[0] - i - 1, :, :] = c
plt.imshow(img0)
np.flipud():[上/下]翻转x轴;np.fliplr():[左/右]翻转y轴。查看以下代码以翻转图像:
img = np.array(Image.open('emma_stone.jpg'))
fig = plt.figure(figsize=(10, 10))
fig.add_subplot(1, 2, 1)
plt.imshow(np.flipud(img))
fig.add_subplot(1, 2, 2)
plt.imshow(np.fliplr(img))
img = np.array(Image.open('emma_stone.jpg'))
img0 = np.array(Image.open('mountains.jpg').resize(img.shape[1::-1])) # resize接受两个参数(WIDTH, HEIGHT)
print(img.dtype)
# uint8
dst = (img * 0.6 + img0 * 0.4).astype(np.uint8) # 混合它们
plt.figure(figsize=(10, 10))
plt.imshow(dst)
img = np.array(Image.open('emma_stone.jpg'))
ones = np.ones((img.shape[0] // 2, img.shape[1] // 2, 3))
zeros = np.zeros(((img.shape[0] // 4, img.shape[1] // 4, 3))
zeros_mid = np.zeros(((img.shape[0] // 2, img.shape[1] // 4, 3)))
up = np.concatenate((zeros, zeros, zeros, zeros), axis=1)
middle = np.concatenate((zeros_mid, ones, zeros_mid), axis=1)
down = np.concatenate((zeros, zeros, zeros, zeros), axis=1)
mask = np.concatenate((up, middle, down), axis=0)
mask = mask / 255
img0 = mask * img
fig = plt.figure(figsize=(10, 10))
fig.add_subplot(1, 2, 1)
plt.imshow(img)
fig.add_subplot(1, 2, 2)
plt.imshow(img0)
img = np.array(Image.open('emma_stone.jpg'))
img_flat = img.flatten()
plt.hist(img_flat, bins=200, range=[0, 256])
plt.title("Number of pixels in each intensity value")
plt.xlabel("Intensity")
plt.ylabel("Number of pixels")
plt.show()