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

在这里插入图片描述

3.3 用NumPy处理图像数据

目录
Syntax error in textmermaid version 10.9.0
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 @   爱上编程技术  阅读(8)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示