使用NumPy进行图像处理

数据科学和科学计算领域,NumPy库因其在线性代数、傅里叶变换、矩阵运算等方面的应用而广受欢迎。它同样在图像处理领域扮演着重要角色,尤其是在数据科学领域。NumPy数组相较于Python列表在速度上有显著优势。

可能已经听说过一些图像处理库,如OpenCV、Python图像库(PIL)、Scikit-Image等。如果想了解更多关于Python图像处理库的信息,请务必查看相关文章。

2021年顶级Python图像处理

对于更多与机器学习和Python相关的文章,请点击。

可能想知道NumPy也用于图像处理。基本原理是知道图像由NumPy的ndarray构成。因此,可以操作这些数组并处理图像。希望这篇博客能为提供关于NumPy在图像处理中的广泛应用的概览。

目录

  • 引言
  • 所需库的安装
  • 导入所需库
  • 打开图像
  • 图像细节
  • 图像的负片
  • 填充黑色空间
  • 可视化RGB通道
  • 颜色减少
  • 修剪图像
  • 使用切片粘贴图像
  • 二值化图像
  • 翻转图像
  • 另一种翻转图像的方法
  • 混合两张图像
  • 遮罩图像
  • 像素强度直方图
  • 结论

所需库的安装

在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保存为图像

要将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通道

要将图像分割成每种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()
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485