|
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
引言
NumPy是Python中用于科学计算的核心库,它提供了高性能的多维数组对象以及用于处理这些数组的工具。在图像处理领域,NumPy扮演着至关重要的角色,因为图像本质上就是多维数组(矩阵)。例如,灰度图像可以表示为二维数组,而彩色图像(RGB)则可以表示为三维数组。掌握NumPy进行图像处理的基础操作,不仅能帮助你理解图像处理的底层原理,还能为你后续学习更高级的图像处理技术(如OpenCV、PIL等)打下坚实的基础。
本文将详细介绍NumPy在图像处理中的基础操作,包括图像的加载与显示、基本图像操作、颜色空间转换、图像滤波与增强、图像算术运算等内容,并通过大量实例和代码演示,帮助你快速提升图像处理技能。
NumPy基础
在开始图像处理之前,我们需要先了解NumPy的一些基础知识。
NumPy数组
NumPy的核心是ndarray对象,它是一个快速、灵活的大型数据集容器。我们可以使用NumPy来创建和操作这些数组。
- import numpy as np
- # 创建一维数组
- arr1 = np.array([1, 2, 3, 4, 5])
- print("一维数组:", arr1)
- # 创建二维数组
- arr2 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
- print("二维数组:\n", arr2)
- # 创建三维数组
- arr3 = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
- print("三维数组:\n", arr3)
- # 查看数组属性
- print("数组形状:", arr2.shape) # 输出: (3, 3)
- print("数组维度:", arr2.ndim) # 输出: 2
- print("数组元素类型:", arr2.dtype) # 输出: int64
复制代码
NumPy数组操作
NumPy提供了丰富的数组操作方法,这些方法在图像处理中非常有用。
- import numpy as np
- # 创建一个3x3的数组
- arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
- # 数组切片
- print("第一行:", arr[0, :]) # 输出: [1 2 3]
- print("第一列:", arr[:, 0]) # 输出: [1 4 7]
- # 数组变形
- reshaped_arr = arr.reshape(1, 9) # 将3x3数组变形为1x9数组
- print("变形后的数组:", reshaped_arr)
- # 数组转置
- transposed_arr = arr.T
- print("转置后的数组:\n", transposed_arr)
- # 数组计算
- print("数组元素求和:", np.sum(arr)) # 输出: 45
- print("数组元素平均值:", np.mean(arr)) # 输出: 5.0
- print("数组元素最大值:", np.max(arr)) # 输出: 9
- print("数组元素最小值:", np.min(arr)) # 输出: 1
复制代码
图像的加载与显示
在开始处理图像之前,我们需要学习如何加载和显示图像。虽然NumPy本身不提供图像I/O功能,但我们可以结合其他库(如PIL、matplotlib)来实现这一功能。
使用PIL加载图像
Python Imaging Library (PIL) 或其分支 Pillow 是Python中常用的图像处理库。我们可以使用PIL加载图像,然后将其转换为NumPy数组进行处理。
- import numpy as np
- from PIL import Image
- import matplotlib.pyplot as plt
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = Image.open(image_path)
- # 将PIL图像转换为NumPy数组
- img_array = np.array(img)
- # 显示图像信息
- print("图像形状:", img_array.shape)
- print("图像数据类型:", img_array.dtype)
- print("图像大小:", img.size)
- # 显示图像
- plt.imshow(img)
- plt.axis('off') # 不显示坐标轴
- plt.show()
复制代码
使用matplotlib加载和显示图像
Matplotlib是Python中常用的绘图库,它也提供了图像加载和显示的功能。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = mpimg.imread(image_path)
- # 显示图像信息
- print("图像形状:", img.shape)
- print("图像数据类型:", img.dtype)
- # 显示图像
- plt.imshow(img)
- plt.axis('off') # 不显示坐标轴
- plt.show()
复制代码
保存图像
处理完图像后,我们可能需要将结果保存下来。我们可以使用PIL或matplotlib来实现这一功能。
- import numpy as np
- from PIL import Image
- import matplotlib.pyplot as plt
- # 假设我们有一个NumPy数组表示的图像
- # 这里我们创建一个随机的RGB图像作为示例
- height, width = 200, 300
- img_array = np.random.randint(0, 256, (height, width, 3), dtype=np.uint8)
- # 使用PIL保存图像
- img = Image.fromarray(img_array)
- img.save("random_image.jpg")
- # 使用matplotlib保存图像
- plt.imsave("random_image_matplotlib.jpg", img_array)
复制代码
基本图像操作
现在我们已经学会了如何加载和显示图像,接下来让我们学习一些基本的图像操作。
图像裁剪
图像裁剪是指从图像中提取一个矩形区域。在NumPy中,这可以通过数组切片来实现。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = mpimg.imread(image_path)
- # 裁剪图像 [y_start:y_end, x_start:x_end]
- # 注意:在NumPy数组中,第一个维度是高度(y轴),第二个维度是宽度(x轴)
- cropped_img = img[100:400, 200:500] # 裁剪从(200,100)到(500,400)的区域
- # 显示原始图像和裁剪后的图像
- plt.figure(figsize=(10, 5))
- plt.subplot(1, 2, 1)
- plt.imshow(img)
- plt.title("原始图像")
- plt.axis('off')
- plt.subplot(1, 2, 2)
- plt.imshow(cropped_img)
- plt.title("裁剪后的图像")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
图像旋转
图像旋转是另一种常见的图像操作。我们可以使用NumPy的rot90函数来实现简单的90度倍数旋转,或者使用更复杂的变换来实现任意角度的旋转。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = mpimg.imread(image_path)
- # 旋转90度(逆时针)
- rotated_90 = np.rot90(img)
- # 旋转180度
- rotated_180 = np.rot90(img, 2)
- # 旋转270度(或顺时针90度)
- rotated_270 = np.rot90(img, 3)
- # 显示原始图像和旋转后的图像
- plt.figure(figsize=(12, 8))
- plt.subplot(2, 2, 1)
- plt.imshow(img)
- plt.title("原始图像")
- plt.axis('off')
- plt.subplot(2, 2, 2)
- plt.imshow(rotated_90)
- plt.title("旋转90度")
- plt.axis('off')
- plt.subplot(2, 2, 3)
- plt.imshow(rotated_180)
- plt.title("旋转180度")
- plt.axis('off')
- plt.subplot(2, 2, 4)
- plt.imshow(rotated_270)
- plt.title("旋转270度")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
如果要实现任意角度的旋转,我们可以使用scipy.ndimage库中的rotate函数:
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- from scipy.ndimage import rotate
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = mpimg.imread(image_path)
- # 旋转45度
- rotated_45 = rotate(img, 45, reshape=False)
- # 旋转30度
- rotated_30 = rotate(img, 30, reshape=False)
- # 显示原始图像和旋转后的图像
- plt.figure(figsize=(15, 5))
- plt.subplot(1, 3, 1)
- plt.imshow(img)
- plt.title("原始图像")
- plt.axis('off')
- plt.subplot(1, 3, 2)
- plt.imshow(rotated_45)
- plt.title("旋转45度")
- plt.axis('off')
- plt.subplot(1, 3, 3)
- plt.imshow(rotated_30)
- plt.title("旋转30度")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
图像缩放
图像缩放是指改变图像的大小。我们可以使用NumPy的resize函数或scipy.ndimage中的zoom函数来实现。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- from scipy.ndimage import zoom
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = mpimg.imread(image_path)
- # 获取原始图像尺寸
- original_height, original_width = img.shape[:2]
- print(f"原始图像尺寸: {original_width}x{original_height}")
- # 使用NumPy的resize函数进行缩放
- # 将图像缩小到原来的一半
- resized_half = np.array(Image.fromarray(img).resize((original_width//2, original_height//2)))
- # 将图像放大到原来的两倍
- resized_double = np.array(Image.fromarray(img).resize((original_width*2, original_height*2)))
- # 使用scipy.ndimage的zoom函数进行缩放
- # 将图像缩小到原来的一半
- zoomed_half = zoom(img, 0.5)
- # 将图像放大到原来的两倍
- zoomed_double = zoom(img, 2)
- # 显示原始图像和缩放后的图像
- plt.figure(figsize=(15, 10))
- plt.subplot(2, 3, 1)
- plt.imshow(img)
- plt.title("原始图像")
- plt.axis('off')
- plt.subplot(2, 3, 2)
- plt.imshow(resized_half)
- plt.title("缩小一半 (NumPy resize)")
- plt.axis('off')
- plt.subplot(2, 3, 3)
- plt.imshow(resized_double)
- plt.title("放大两倍 (NumPy resize)")
- plt.axis('off')
- plt.subplot(2, 3, 4)
- plt.imshow(img)
- plt.title("原始图像")
- plt.axis('off')
- plt.subplot(2, 3, 5)
- plt.imshow(zoomed_half)
- plt.title("缩小一半 (scipy zoom)")
- plt.axis('off')
- plt.subplot(2, 3, 6)
- plt.imshow(zoomed_double)
- plt.title("放大两倍 (scipy zoom)")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
图像翻转
图像翻转是指沿水平轴或垂直轴翻转图像。我们可以使用NumPy的flip函数来实现。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = mpimg.imread(image_path)
- # 水平翻转(沿垂直轴)
- flipped_horizontal = np.fliplr(img)
- # 垂直翻转(沿水平轴)
- flipped_vertical = np.flipud(img)
- # 水平和垂直翻转
- flipped_both = np.flip(img)
- # 显示原始图像和翻转后的图像
- plt.figure(figsize=(10, 8))
- plt.subplot(2, 2, 1)
- plt.imshow(img)
- plt.title("原始图像")
- plt.axis('off')
- plt.subplot(2, 2, 2)
- plt.imshow(flipped_horizontal)
- plt.title("水平翻转")
- plt.axis('off')
- plt.subplot(2, 2, 3)
- plt.imshow(flipped_vertical)
- plt.title("垂直翻转")
- plt.axis('off')
- plt.subplot(2, 2, 4)
- plt.imshow(flipped_both)
- plt.title("水平和垂直翻转")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
图像颜色空间转换
在图像处理中,我们经常需要将图像从一种颜色空间转换到另一种颜色空间。最常见的转换是将彩色图像(RGB)转换为灰度图像。
RGB转灰度
RGB图像转换为灰度图像有多种方法,其中最常用的是加权平均法。我们可以使用NumPy来实现这一转换。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = mpimg.imread(image_path)
- # 方法1:简单平均法
- gray_avg = np.mean(img, axis=2)
- # 方法2:加权平均法(更符合人眼感知)
- # 灰度 = 0.299 * R + 0.587 * G + 0.114 * B
- weights = [0.299, 0.587, 0.114]
- gray_weighted = np.dot(img[..., :3], weights)
- # 显示原始图像和灰度图像
- plt.figure(figsize=(15, 5))
- plt.subplot(1, 3, 1)
- plt.imshow(img)
- plt.title("原始图像")
- plt.axis('off')
- plt.subplot(1, 3, 2)
- plt.imshow(gray_avg, cmap='gray')
- plt.title("简单平均灰度")
- plt.axis('off')
- plt.subplot(1, 3, 3)
- plt.imshow(gray_weighted, cmap='gray')
- plt.title("加权平均灰度")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
RGB转HSV
HSV(色相、饱和度、明度)是另一种常用的颜色空间。我们可以使用colorsys模块将RGB转换为HSV。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- import colorsys
- def rgb_to_hsv(rgb_image):
- """将RGB图像转换为HSV图像"""
- # 确保输入值在0-1范围内
- if rgb_image.dtype == np.uint8:
- rgb_image = rgb_image / 255.0
-
- # 创建空的HSV图像
- hsv_image = np.zeros_like(rgb_image)
-
- # 遍历每个像素
- for i in range(rgb_image.shape[0]):
- for j in range(rgb_image.shape[1]):
- r, g, b = rgb_image[i, j]
- h, s, v = colorsys.rgb_to_hsv(r, g, b)
- hsv_image[i, j] = [h, s, v]
-
- return hsv_image
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = mpimg.imread(image_path)
- # 转换为HSV
- hsv_img = rgb_to_hsv(img)
- # 显示HSV通道
- plt.figure(figsize=(15, 5))
- plt.subplot(1, 4, 1)
- plt.imshow(img)
- plt.title("原始RGB图像")
- plt.axis('off')
- plt.subplot(1, 4, 2)
- plt.imshow(hsv_img[:, :, 0], cmap='hsv')
- plt.title("色相 (H)")
- plt.axis('off')
- plt.subplot(1, 4, 3)
- plt.imshow(hsv_img[:, :, 1], cmap='gray')
- plt.title("饱和度 (S)")
- plt.axis('off')
- plt.subplot(1, 4, 4)
- plt.imshow(hsv_img[:, :, 2], cmap='gray')
- plt.title("明度 (V)")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
分离和合并RGB通道
我们可以使用NumPy来分离和合并RGB通道。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = mpimg.imread(image_path)
- # 分离RGB通道
- r = img[:, :, 0]
- g = img[:, :, 1]
- b = img[:, :, 2]
- # 创建只包含红色通道的图像
- r_img = np.zeros_like(img)
- r_img[:, :, 0] = r
- # 创建只包含绿色通道的图像
- g_img = np.zeros_like(img)
- g_img[:, :, 1] = g
- # 创建只包含蓝色通道的图像
- b_img = np.zeros_like(img)
- b_img[:, :, 2] = b
- # 显示原始图像和各个通道
- plt.figure(figsize=(15, 10))
- plt.subplot(2, 2, 1)
- plt.imshow(img)
- plt.title("原始图像")
- plt.axis('off')
- plt.subplot(2, 2, 2)
- plt.imshow(r_img)
- plt.title("红色通道")
- plt.axis('off')
- plt.subplot(2, 2, 3)
- plt.imshow(g_img)
- plt.title("绿色通道")
- plt.axis('off')
- plt.subplot(2, 2, 4)
- plt.imshow(b_img)
- plt.title("蓝色通道")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
图像滤波与增强
图像滤波和增强是图像处理中的重要操作,可以用于去噪、边缘检测、图像锐化等。
均值滤波
均值滤波是一种简单的线性滤波,用于图像平滑和去噪。它通过用邻域像素的平均值替换中心像素来实现。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- from scipy.ndimage import uniform_filter
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = mpimg.imread(image_path)
- # 转换为灰度图像
- if len(img.shape) == 3:
- img_gray = np.mean(img, axis=2)
- else:
- img_gray = img
- # 应用均值滤波
- # 使用3x3的滤波器
- filtered_3x3 = uniform_filter(img_gray, size=3)
- # 使用5x5的滤波器
- filtered_5x5 = uniform_filter(img_gray, size=5)
- # 使用7x7的滤波器
- filtered_7x7 = uniform_filter(img_gray, size=7)
- # 显示原始图像和滤波后的图像
- plt.figure(figsize=(15, 10))
- plt.subplot(2, 2, 1)
- plt.imshow(img_gray, cmap='gray')
- plt.title("原始灰度图像")
- plt.axis('off')
- plt.subplot(2, 2, 2)
- plt.imshow(filtered_3x3, cmap='gray')
- plt.title("3x3均值滤波")
- plt.axis('off')
- plt.subplot(2, 2, 3)
- plt.imshow(filtered_5x5, cmap='gray')
- plt.title("5x5均值滤波")
- plt.axis('off')
- plt.subplot(2, 2, 4)
- plt.imshow(filtered_7x7, cmap='gray')
- plt.title("7x7均值滤波")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
高斯滤波
高斯滤波是一种更有效的平滑滤波器,它使用高斯函数作为权重,对中心像素给予更高的权重。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- from scipy.ndimage import gaussian_filter
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = mpimg.imread(image_path)
- # 转换为灰度图像
- if len(img.shape) == 3:
- img_gray = np.mean(img, axis=2)
- else:
- img_gray = img
- # 应用高斯滤波
- # 使用sigma=1
- filtered_1 = gaussian_filter(img_gray, sigma=1)
- # 使用sigma=2
- filtered_2 = gaussian_filter(img_gray, sigma=2)
- # 使用sigma=3
- filtered_3 = gaussian_filter(img_gray, sigma=3)
- # 显示原始图像和滤波后的图像
- plt.figure(figsize=(15, 10))
- plt.subplot(2, 2, 1)
- plt.imshow(img_gray, cmap='gray')
- plt.title("原始灰度图像")
- plt.axis('off')
- plt.subplot(2, 2, 2)
- plt.imshow(filtered_1, cmap='gray')
- plt.title("高斯滤波 (sigma=1)")
- plt.axis('off')
- plt.subplot(2, 2, 3)
- plt.imshow(filtered_2, cmap='gray')
- plt.title("高斯滤波 (sigma=2)")
- plt.axis('off')
- plt.subplot(2, 2, 4)
- plt.imshow(filtered_3, cmap='gray')
- plt.title("高斯滤波 (sigma=3)")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
中值滤波
中值滤波是一种非线性滤波技术,对去除椒盐噪声特别有效。它通过用邻域像素的中值替换中心像素来实现。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- from scipy.ndimage import median_filter
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = mpimg.imread(image_path)
- # 转换为灰度图像
- if len(img.shape) == 3:
- img_gray = np.mean(img, axis=2)
- else:
- img_gray = img
- # 添加椒盐噪声
- noise_prob = 0.05 # 噪声概率
- noisy_img = img_gray.copy()
- rand_mask = np.random.random(img_gray.shape)
- noisy_img[rand_mask < noise_prob/2] = 0 # 椒噪声
- noisy_img[rand_mask > 1 - noise_prob/2] = 1 # 盐噪声
- # 应用中值滤波
- # 使用3x3的滤波器
- filtered_3x3 = median_filter(noisy_img, size=3)
- # 使用5x5的滤波器
- filtered_5x5 = median_filter(noisy_img, size=5)
- # 显示原始图像、噪声图像和滤波后的图像
- plt.figure(figsize=(15, 10))
- plt.subplot(2, 2, 1)
- plt.imshow(img_gray, cmap='gray')
- plt.title("原始灰度图像")
- plt.axis('off')
- plt.subplot(2, 2, 2)
- plt.imshow(noisy_img, cmap='gray')
- plt.title("添加椒盐噪声后的图像")
- plt.axis('off')
- plt.subplot(2, 2, 3)
- plt.imshow(filtered_3x3, cmap='gray')
- plt.title("3x3中值滤波")
- plt.axis('off')
- plt.subplot(2, 2, 4)
- plt.imshow(filtered_5x5, cmap='gray')
- plt.title("5x5中值滤波")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
边缘检测
边缘检测是图像处理中的重要操作,用于识别图像中的边缘。我们可以使用Sobel算子来实现边缘检测。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- from scipy.ndimage import sobel
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = mpimg.imread(image_path)
- # 转换为灰度图像
- if len(img.shape) == 3:
- img_gray = np.mean(img, axis=2)
- else:
- img_gray = img
- # 应用Sobel算子
- # 水平方向边缘检测
- edge_h = sobel(img_gray, axis=1)
- # 垂直方向边缘检测
- edge_v = sobel(img_gray, axis=0)
- # 组合水平和垂直边缘
- edge_combined = np.sqrt(edge_h**2 + edge_v**2)
- # 显示原始图像和边缘检测结果
- plt.figure(figsize=(15, 10))
- plt.subplot(2, 2, 1)
- plt.imshow(img_gray, cmap='gray')
- plt.title("原始灰度图像")
- plt.axis('off')
- plt.subplot(2, 2, 2)
- plt.imshow(edge_h, cmap='gray')
- plt.title("水平边缘检测")
- plt.axis('off')
- plt.subplot(2, 2, 3)
- plt.imshow(edge_v, cmap='gray')
- plt.title("垂直边缘检测")
- plt.axis('off')
- plt.subplot(2, 2, 4)
- plt.imshow(edge_combined, cmap='gray')
- plt.title("组合边缘检测")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
图像锐化
图像锐化可以增强图像的边缘和细节,使图像看起来更清晰。我们可以使用拉普拉斯算子来实现图像锐化。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- from scipy.ndimage import laplace
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = mpimg.imread(image_path)
- # 转换为灰度图像
- if len(img.shape) == 3:
- img_gray = np.mean(img, axis=2)
- else:
- img_gray = img
- # 应用拉普拉斯算子
- laplacian = laplace(img_gray)
- # 图像锐化
- # 锐化图像 = 原始图像 - 系数 * 拉普拉斯图像
- alpha = 0.5 # 锐化系数
- sharpened = img_gray - alpha * laplacian
- # 确保值在0-1范围内
- sharpened = np.clip(sharpened, 0, 1)
- # 显示原始图像和锐化后的图像
- plt.figure(figsize=(15, 5))
- plt.subplot(1, 3, 1)
- plt.imshow(img_gray, cmap='gray')
- plt.title("原始灰度图像")
- plt.axis('off')
- plt.subplot(1, 3, 2)
- plt.imshow(laplacian, cmap='gray')
- plt.title("拉普拉斯图像")
- plt.axis('off')
- plt.subplot(1, 3, 3)
- plt.imshow(sharpened, cmap='gray')
- plt.title("锐化后的图像")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
图像算术运算
图像算术运算包括图像的加法、减法、乘法和除法等操作。这些操作在图像处理中有广泛的应用,如图像混合、图像差异检测等。
图像加法
图像加法可以用于图像混合或增加图像亮度。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- # 加载图像
- image_path1 = "example1.jpg" # 替换为你的图像路径
- image_path2 = "example2.jpg" # 替换为你的图像路径
- img1 = mpimg.imread(image_path1)
- img2 = mpimg.imread(image_path2)
- # 确保两个图像大小相同
- if img1.shape != img2.shape:
- img2 = np.array(Image.fromarray(img2).resize((img1.shape[1], img1.shape[0])))
- # 图像加法
- # 方法1:简单相加(可能导致值超出范围)
- added_simple = img1 + img2
- # 方法2:加权相加(更常用)
- alpha = 0.5 # 第一个图像的权重
- beta = 0.5 # 第二个图像的权重
- added_weighted = alpha * img1 + beta * img2
- # 确保值在0-1范围内
- added_weighted = np.clip(added_weighted, 0, 1)
- # 显示原始图像和相加后的图像
- plt.figure(figsize=(15, 5))
- plt.subplot(1, 3, 1)
- plt.imshow(img1)
- plt.title("图像1")
- plt.axis('off')
- plt.subplot(1, 3, 2)
- plt.imshow(img2)
- plt.title("图像2")
- plt.axis('off')
- plt.subplot(1, 3, 3)
- plt.imshow(added_weighted)
- plt.title("加权相加后的图像")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
图像减法
图像减法可以用于检测图像之间的差异或背景减除。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- # 加载图像
- image_path1 = "example1.jpg" # 替换为你的图像路径
- image_path2 = "example2.jpg" # 替换为你的图像路径
- img1 = mpimg.imread(image_path1)
- img2 = mpimg.imread(image_path2)
- # 确保两个图像大小相同
- if img1.shape != img2.shape:
- img2 = np.array(Image.fromarray(img2).resize((img1.shape[1], img1.shape[0])))
- # 图像减法
- subtracted = img1 - img2
- # 显示绝对差异
- absolute_diff = np.abs(img1 - img2)
- # 显示原始图像和相减后的图像
- plt.figure(figsize=(15, 10))
- plt.subplot(2, 2, 1)
- plt.imshow(img1)
- plt.title("图像1")
- plt.axis('off')
- plt.subplot(2, 2, 2)
- plt.imshow(img2)
- plt.title("图像2")
- plt.axis('off')
- plt.subplot(2, 2, 3)
- plt.imshow(subtracted)
- plt.title("图像减法")
- plt.axis('off')
- plt.subplot(2, 2, 4)
- plt.imshow(absolute_diff)
- plt.title("绝对差异")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
图像乘法
图像乘法可以用于调整图像对比度或应用掩码。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = mpimg.imread(image_path)
- # 转换为灰度图像
- if len(img.shape) == 3:
- img_gray = np.mean(img, axis=2)
- else:
- img_gray = img
- # 创建一个掩码(例如,中心亮,周围暗)
- height, width = img_gray.shape
- y, x = np.ogrid[:height, :width]
- center_y, center_x = height // 2, width // 2
- # 创建径向渐变掩码
- dist_from_center = np.sqrt((x - center_x)**2 + (y - center_y)**2)
- max_dist = np.sqrt(center_x**2 + center_y**2)
- mask = 1 - (dist_from_center / max_dist)
- # 应用掩码
- masked = img_gray * mask
- # 调整对比度
- contrast_factor = 1.5 # 大于1增加对比度,小于1降低对比度
- mean = np.mean(img_gray)
- adjusted = mean + contrast_factor * (img_gray - mean)
- # 确保值在0-1范围内
- adjusted = np.clip(adjusted, 0, 1)
- # 显示原始图像和处理后的图像
- plt.figure(figsize=(15, 10))
- plt.subplot(2, 2, 1)
- plt.imshow(img_gray, cmap='gray')
- plt.title("原始灰度图像")
- plt.axis('off')
- plt.subplot(2, 2, 2)
- plt.imshow(mask, cmap='gray')
- plt.title("掩码")
- plt.axis('off')
- plt.subplot(2, 2, 3)
- plt.imshow(masked, cmap='gray')
- plt.title("应用掩码后的图像")
- plt.axis('off')
- plt.subplot(2, 2, 4)
- plt.imshow(adjusted, cmap='gray')
- plt.title("调整对比度后的图像")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
图像除法
图像除法可以用于归一化或校正图像。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = mpimg.imread(image_path)
- # 转换为灰度图像
- if len(img.shape) == 3:
- img_gray = np.mean(img, axis=2)
- else:
- img_gray = img
- # 创建一个背景图像(例如,模糊版本的原始图像)
- from scipy.ndimage import gaussian_filter
- background = gaussian_filter(img_gray, sigma=10)
- # 图像除法(用于背景校正)
- # 避免除以零
- background = np.where(background < 0.01, 0.01, background)
- corrected = img_gray / background
- # 归一化到0-1范围
- corrected = (corrected - np.min(corrected)) / (np.max(corrected) - np.min(corrected))
- # 显示原始图像和处理后的图像
- plt.figure(figsize=(15, 5))
- plt.subplot(1, 3, 1)
- plt.imshow(img_gray, cmap='gray')
- plt.title("原始灰度图像")
- plt.axis('off')
- plt.subplot(1, 3, 2)
- plt.imshow(background, cmap='gray')
- plt.title("背景图像")
- plt.axis('off')
- plt.subplot(1, 3, 3)
- plt.imshow(corrected, cmap='gray')
- plt.title("背景校正后的图像")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
实际案例
现在,让我们通过一些实际案例来综合运用前面学到的知识。
案例1:图像去噪
在这个案例中,我们将结合使用多种滤波技术来去除图像中的噪声。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- from scipy.ndimage import gaussian_filter, median_filter
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = mpimg.imread(image_path)
- # 转换为灰度图像
- if len(img.shape) == 3:
- img_gray = np.mean(img, axis=2)
- else:
- img_gray = img
- # 添加高斯噪声
- mean = 0
- stddev = 0.1
- gaussian_noise = np.random.normal(mean, stddev, img_gray.shape)
- noisy_img_gaussian = img_gray + gaussian_noise
- # 添加椒盐噪声
- noise_prob = 0.05
- noisy_img_salt_pepper = img_gray.copy()
- rand_mask = np.random.random(img_gray.shape)
- noisy_img_salt_pepper[rand_mask < noise_prob/2] = 0 # 椒噪声
- noisy_img_salt_pepper[rand_mask > 1 - noise_prob/2] = 1 # 盐噪声
- # 去噪处理
- # 高斯噪声使用高斯滤波
- denoised_gaussian = gaussian_filter(noisy_img_gaussian, sigma=1)
- # 椒盐噪声使用中值滤波
- denoised_salt_pepper = median_filter(noisy_img_salt_pepper, size=3)
- # 确保值在0-1范围内
- denoised_gaussian = np.clip(denoised_gaussian, 0, 1)
- denoised_salt_pepper = np.clip(denoised_salt_pepper, 0, 1)
- # 显示原始图像、噪声图像和去噪后的图像
- plt.figure(figsize=(15, 10))
- plt.subplot(2, 3, 1)
- plt.imshow(img_gray, cmap='gray')
- plt.title("原始灰度图像")
- plt.axis('off')
- plt.subplot(2, 3, 2)
- plt.imshow(noisy_img_gaussian, cmap='gray')
- plt.title("添加高斯噪声")
- plt.axis('off')
- plt.subplot(2, 3, 3)
- plt.imshow(denoised_gaussian, cmap='gray')
- plt.title("高斯滤波去噪")
- plt.axis('off')
- plt.subplot(2, 3, 4)
- plt.imshow(img_gray, cmap='gray')
- plt.title("原始灰度图像")
- plt.axis('off')
- plt.subplot(2, 3, 5)
- plt.imshow(noisy_img_salt_pepper, cmap='gray')
- plt.title("添加椒盐噪声")
- plt.axis('off')
- plt.subplot(2, 3, 6)
- plt.imshow(denoised_salt_pepper, cmap='gray')
- plt.title("中值滤波去噪")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
案例2:图像增强
在这个案例中,我们将使用多种技术来增强图像的质量和视觉效果。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- from scipy.ndimage import laplace, gaussian_filter
- # 加载图像
- image_path = "example.jpg" # 替换为你的图像路径
- img = mpimg.imread(image_path)
- # 转换为灰度图像
- if len(img.shape) == 3:
- img_gray = np.mean(img, axis=2)
- else:
- img_gray = img
- # 1. 对比度增强
- # 线性对比度拉伸
- min_val = np.min(img_gray)
- max_val = np.max(img_gray)
- stretched = (img_gray - min_val) / (max_val - min_val)
- # 2. 直方图均衡化
- hist, bins = np.histogram(img_gray.flatten(), 256, [0, 1])
- cdf = hist.cumsum()
- cdf_normalized = cdf / cdf[-1]
- equalized = np.interp(img_gray.flatten(), bins[:-1], cdf_normalized).reshape(img_gray.shape)
- # 3. 锐化
- # 使用拉普拉斯算子
- laplacian = laplace(img_gray)
- alpha = 0.5 # 锐化系数
- sharpened = img_gray - alpha * laplacian
- sharpened = np.clip(sharpened, 0, 1)
- # 4. 边缘增强
- # 提取边缘
- edge_enhanced = img_gray + 0.5 * laplacian
- edge_enhanced = np.clip(edge_enhanced, 0, 1)
- # 显示原始图像和增强后的图像
- plt.figure(figsize=(15, 10))
- plt.subplot(2, 3, 1)
- plt.imshow(img_gray, cmap='gray')
- plt.title("原始灰度图像")
- plt.axis('off')
- plt.subplot(2, 3, 2)
- plt.imshow(stretched, cmap='gray')
- plt.title("对比度拉伸")
- plt.axis('off')
- plt.subplot(2, 3, 3)
- plt.imshow(equalized, cmap='gray')
- plt.title("直方图均衡化")
- plt.axis('off')
- plt.subplot(2, 3, 4)
- plt.imshow(sharpened, cmap='gray')
- plt.title("锐化")
- plt.axis('off')
- plt.subplot(2, 3, 5)
- plt.imshow(edge_enhanced, cmap='gray')
- plt.title("边缘增强")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
案例3:图像拼接
在这个案例中,我们将学习如何将多张图像拼接成一张全景图。
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.image as mpimg
- # 加载图像
- image_path1 = "left.jpg" # 替换为你的图像路径
- image_path2 = "right.jpg" # 替换为你的图像路径
- img1 = mpimg.imread(image_path1)
- img2 = mpimg.imread(image_path2)
- # 转换为灰度图像以简化处理
- if len(img1.shape) == 3:
- img1_gray = np.mean(img1, axis=2)
- else:
- img1_gray = img1
- if len(img2.shape) == 3:
- img2_gray = np.mean(img2, axis=2)
- else:
- img2_gray = img2
- # 简单的图像拼接(水平拼接)
- # 确保两个图像高度相同
- if img1.shape[0] != img2.shape[0]:
- # 调整第二个图像的高度以匹配第一个图像
- from PIL import Image
- img2 = np.array(Image.fromarray(img2).resize((img2.shape[1], img1.shape[0])))
- img2_gray = np.mean(img2, axis=2) if len(img2.shape) == 3 else img2
- # 水平拼接
- panorama_simple = np.hstack((img1, img2))
- # 更复杂的拼接(带重叠区域)
- # 假设有20%的重叠区域
- overlap_percent = 0.2
- overlap_width = int(img1.shape[1] * overlap_percent)
- # 创建全景图
- panorama_width = img1.shape[1] + img2.shape[1] - overlap_width
- panorama_height = img1.shape[0]
- panorama = np.zeros((panorama_height, panorama_width, 3)) if len(img1.shape) == 3 else np.zeros((panorama_height, panorama_width))
- # 放置第一张图像
- panorama[:, :img1.shape[1]] = img1
- # 创建渐变掩码用于重叠区域
- mask = np.linspace(1, 0, overlap_width)
- if len(img1.shape) == 3:
- mask_3d = np.tile(mask[:, np.newaxis], (1, 3, 1)).transpose(2, 0, 1)
- else:
- mask_3d = mask[:, np.newaxis]
- # 放置第二张图像,重叠区域使用渐变混合
- panorama[:, img1.shape[1]-overlap_width:] = (
- img1[:, -overlap_width:] * mask_3d +
- img2[:, :overlap_width] * (1 - mask_3d)
- )
- panorama[:, img1.shape[1]:] = img2[:, overlap_width:]
- # 显示原始图像和拼接后的图像
- plt.figure(figsize=(15, 5))
- plt.subplot(1, 3, 1)
- plt.imshow(img1)
- plt.title("图像1")
- plt.axis('off')
- plt.subplot(1, 3, 2)
- plt.imshow(img2)
- plt.title("图像2")
- plt.axis('off')
- plt.subplot(1, 3, 3)
- plt.imshow(panorama)
- plt.title("拼接后的全景图")
- plt.axis('off')
- plt.tight_layout()
- plt.show()
复制代码
总结与进阶学习资源
通过本文的学习,我们已经掌握了使用NumPy进行图像处理的基础操作,包括图像的加载与显示、基本图像操作、颜色空间转换、图像滤波与增强、图像算术运算等内容。这些基础知识为我们后续学习更高级的图像处理技术打下了坚实的基础。
总结要点
1. NumPy数组与图像:图像在NumPy中表示为多维数组,灰度图像是二维数组,彩色图像是三维数组。
2. 图像基本操作:包括裁剪、旋转、缩放和翻转等,这些操作可以通过NumPy的切片和变换函数实现。
3. 颜色空间转换:包括RGB转灰度、RGB转HSV等,这些转换在图像处理中非常常见。
4. 图像滤波与增强:包括均值滤波、高斯滤波、中值滤波、边缘检测和图像锐化等,这些操作可以用于去噪、特征提取和图像增强。
5. 图像算术运算:包括图像的加法、减法、乘法和除法,这些操作在图像混合、差异检测和对比度调整等方面有广泛应用。
NumPy数组与图像:图像在NumPy中表示为多维数组,灰度图像是二维数组,彩色图像是三维数组。
图像基本操作:包括裁剪、旋转、缩放和翻转等,这些操作可以通过NumPy的切片和变换函数实现。
颜色空间转换:包括RGB转灰度、RGB转HSV等,这些转换在图像处理中非常常见。
图像滤波与增强:包括均值滤波、高斯滤波、中值滤波、边缘检测和图像锐化等,这些操作可以用于去噪、特征提取和图像增强。
图像算术运算:包括图像的加法、减法、乘法和除法,这些操作在图像混合、差异检测和对比度调整等方面有广泛应用。
进阶学习资源
如果你想进一步学习图像处理,以下资源可能会有所帮助:
1. OpenCV:OpenCV是一个开源的计算机视觉库,提供了丰富的图像处理和计算机视觉功能。它是NumPy图像处理的自然延伸。
2. scikit-image:scikit-image是一个基于NumPy的图像处理库,提供了许多高级图像处理算法。
3. PIL/Pillow:PIL(Python Imaging Library)或其分支Pillow是Python中常用的图像处理库,提供了图像I/O和基本的图像处理功能。
4. 深度学习框架:如TensorFlow、PyTorch等,它们提供了强大的图像处理和计算机视觉功能,特别是在深度学习领域。
5. 在线课程和教程:Coursera上的”图像处理基础”课程Udemy上的”Python图像处理:从入门到精通”YouTube上的图像处理教程
6. Coursera上的”图像处理基础”课程
7. Udemy上的”Python图像处理:从入门到精通”
8. YouTube上的图像处理教程
9. 书籍:《数字图像处理》(Digital Image Processing)by Rafael C. Gonzalez and Richard E. Woods《Python计算机视觉编程》(Programming Computer Vision with Python)by Jan Erik Solem
10. 《数字图像处理》(Digital Image Processing)by Rafael C. Gonzalez and Richard E. Woods
11. 《Python计算机视觉编程》(Programming Computer Vision with Python)by Jan Erik Solem
OpenCV:OpenCV是一个开源的计算机视觉库,提供了丰富的图像处理和计算机视觉功能。它是NumPy图像处理的自然延伸。
scikit-image:scikit-image是一个基于NumPy的图像处理库,提供了许多高级图像处理算法。
PIL/Pillow:PIL(Python Imaging Library)或其分支Pillow是Python中常用的图像处理库,提供了图像I/O和基本的图像处理功能。
深度学习框架:如TensorFlow、PyTorch等,它们提供了强大的图像处理和计算机视觉功能,特别是在深度学习领域。
在线课程和教程:
• Coursera上的”图像处理基础”课程
• Udemy上的”Python图像处理:从入门到精通”
• YouTube上的图像处理教程
书籍:
• 《数字图像处理》(Digital Image Processing)by Rafael C. Gonzalez and Richard E. Woods
• 《Python计算机视觉编程》(Programming Computer Vision with Python)by Jan Erik Solem
通过不断学习和实践,你将能够掌握更多高级的图像处理技术,并将其应用到实际项目中。祝你在图像处理的学习之旅中取得成功! |
|