【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】3.3 用NumPy处理图像数据

在这里插入图片描述

3.3 用NumPy处理图像数据

目录
3.3 用NumPy处理图像数据
3.3.1 图像数据的基本概念
3.3.1.1 图像表示
3.3.1.2 图像类型
3.3.1.3 图像文件格式
3.3.2 使用NumPy读取和写入图像数据
3.3.2.1 读取图像
3.3.2.2 写入图像
3.3.3 图像数据处理的实际应用
3.3.3.1 图像缩放
3.3.3.2 图像旋转
3.3.3.3 图像滤波
3.3.3.4 图像增强
3.3.4 代码实现:详细原理和源码注释
3.3.4.1 图像缩放代码实现
3.3.4.2 图像旋转代码实现
3.3.4.3 图像滤波代码实现
3.3.4.4 图像增强代码实现
3.3.5 总结与展望
3.3.5.1 本文总结
3.3.5.2 未来拓展方向
3.3.5.3 相关资源推荐
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 读取图像

使用 OpenCVPIL 库可以方便地读取图像数据到 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 写入图像

使用 OpenCVPIL 库可以方便地将 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 未来拓展方向
  1. 深度学习在图像处理中的应用:结合深度学习模型,实现更高级的图像处理任务,如目标检测、图像分割等。
  2. 并行处理:利用多线程或 GPU 加速图像处理算法,提高处理效率。
  3. 图像压缩与优化:研究图像压缩算法,如 JPEG、PNG 和 WebP,以及如何优化图像文件的大小。
  4. 图像特征提取:提取图像的特征,如边缘、角点等,用于图像识别和匹配。
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

这篇文章包含了详细的原理介绍、代码示例、源码注释以及案例等。希望这对您有帮助。如果有任何问题请随私信或评论告诉我。

posted @ 2025-02-05 11:39  爱上编程技术  阅读(46)  评论(0)    收藏  举报  来源