图像数据的表示与基本运算
1. 图像文件的读写与显示
图像文件格式
-
图像文件结构:图像文件通常由文件头(file header)和图像数据(image data)两部分组成。文件头包含关于文件类型、创建者、时间、版本、大小、压缩方式等信息,这些信息对于图像数据的存储布局非常重要。
-
常见图像文件格式:
-
JPEG (.jpg, .jpeg): 文件头标识符为FFD8,广泛用于照片及网页图像,压缩比高但有损压缩。
-
PNG (.png): 文件头标识符为89504E470D0A1A0A,支持无损压缩及透明度处理,适合保存图标及图表。
-
GIF (.gif): 文件头标识符为474946383961,支持8位256色及简单动画,适合网络小动画。
-
BMP (.bmp): 文件头标识符为424D,Windows系统原生图像格式,不压缩但占用空间较大。
-
常用的图像处理工具包
-
OpenCV: 支持多种图像文件格式,提供了强大的图像处理功能,包括图像读取、转换、显示和保存。
-
Matplotlib: 主要用于数据可视化,也可以用来显示图像,特别是在需要将图像与其他数据可视化结合时。
-
Pillow (PIL): 是Python的图像处理库,用于图像的打开、操作和保存,适合进行简单的图像处理任务。
-
Scikit-image: 专门用于图像处理的Python包,包含图像增强、几何变换、滤波和分析等功能。
图像读写与显示的代码示例
-
OpenCV读取彩色图像并转换为灰度图像:
import cv2 as cv # 读取图像,以彩色模式加载 img = cv.imread('image.jpg', cv.IMREAD_COLOR) # 将彩色图像转换为灰度图像 img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 将灰度图像保存到文件 cv.imwrite('image_gray.jpg', img_gray)
-
Matplotlib显示图像:
import matplotlib.pyplot as plt import cv2 as cv # 读取图像,以彩色模式加载 img = cv.imread('image.jpg', cv.IMREAD_COLOR) # 将图像从 BGR 格式转换为 RGB 格式(因为 OpenCV 默认使用 BGR,而 Matplotlib 使用 RGB) plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB)) # 显示图像 plt.show()
OpenCV支持的图像格式
-
Windows位图: .bmp, .dib
-
JPEG文件: .jpeg, .jpg, .jpe
-
JPEG 2000文件: .jp2
-
PNG文件: .png
-
WebP文件: .webp
-
TIFF文件: .tiff, .tif
-
其他格式: .pbm, .pgm, .ppm, .pxm, .pnm, .sr, .ras
OpenCV视频处理
-
OpenCV还支持视频的读取与处理,以下代码示例展示了如何读取视频帧并保存为灰度视频:
import cv2 as cv # 打开视频文件 cap = cv.VideoCapture('video.mp4') # 指定视频编解码器为 XVID fourcc = cv.VideoWriter_fourcc(*'XVID') # 创建 VideoWriter 对象,用于将处理后的帧保存为新视频 # 参数包括输出文件名、编解码器、帧率(这里是 20.0),以及帧的大小(640x480) # isColor=False 表示输出为灰度视频 out = cv.VideoWriter('output.avi', fourcc, 20.0, (640, 480), isColor=False) # 循环读取视频帧 while cap.isOpened(): ret, frame = cap.read() # 读取一帧 if not ret: break # 如果读取失败,退出循环 # 将彩色帧转换为灰度帧 gray_frame = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) # 将灰度帧写入输出视频文件 out.write(gray_frame) # 释放视频捕获和写入对象 cap.release() out.release() # 销毁所有 OpenCV 窗口 cv.destroyAllWindows()
2. 图像类型与数据表示
图像类型
-
RGB真彩色图像:用M×N×3的三维数组保存每个像素的红、绿、蓝分量值。RGB图像常用于显示和图像处理任务,每个分量通常用8位表示,因此每个像素的颜色可以有16777216种不同组合。
-
索引图像 (Indexed Color Image):索引图像使用一个颜色索引表(调色板)来保存颜色信息。图像数据是一个M×N的二维数组,保存每个像素的颜色索引值,实际颜色由一个P×3的二维数组(调色板)来定义。
-
灰度图像 (Grayscale Image):灰度图像的每个像素值只包含一个灰度值,通常用8位表示,因此每个像素可以有256种灰度级别。适用于不需要颜色信息的场景,如医学影像、安防监控等。
-
二值图像 (Binary Image):二值图像的每个像素只能取两个离散值,通常为0和255,分别表示黑和白。适用于形状检测和图像分割任务。
-
视频图像 (Video Image):视频图像是由一组连续的静态图像帧组成,按一定的帧率播放,从而产生视觉运动感。
图像类型转换
-
彩色图像转换为灰度图像:
-
OpenCV:
import cv2 as cv # 读取彩色图像 img = cv.imread('image.jpg', cv.IMREAD_COLOR) # 使用 OpenCV 将彩色图像转换为灰度图像 img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
-
Scikit-image:
from skimage import color import cv2 as cv # 读取彩色图像 img = cv.imread('image.jpg', cv.IMREAD_COLOR) # 使用 Scikit-image 将彩色图像转换为灰度图像 # 注意:scikit-image 的 color.rgb2gray 会将图像值标准化为 0 到 1 之间的浮点数 img_gray = color.rgb2gray(img) # 如果需要将其转换回 0-255 范围的 uint8 类型 img_gray = (img_gray * 255).astype('uint8')
-
-
灰度图像转换为彩色图像(伪彩色):
import cv2 as cv # 假设 img_gray 是已经转换好的灰度图像 # 使用 OpenCV 的 applyColorMap 函数将灰度图像转换为伪彩色图像 img_color = cv.applyColorMap(img_gray, cv.COLORMAP_JET) # 显示伪彩色图像 cv.imshow('Pseudocolor Image', img_color) cv.waitKey(0) cv.destroyAllWindows()
3. 图像的数字化过程
图像的数学表示
-
二维函数:灰度图像可以表示为一个二维函数f(x,y),其中x和y是空间坐标,f(x,y)是图像的灰度值。
-
RGB图像的表示:RGB图像可以表示为f(x,y) = (R(x,y), G(x,y), B(x,y)),其中R, G, B分别表示红、绿、蓝三个颜色分量的强度。
图像的数字化
-
空间采样:对图像的光影像进行空间采样,将其离散化为一组采样点(像素),每个像素代表图像在该点的光强度。
-
时间采样:通过曝光时间控制采样时刻,从而捕获不同时间点的图像信息。
-
像素值量化:将采样得到的模拟信号转换为数字信号,通常使用8位量化,像素值范围在0-255之间。
空间分辨率与灰度分辨率
-
空间分辨率:表示图像中可分辨的最小细节,通常以像素数表示。分辨率越高,图像越清晰。
-
灰度分辨率:表示图像像素灰度值的分辨能力,通常由量化级数决定。灰度分辨率越高,图像的灰度变化越细腻。
4. 图像的基本运算
图像的算术运算
-
加法与减法:用于图像的增强和差异计算。两个图像相加可以增强图像亮度,减法则可以突出图像中的变化。
import cv2 as cv # 读取两张图像 img1 = cv.imread('image1.jpg', cv.IMREAD_COLOR) img2 = cv.imread('image2.jpg', cv.IMREAD_COLOR) # 对两张图像进行加法运算,增强图像亮度 img_sum = cv.add(img1, img2) # 对两张图像进行减法运算,突出图像中的变化 img_diff = cv.subtract(img1, img2) # 显示结果 cv.imshow('Image Sum', img_sum) cv.imshow('Image Difference', img_diff) cv.waitKey(0) cv.destroyAllWindows()
-
乘法与除法:用于图像的缩放和增强。乘法可以增加图像的对比度,而除法可以用于光照校正。
import cv2 as cv # 读取图像 img1 = cv.imread('image1.jpg', cv.IMREAD_COLOR) # 对图像进行乘法运算,增加图像的对比度 # 这里 1.5 是一个标量,可以调整对比度的增强程度 img_mul = cv.multiply(img1, 1.5) # 对图像进行除法运算,用于光照校正 # 这里 2 是一个标量,减少图像的亮度 img_div = cv.divide(img1, 2) # 显示结果 cv.imshow('Image Multiply', img_mul) cv.imshow('Image Divide', img_div) cv.waitKey(0) cv.destroyAllWindows()
图像的逻辑运算
-
与 (AND) 运算:用于图像的掩膜操作,将某些区域设置为黑色(0)。
import cv2 as cv # 读取图像和掩膜 img = cv.imread('image.jpg', cv.IMREAD_COLOR) mask = cv.imread('mask.jpg', cv.IMREAD_GRAYSCALE) # 掩膜通常为灰度图像 # 对图像和掩膜进行与运算,将掩膜区域外的像素设为黑色 img_and = cv.bitwise_and(img, img, mask=mask) # 显示结果 cv.imshow('Image AND', img_and) cv.waitKey(0) cv.destroyAllWindows()
-
或 (OR) 运算:用于合并两个图像,保留所有非零像素。
import cv2 as cv # 读取两张图像 img1 = cv.imread('image1.jpg', cv.IMREAD_COLOR) img2 = cv.imread('image2.jpg', cv.IMREAD_COLOR) # 对两张图像进行或运算,合并所有非零像素 img_or = cv.bitwise_or(img1, img2) # 显示结果 cv.imshow('Image OR', img_or) cv.waitKey(0) cv.destroyAllWindows()
-
非 (NOT) 运算:将图像的所有像素值取反,适用于创建图像的负片效果。
import cv2 as cv # 读取图像 img = cv.imread('image.jpg', cv.IMREAD_COLOR) # 对图像进行非运算,将所有像素值取反 # 适用于创建图像的负片效果 img_not = cv.bitwise_not(img) # 显示结果 cv.imshow('Image NOT', img_not) cv.waitKey(0) cv.destroyAllWindows()
图像的几何变换
-
旋转:通过定义旋转中心、旋转角度和缩放因子对图像进行旋转。
import cv2 as cv # 读取图像 img = cv.imread('image.jpg', cv.IMREAD_COLOR) # 获取图像的尺寸 rows, cols = img.shape[:2] # 定义旋转中心为图像的中心点 center = (cols / 2, rows / 2) # 定义旋转角度为 45 度,缩放因子为 1(保持原尺寸) angle = 45 scale = 1 # 获取旋转矩阵 matrotate = cv.getRotationMatrix2D(center=center, angle=angle, scale=scale) # 应用旋转矩阵对图像进行旋转 img_rotated = cv.warpAffine(img, matrotate, (cols, rows)) # 显示结果 cv.imshow('Rotated Image', img_rotated) cv.waitKey(0) cv.destroyAllWindows()
5. 图像的高级运算与处理
图像滤波
-
空域滤波
:直接在图像的像素空间进行操作,如均值滤波、Gaussian滤波、Laplace滤波等。
-
频域滤波:将图像转换到频域进行滤波处理,如傅里叶变换(FFT)、高通滤波和低通滤波。
图像增强
-
直方图均衡化:通过调整图像的灰度直方图分布来增强图像的对比度。
import cv2 as cv import matplotlib.pyplot as plt # 读取图像并转换为灰度图 img = cv.imread('image.jpg', cv.IMREAD_COLOR) # 读取彩色图像 img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 将彩色图像转换为灰度图像 # 直方图均衡化 # 直方图均衡化是一种增强图像对比度的技术,通过调整图像像素的灰度分布,使图像的细节更加清晰。 img_eq = cv.equalizeHist(img_gray) # 对灰度图像进行直方图均衡化处理 # 使用matplotlib显示原始图像和均衡化后的图像 plt.figure(figsize=(10, 5)) # 设置图像显示的窗口大小 plt.subplot(1, 2, 1) # 将显示窗口分为1行2列,选择第一个子图 plt.title('Original Image') # 设置子图的标题 plt.imshow(img_gray, cmap='gray') # 显示原始灰度图像 plt.axis('off') # 隐藏坐标轴 plt.subplot(1, 2, 2) # 选择第二个子图 plt.title('Equalized Image') # 设置子图的标题 plt.imshow(img_eq, cmap='gray') # 显示直方图均衡化后的图像 plt.axis('off') # 隐藏坐标轴 plt.show() # 显示图像
-
伽马校正:通过对图像的像素值进行非线性变换来调整图像的亮度和对比度。
import cv2 as cv import numpy as np import matplotlib.pyplot as plt # 读取图像并转换为灰度图 img = cv.imread('image.jpg', cv.IMREAD_COLOR) # 读取彩色图像 img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 将彩色图像转换为灰度图像 # 伽马校正 # 伽马校正是一种通过对像素值进行非线性变换来调整图像亮度和对比度的方法。 gamma = 2.2 # 设置伽马值,伽马值越大,图像越暗;伽马值越小,图像越亮 img_gamma = np.power(img_gray / 255.0, gamma) * 255.0 # 对图像进行伽马校正,像素值范围调整为0-255 img_gamma = img_gamma.astype(np.uint8) # 将计算结果转换为8位无符号整数类型,以便显示 # 使用matplotlib显示原始图像和伽马校正后的图像 plt.figure(figsize=(10, 5)) # 设置图像显示的窗口大小 plt.subplot(1, 2, 1) # 将显示窗口分为1行2列,选择第一个子图 plt.title('Original Image') # 设置子图的标题 plt.imshow(img_gray, cmap='gray') # 显示原始灰度图像 plt.axis('off') # 隐藏坐标轴 plt.subplot(1, 2, 2) # 选择第二个子图 plt.title('Gamma Corrected Image') # 设置子图的标题 plt.imshow(img_gamma, cmap='gray') # 显示伽马校正后的图像 plt.axis('off') # 隐藏坐标轴 plt.show() # 显示图像
图像分割
-
边缘检测:使用Sobel算子、Canny算法等进行图像边缘的检测。
-
区域生长:通过从种子点开始,逐步合并相邻像素来分割图像。
图像复原
-
去噪:使用中值滤波、双边滤波等去除图像中的噪声。
-
反卷积:通过逆滤波等方法恢复图像的模糊部分。