1.背景介绍
在许多计算机视觉任务中,图像处理占据了很重要的角色,尤其是在目标检测、特征提取、分类、跟踪等计算机视觉任务中。图像处理是一个复杂的过程,涉及到图像的采集、分析、存储、显示等环节。本文将讨论基于Python实现的图像处理的相关知识和技术。下面先介绍图像的定义、结构、属性及一些基本术语。
一、图像的定义、结构、属性及一些基本术语
-
图像的定义 在数学上,图像(image)是指空间中的点所组成的集合。图像由像素或灰度值表示。一幅图像通常可以看作是一个二维或三维矩阵。
-
图像的结构 图像由两个维度,即行数和列数。例如,彩色图像的像素点有三个颜色通道(红、绿、蓝)。在彩色图像中,每个像素点都有一个坐标值,描述这个像素点相对于整个图像的位置。
-
图像的属性
- 边界:图像的边界是一个外形,它把图像分割成若干个区域。图像的边界可以是矩形、圆形、椭圆、弯曲等。
- 直方图:直方图是图像的一维分布图,用以呈现灰度值或色调的分布情况。直方图能够直观地反映出图像的整体对比度、均匀性、均值等特性。
- 模糊:图像模糊是指图像中的高频噪声被低频信号所掩盖而得来的效果。图像模糊的原因很多,比如光照变化、摄像机运动、恶劣天气、光污染等。
- 空间域变换:在不同的空间域下,图像的视野范围不同,图像也会发生变化。
- 几何变换:图像的几何变换是指改变图像的大小、旋转角度、放缩等,以达到图像编辑、图像质量评估、增强等目的。
- 分割:图像的分割是图像识别、目标检测等任务的关键一步。图像的分割可以分为全局分割和局部分割。全局分割是指按照某种规则将整个图像划分成几个互不重叠的子区域。局部分割是指根据不同特征进行区域的分割。
- 一些基本术语
- 坐标系:坐标系用来描述一个点或者图像区域在某种坐标下的位置。常用的坐标系有笛卡尔坐标系和球面坐标系。
- RGB: 是一种三原色图片的色彩模型,其中R代表红色、G代表绿色、B代表蓝色。
- 灰度图: 是黑白的图像,其中每一个像素的值对应的是该像素的亮度。
- HSV: 是一种色彩模型,它把颜色划分为色调、饱和度、明度三个参数,分别对应红色、绿色、蓝色。
- 颜色空间转换:是指从一种颜色空间转换到另一种颜色空间。常见的颜色空间有RGB、HSV、CMYK、YCbCr四种。
- 拉普拉斯算子:是一个二阶微分算子,用于检测图像中的边缘。它的水平方向、垂直方向和对角线方向上的梯度都是1,中间的元素是0。
- 中值滤波:是一种图像平滑方法。它用邻域内的中值代替当前像素的灰度值。
- 锐化(Sharpen):是指将图像中的细节锐化,使其显得更加醒目。
- 撕裂(Dilation):是指将图像中的细节向外扩张。
- 膨胀(Erosion):是指将图像中的细节向里收缩。
- 腐蚀(erosion):是指将图像中的噪声点排除掉,只保留边缘信息。
二、Python 的图像处理库
- OpenCV (Open Source Computer Vision Library) OpenCV (Open Source Computer Vision Library) 是目前最流行的开源计算机视觉库。该库提供了各种功能,如图像处理、计算机视觉、机器学习、自然语言处理等。它支持多种编程语言,包括 C++、Java、Python、MATLAB 和其他。OpenCV 库提供多个工具集用于解决日常生活中的常见计算机视觉问题。
- Pillow (Python Imaging Library) Pillow 是一个用来创建、编辑、保存、显示、分析和转换图像的 Python 模块。Pillow 提供了 Image 对象,并提供了一系列的方法用来对图像进行操作。
- Scikit-Image (scikit-learn for image processing) Scikit-Image 是基于 NumPy, SciPy, and matplotlib 的 Python 图像处理库。它提供多种函数来进行图像的读取、写入、裁剪、缩放、翻转、显示、转换等。还可以通过不同的算法来进行图像的分割、过滤、形态学处理、特征提取等。
- Keras with TensorFlow backend Keras 是用于构建和训练神经网络的高级 API。它具有可移植性、易用性、模块化设计和可扩展性。Keras 可以运行在 TensorFlow 或 Theano 上,为开发人员提供简单且高效的接口。它支持常见的数据结构,如张量、数组、字典等,并且支持加载、存储、归一化数据、监控训练过程、可视化结果等功能。
三、数字图像处理的一些基本技术
- 颜色模型转换
- RGB 颜色模型转换为 YUV
- YUV 颜色模型转换为 RGB
- RGB 颜色模型转换为 HSV
- 图像拼接
- 横向拼接
- 纵向拼接
- 图像均衡化
- 全局均衡化
- 局部均衡化
- 图像滤波
- 中值滤波
- 双边滤波
- 均值滤波
- 高斯滤波
- 图像预处理
- 直方图归一化
- 标准化
- 高斯噪声降低
- 图像增强
- 对比度增强
- 色调增强
- 饱和度增强
- 平滑
- 锐化
- 图像融合
- 抖动合并
- 权重融合
- 插值融合
- 平均融合
- 图像分割
- 阈值分割
- K-Means 聚类
- Mean Shift 聚类
- 形态学操作
- 开运算
- 闭运算
- 顶帽运算
- 底帽运算
- 形态学梯度
- 顶帽操作与底帽操作结合
四、Python 图像处理实践
下面我们通过实例,使用 Python 来实现一些常见的图像处理技术,包括图片缩放、拼接、锐化、均衡化、图片增强、形态学处理等。具体如下:
1. 图片缩放
python
from PIL import Image
import numpy as np
img = Image.open('lena_color.tif') # 以 RGB 模式打开彩色图像
width = int(img.size[0] * 0.5) # 宽度缩小一半
height = int(img.size[1] * 0.5) # 高度缩小一半
img_small = img.resize((width, height), Image.ANTIALIAS) # 使用 ANTIALIAS 选项进行放缩
img_arr = np.array(img).astype("uint8") # 将图像转换为 Numpy array
img_small_arr = np.array(img_small).astype("uint8")
print(f"Original size is {img.size}, new size is {img_small.size}")
print(f"Difference between original pixel values and resized small ones:\n{np.abs(img_arr - img_small_arr)}")
2. 拼接图片
python
from PIL import Image
import os
path = 'images' # 指定图片路径
files = sorted([os.path.join(path, f) for f in os.listdir(path)]) # 获取指定路径的所有图片文件
img_new = None # 初始化空图像
for i, img in enumerate(imgs):
print(f"{i+1}. Size of the current picture is {img.size}")
if img_new == None:
img_new = img # 如果是第一张图片,直接赋值给 img_new
else:
img_new = Image.alpha_composite(img_new, img) # 用 alpha 透明度模式拼接图片
if not os.path.exists('output'): # 检查输出目录是否存在,不存在则创建
os.mkdir('output')
3. 锐化图片
python
from PIL import ImageFilter, ImageEnhance
img = Image.open('lena_gray.tif').convert('L') # 打开灰度图像并转换为灰度图像
filter_blur = img.filter(ImageFilter.GaussianBlur(radius=3)) # 高斯滤波降低噪声
enhancer = ImageEnhance.Sharpness(filter_blur) # 创建 Sharpness 对象
sharped_img = enhancer.enhance(2.0) # 锐化增强
if not os.path.exists('output'): # 检查输出目录是否存在,不存在则创建
os.mkdir('output')
sharped_img.save(os.path.join('output','sharped.tif')) # 保存锐化后的图像
4. 均衡化图片
python
from skimage import data, exposure
import numpy as np
import matplotlib.pyplot as plt
img = data.moon() # 读取月牙图像
increasing_hist = exposure.equalize_adapthist(img, clip_limit=0.03) # 使用 CLAHE 直方图均衡化
fig, ax = plt.subplots(nrows=1, ncols=3, figsize=(8, 3)) # 设置子图大小
ax[0].imshow(img, cmap='gray') # 原始图像
ax[0].set_title('Original image')
ax[1].imshow(increasing_hist, cmap='gray') # 均衡化图像
ax[1].set_title('Histogram equalized image')
ax[2].hist(increasing_hist.flatten(), bins=256, range=[0, 256], histtype='stepfilled', color='black')
ax[2].set_xlim([0, 256]) # 设置 x 轴刻度范围
ax[2].set_ylim([0, np.max(increasing_hist)*1.1]) # 设置 y 轴刻度范围
ax[2].set_xlabel('Pixel intensity')
ax[2].set_ylabel('Number of pixels')
ax[2].set_title('Histogram of the histogram equalized image')
plt.tight_layout() # 自动调整子图间距
plt.show() # 显示图像
5. 图像增强
python
from PIL import ImageEnhance
from skimage import data
img = data.coins() # 读取硬币图像
enhancers = [ImageEnhance.Brightness(img),
ImageEnhance.Color(img),
ImageEnhance.Contrast(img)]
fig, axes = plt.subplots(nrows=3, ncols=2, figsize=(6, 8)) # 设置子图布局
titles = ["Brightness", "Color", "Contrast"] # 设置子图标题
images = [(enhancers[j*2]).enhance(1.5 + j) for j in range(3)] # 设置增强因子列表
for i, im in enumerate(images): # 遍历增强后图片
row, col = divmod(i, 2) # 根据索引计算子图的行列坐标
axes[row][col].imshow(im) # 在子图中绘制图像
axes[row][col].set_axis_off() # 关闭坐标轴
axes[row][col].set_title(titles[row]) # 添加子图标题
plt.tight_layout() # 自动调整子图间距
plt.show() # 显示图像
6. 形态学处理
python
from scipy import ndimage
import matplotlib.pyplot as plt
img = np.zeros((100, 100)).astype("uint8") # 创建 100x100 黑色图像
img[:50,:] = 255 # 第 1/4 置为白色
img[:, :50] = 255 # 第 1/4 置为白色
img[50:, :] = 255 # 第 1/4 置为白色
img[:, 50:] = 255 # 第 1/4 置为白色
eroded_img = ndimage.binary_erosion(img).astype("uint8") # 腐蚀处理
dilation_img = ndimage.binary_dilation(img).astype("uint8") # 膨胀处理
gradient_img = eroded_img - dilation_img # 形态学梯度
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(8, 8)) # 设置子图布局
axes[0][0].imshow(img, cmap="gray") # 原始图像
axes[0][0].set_title('Original binary image')
axes[0][1].imshow(eroded_img, cmap="gray") # 腐蚀图像
axes[0][1].set_title('Eroded image')
axes[1][0].imshow(dilation_img, cmap="gray") # 膨胀图像
axes[1][0].set_title('Dilated image')
axes[1][1].imshow(gradient_img, cmap="gray") # 形态学梯度图像
axes[1][1].set_title('Morphological gradient')
plt.tight_layout() # 自动调整子图间距
plt.show() # 显示图像