【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】3.3 用NumPy处理图像数据
3.3 用NumPy处理图像数据
目录
3.3.1 图像数据的基本概念
3.3.1.1 图像表示
图像在计算机中通常表示为二维或三维数组。对于灰度图像,每个像素的值范围从0到255,表示从黑色到白色的灰度级。对于彩色图像,每个像素通常由三个通道(红、绿、蓝)组成,每个通道的值范围也是0到255。
- 灰度图像:二维数组,每个元素表示一个像素的灰度值。
- 彩色图像:三维数组,每个元素表示一个像素的三个通道值。
import numpy as np
import matplotlib.pyplot as plt
# 创建一个 5x5 的灰度图像
gray_image = np.array([
[0, 64, 128, 192, 255],
[0, 64, 128, 192, 255],
[0, 64, 128, 192, 255],
[0, 64, 128, 192, 255],
[0, 64, 128, 192, 255]
], dtype=np.uint8)
# 创建一个 5x5 的彩色图像
color_image = np.array([
[
[255, 0, 0],
[128, 0, 0],
[64, 0, 0],
[0, 0, 0],
[0, 0, 0]
],
[
[255, 128, 0],
[128, 128, 0],
[64, 128, 0],
[0, 128, 0],
[0, 128, 0]
],
[
[255, 255, 0],
[128, 255, 0],
[64, 255, 0],
[0, 255, 0],
[0, 255, 0]
],
[
[255, 255, 128],
[128, 255, 128],
[64, 255, 128],
[0, 255, 128],
[0, 255, 128]
],
[
[255, 255, 255],
[128, 255, 255],
[64, 255, 255],
[0, 255, 255],
[0, 255, 255]
]
], dtype=np.uint8).transpose(1, 0, 2)
# 显示图像
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.imshow(gray_image, cmap='gray')
plt.title('灰度图像')
plt.subplot(1, 2, 2)
plt.imshow(color_image)
plt.title('彩色图像')
plt.show()
3.3.1.2 图像类型
图像类型主要分为两种:整型图像和浮点型图像。
- 整型图像:每个像素值是整数,通常使用
uint8
类型,范围从0到255。 - 浮点型图像:每个像素值是浮点数,通常使用
float32
类型,范围从0.0到1.0。
# 创建一个 5x5 的浮点型彩色图像
float_image = color_image.astype(np.float32) / 255.0
# 显示图像
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.imshow(color_image)
plt.title('整型彩色图像')
plt.subplot(1, 2, 2)
plt.imshow(float_image)
plt.title('浮点型彩色图像')
plt.show()
3.3.1.3 图像文件格式
常见的图像文件格式包括:
- JPEG:有损压缩,适合存储照片。
- PNG:无损压缩,支持透明度。
- BMP:无压缩,文件体积较大。
- TIFF:支持多种压缩方式,适合存储高精度图像。
3.3.2 使用NumPy读取和写入图像数据
3.3.2.1 读取图像
使用 OpenCV
和 PIL
库可以方便地读取图像数据到 NumPy 数组中。
import cv2
from PIL import Image
# 使用 OpenCV 读取灰度图像
cv2_gray_image = cv2.imread('example.jpg', cv2.IMREAD_GRAYSCALE)
# 使用 PIL 读取灰度图像
pil_gray_image = np.array(Image.open('example.jpg').convert('L'))
# 使用 OpenCV 读取彩色图像
cv2_color_image = cv2.imread('example.jpg', cv2.IMREAD_COLOR)
# 使用 PIL 读取彩色图像
pil_color_image = np.array(Image.open('example.jpg'))
# 显示图像
plt.figure(figsize=(10, 5))
plt.subplot(2, 2, 1)
plt.imshow(cv2_gray_image, cmap='gray')
plt.title('OpenCV 灰度图像')
plt.subplot(2, 2, 2)
plt.imshow(pil_gray_image, cmap='gray')
plt.title('PIL 灰度图像')
plt.subplot(2, 2, 3)
plt.imshow(cv2.cvtColor(cv2_color_image, cv2.COLOR_BGR2RGB))
plt.title('OpenCV 彩色图像')
plt.subplot(2, 2, 4)
plt.imshow(pil_color_image)
plt.title('PIL 彩色图像')
plt.show()
3.3.2.2 写入图像
使用 OpenCV
和 PIL
库可以方便地将 NumPy 数组写入图像文件。
# 使用 OpenCV 写入灰度图像
cv2.imwrite('cv2_gray_output.jpg', cv2_gray_image)
# 使用 PIL 写入灰度图像
Image.fromarray(pil_gray_image).save('pil_gray_output.jpg')
# 使用 OpenCV 写入彩色图像
cv2.imwrite('cv2_color_output.jpg', cv2.cvtColor(cv2_color_image, cv2.COLOR_RGB2BGR))
# 使用 PIL 写入彩色图像
Image.fromarray(pil_color_image).save('pil_color_output.jpg')
3.3.3 图像数据处理的实际应用
3.3.3.1 图像缩放
图像缩放是一种常见的图像处理技术,可以调整图像的大小。常用的缩放方法包括最近邻插值、双线性插值和双三次插值。
- 最近邻插值:每个像素的新值取最近的像素值。
- 双线性插值:每个像素的新值取其周围四个像素值的加权平均。
- 双三次插值:每个像素的新值取其周围16个像素值的加权平均。
import numpy as np
import cv2
import matplotlib.pyplot as plt
# 定义双线性插值函数
def bilinear_interpolation(image, new_shape):
height, width = image.shape
new_height, new_width = new_shape
ratio_x = width / new_width
ratio_y = height / new_height
x, y = np.meshgrid(np.arange(new_width), np.arange(new_height))
x = x * ratio_x
y = y * ratio_y
x_floor = np.floor(x).astype(int)
y_floor = np.floor(y).astype(int)
x_ceil = np.ceil(x).astype(int)
y_ceil = np.ceil(y).astype(int)
# 边界处理
x_ceil[x_ceil == width] = width - 1
y_ceil[y_ceil == height] = height - 1
Q11 = image[y_floor, x_floor]
Q12 = image[y_floor, x_ceil]
Q21 = image[y_ceil, x_floor]
Q22 = image[y_ceil, x_ceil]
x_diff = x - x_floor
y_diff = y - y_floor
interpolated = Q11 * (1 - x_diff) * (1 - y_diff) + \
Q12 * x_diff * (1 - y_diff) + \
Q21 * (1 - x_diff) * y_diff + \
Q22 * x_diff * y_diff
return interpolated
# 读取图像
img = cv2.imread('example.jpg', cv2.IMREAD_GRAYSCALE)
# 新图像的尺寸
new_shape = (800, 600)
# 使用不同插值方法调整图像大小
resized_nearest = cv2.resize(img, new_shape, interpolation=cv2.INTER_NEAREST)
resized_linear = cv2.resize(img, new_shape, interpolation=cv2.INTER_LINEAR)
resized_bilinear = bilinear_interpolation(img, new_shape)
resized_cubic = cv2.resize(img, new_shape, interpolation=cv2.INTER_CUBIC)
# 显示结果
plt.figure(figsize=(15, 10))
plt.subplot(2, 2, 1)
plt.imshow(resized_nearest, cmap='gray')
plt.title('最近邻插值')
plt.subplot(2, 2, 2)
plt.imshow(resized_linear, cmap='gray')
plt.title('双线性插值')
plt.subplot(2, 2, 3)
plt.imshow(resized_bilinear, cmap='gray')
plt.title('自定义双线性插值')
plt.subplot(2, 2, 4)
plt.imshow(resized_cubic, cmap='gray')
plt.title('双三次插值')
plt.show()
3.3.3.2 图像旋转
图像旋转是将图像绕某个点旋转一定角度。常用的旋转方法包括:
- 绕图像中心旋转:常用的旋转方式。
- 绕指定点旋转:可以根据需要指定旋转中心。
# 定义图像旋转函数
def rotate_image(image, angle, center=None, scale=1.0):
(height, width) = image.shape[:2]
if center is None:
center = (width // 2, height // 2)
M = cv2.getRotationMatrix2D(center, angle, scale)
rotated = cv2.warpAffine(image, M, (width, height))
return rotated
# 读取图像
img = cv2.imread('example.jpg', cv2.IMREAD_GRAYSCALE)
# 旋转图像
rotated_30 = rotate_image(img, 30)
rotated_60 = rotate_image(img, 60)
rotated_90 = rotate_image(img, 90)
# 显示结果
plt.figure(figsize=(15, 10))
plt.subplot(1, 3, 1)
plt.imshow(rotated_30, cmap='gray')
plt.title('旋转 30 度')
plt.subplot(1, 3, 2)
plt.imshow(rotated_60, cmap='gray')
plt.title('旋转 60 度')
plt.subplot(1, 3, 3)
plt.imshow(rotated_90, cmap='gray')
plt.title('旋转 90 度')
plt.show()
3.3.3.3 图像滤波
图像滤波是一种常见的图像处理技术,用于去除噪声或增强图像的某些特征。常用的滤波方法包括:
- 均值滤波:每个像素的新值取其邻域像素值的平均值。
- 高斯滤波:每个像素的新值取其邻域像素值的高斯加权平均值。
- 中值滤波:每个像素的新值取其邻域像素值的中位数。
# 读取图像
img = cv2.imread('example.jpg', cv2.IMREAD_GRAYSCALE)
# 应用均值滤波
blurred_avg = cv2.blur(img, (5, 5))
# 应用高斯滤波
blurred_gaussian = cv2.GaussianBlur(img, (5, 5), 0)
# 应用中值滤波
blurred_median = cv2.medianBlur(img, 5)
# 显示结果
plt.figure(figsize=(15, 10))
plt.subplot(1, 3, 1)
plt.imshow(blurred_avg, cmap='gray')
plt.title('均值滤波')
plt.subplot(1, 3, 2)
plt.imshow(blurred_gaussian, cmap='gray')
plt.title('高斯滤波')
plt.subplot(1, 3, 3)
plt.imshow(blurred_median, cmap='gray')
plt.title('中值滤波')
plt.show()
3.3.3.4 图像增强
图像增强是通过调整图像的某些属性来改善图像的质量。常用的图像增强方法包括:
- 直方图均衡化:提高图像的对比度。
- Gamma 校正:调整图像的亮度和对比度。
- CLAHE:局部自适应直方图均衡化,适用于具有复杂光照条件的图像。
# 读取图像
img = cv2.imread('example.jpg', cv2.IMREAD_GRAYSCALE)
# 应用直方图均衡化
equalized = cv2.equalizeHist(img)
# 应用 Gamma 校正
gamma = 1.5
gamma_corrected = np.power(img / 255.0, gamma) * 255.0
# 应用 CLAHE
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
clahe_corrected = clahe.apply(img)
# 显示结果
plt.figure(figsize=(15, 10))
plt.subplot(1, 3, 1)
plt.imshow(equalized, cmap='gray')
plt.title('直方图均衡化')
plt.subplot(1, 3, 2)
plt.imshow(gamma_corrected, cmap='gray')
plt.title('Gamma 校正')
plt.subplot(1, 3, 3)
plt.imshow(clahe_corrected, cmap='gray')
plt.title('CLAHE')
plt.show()
3.3.4 代码实现:详细原理和源码注释
3.3.4.1 图像缩放代码实现
import numpy as np
import cv2
import matplotlib.pyplot as plt
# 定义双线性插值函数
def bilinear_interpolation(image, new_shape):
"""
双线性插值实现图像缩放。
参数:
image (numpy.ndarray): 输入图像。
new_shape (tuple): 新图像的尺寸 (宽度, 高度)。
返回:
numpy.ndarray: 缩放后的图像。
"""
height, width = image.shape
new_height, new_width = new_shape
ratio_x = width / new_width
ratio_y = height / new_height
x, y = np.meshgrid(np.arange(new_width), np.arange(new_height)) # 创建网格
x = x * ratio_x
y = y * ratio_y
x_floor = np.floor(x).astype(int)
y_floor = np.floor(y).astype(int)
x_ceil = np.ceil(x).astype(int)
y_ceil = np.ceil(y).astype(int)
# 边界处理
x_ceil[x_ceil == width] = width - 1
y_ceil[y_ceil == height] = height - 1
Q11 = image[y_floor, x_floor] # 取左上角像素值
Q12 = image[y_floor, x_ceil] # 取右上角像素值
Q21 = image[y_ceil, x_floor] # 取左下角像素值
Q22 = image[y_ceil, x_ceil] # 取右下角像素值
x_diff = x - x_floor
y_diff = y - y_floor
# 计算插值结果
interpolated = Q11 * (1 - x_diff) * (1 - y_diff) + \
Q12 * x_diff * (1 - y_diff) + \
Q21 * (1 - x_diff) * y_diff + \
Q22 * x_diff * y_diff
return interpolated
# 读取图像
img = cv2.imread('example.jpg', cv2.IMREAD_GRAYSCALE)
# 新图像的尺寸
new_shape = (800, 600)
# 使用不同插值方法调整图像大小
resized_nearest = cv2.resize(img, new_shape, interpolation=cv2.INTER_NEAREST)
resized_linear = cv2.resize(img, new_shape, interpolation=cv2.INTER_LINEAR)
resized_bilinear = bilinear_interpolation(img, new_shape)
resized_cubic = cv2.resize(img, new_shape, interpolation=cv2.INTER_CUBIC)
# 显示结果
plt.figure(figsize=(15, 10))
plt.subplot(2, 2, 1)
plt.imshow(resized_nearest, cmap='gray')
plt.title('最近邻插值')
plt.subplot(2, 2, 2)
plt.imshow(resized_linear, cmap='gray')
plt.title('双线性插值 (OpenCV)')
plt.subplot(2, 2, 3)
plt.imshow(resized_bilinear, cmap='gray')
plt.title('双线性插值 (自定义)')
plt.subplot(2, 2, 4)
plt.imshow(resized_cubic, cmap='gray')
plt.title('双三次插值')
plt.show()
3.3.4.2 图像旋转代码实现
# 定义图像旋转函数
def rotate_image(image, angle, center=None, scale=1.0):
"""
旋转图像。
参数:
image (numpy.ndarray): 输入图像。
angle (float): 旋转角度(逆时针方向)。
center (tuple): 旋转中心,默认为图像中心。
scale (float): 缩放比例,默认为1.0。
返回:
numpy.ndarray: 旋转后的图像。
"""
(height, width) = image.shape[:2]
if center is None:
center = (width // 2, height // 2)
M = cv2.getRotationMatrix2D(center, angle, scale)
rotated = cv2.warpAffine(image, M, (width, height))
return rotated
# 读取图像
img = cv2.imread('example.jpg', cv2.IMREAD_GRAYSCALE)
# 旋转图像
rotated_30 = rotate_image(img, 30)
rotated_60 = rotate_image(img, 60)
rotated_90 = rotate_image(img, 90)
# 显示结果
plt.figure(figsize=(15, 10))
plt.subplot(1, 3, 1)
plt.imshow(rotated_30, cmap='gray')
plt.title('旋转 30 度')
plt.subplot(1, 3, 2)
plt.imshow(rotated_60, cmap='gray')
plt.title('旋转 60 度')
plt.subplot(1, 3, 3)
plt.imshow(rotated_90, cmap='gray')
plt.title('旋转 90 度')
plt.show()
3.3.4.3 图像滤波代码实现
# 读取图像
img = cv2.imread('example.jpg', cv2.IMREAD_GRAYSCALE)
# 应用均值滤波
blurred_avg = cv2.blur(img, (5, 5))
# 应用高斯滤波
blurred_gaussian = cv2.GaussianBlur(img, (5, 5), 0)
# 应用中值滤波
blurred_median = cv2.medianBlur(img, 5)
# 显示结果
plt.figure(figsize=(15, 10))
plt.subplot(1, 3, 1)
plt.imshow(blurred_avg, cmap='gray')
plt.title('均值滤波')
plt.subplot(1, 3, 2)
plt.imshow(blurred_gaussian, cmap='gray')
plt.title('高斯滤波')
plt.subplot(1, 3, 3)
plt.imshow(blurred_median, cmap='gray')
plt.title('中值滤波')
plt.show()
3.3.4.4 图像增强代码实现
# 读取图像
img = cv2.imread('example.jpg', cv2.IMREAD_GRAYSCALE)
# 应用直方图均衡化
equalized = cv2.equalizeHist(img)
# 应用 Gamma 校正
gamma = 1.5
gamma_corrected = np.power(img / 255.0, gamma) * 255.0
# 应用 CLAHE
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
clahe_corrected = clahe.apply(img)
# 显示结果
plt.figure(figsize=(15, 10))
plt.subplot(1, 3, 1)
plt.imshow(equalized, cmap='gray')
plt.title('直方图均衡化')
plt.subplot(1, 3, 2)
plt.imshow(gamma_corrected, cmap='gray')
plt.title('Gamma 校正')
plt.subplot(1, 3, 3)
plt.imshow(clahe_corrected, cmap='gray')
plt.title('CLAHE')
plt.show()
3.3.5 总结与展望
3.3.5.1 本文总结
本文详细介绍了如何使用 NumPy 处理图像数据。首先,我们讨论了图像数据的基本概念,包括图像的表示、类型和文件格式。接着,我们介绍了如何使用 NumPy 和常用的图像处理库(如 OpenCV 和 PIL)读取和写入图像数据。随后,我们探讨了图像缩放、旋转和滤波的实际应用,并提供了相应的代码实现。最后,我们介绍了图像增强技术,包括直方图均衡化、Gamma 校正和 CLAHE。
3.3.5.2 未来拓展方向
- 深度学习在图像处理中的应用:结合深度学习模型,实现更高级的图像处理任务,如目标检测、图像分割等。
- 并行处理:利用多线程或 GPU 加速图像处理算法,提高处理效率。
- 图像压缩与优化:研究图像压缩算法,如 JPEG、PNG 和 WebP,以及如何优化图像文件的大小。
- 图像特征提取:提取图像的特征,如边缘、角点等,用于图像识别和匹配。
3.3.5.3 相关资源推荐
资料名称 | 链接 |
---|---|
NumPy 官方文档 | https://numpy.org/doc/stable/ |
OpenCV 官方文档 | https://docs.opencv.org/4.5.3/ |
PIL 官方文档 | https://pillow.readthedocs.io/en/stable/ |
图像处理基础 | https://www.geeksforgeeks.org/fundamentals-of-image-processing/ |
图像处理算法详解 | https://www.imageprocessingplace.com/ |
直方图均衡化详解 | https://en.wikipedia.org/wiki/Histogram_equalization |
Gamma 校正详解 | https://www.peterkovesi.com/papers/SpeedingUpGammaCorrection.pdf |
CLAHE 详解 | https://ieeexplore.ieee.org/document/1280562 |
图像处理实战案例 | https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_table_of_contents_imgproc/py_table_of_contents_imgproc.html |
图像缩放算法综述 | https://www.sciencedirect.com/science/article/pii/S003132030600390X |
图像旋转算法详解 | https://www.researchgate.net/publication/267664844_Rotation_of_Images_and_Videos_based_on_Complex_Numbers_and_Fourier_Transform |
图像滤波算法综述 | https://www.researchgate.net/publication/221130568_Robust_Image_Denoising_via_Low-Rank_and_Sparse_Matrix_Decomposition |
这篇文章包含了详细的原理介绍、代码示例、源码注释以及案例等。希望这对您有帮助。如果有任何问题请随私信或评论告诉我。
代码学习,前言技术分享,深度分析编程技术,普及科普编程技术,天天都要敲代码
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)