图像处理基础
图像处理是计算机视觉的核心,本章介绍OpenCV中三个基础而重要的处理技术:灰度化、二值化和形态学变换。
图像灰度化
灰度化是将彩色图像转换为灰度图像的过程,是许多高级图像处理算法的预处理步骤。
彩色图像
→
灰度图像
灰度化的方法
常见的灰度化方法包括:
1. 最大值法
gray = np.max(img, axis=2) # 取RGB三通道的最大值
2. 平均值法
gray = np.mean(img, axis=2).astype(np.uint8) # 取RGB三通道的平均值
3. 加权平均法(最常用)
# OpenCV的默认方法: 0.299*R + 0.587*G + 0.114*B
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
小贴士
加权平均法考虑了人眼对不同颜色的敏感度:对绿色最敏感(0.587),对蓝色最不敏感(0.114)。
灰度化比较表
方法 | 公式 | 优势 | 劣势 |
---|---|---|---|
最大值法 | max(R,G,B) | 简单快速 | 丢失颜色信息多 |
平均值法 | (R+G+B)/3 | 直观易实现 | 不符合人眼感知 |
加权平均法 | 0.299R+0.587G+0.114B | 符合人眼感知 | 计算稍复杂 |
图像二值化
二值化将灰度图像转换为只有黑(0)和白(255)两种像素值的图像,常用于提取目标、OCR等任务。
灰度图像
→
二值图像
全局二值化
全局二值化是使用一个固定的阈值将图像分为前景和背景。
# 简单二值化,阈值为127
ret, binary = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY)
二值化类型
类型 | 函数常量 | 效果 |
---|---|---|
二值化 | cv2.THRESH_BINARY | 大于阈值→255,小于阈值→0 |
反二值化 | cv2.THRESH_BINARY_INV | 大于阈值→0,小于阈值→255 |
截断 | cv2.THRESH_TRUNC | 大于阈值→阈值,小于阈值→保持原值 |
阈值为0 | cv2.THRESH_TOZERO | 大于阈值→保持原值,小于阈值→0 |
反阈值为0 | cv2.THRESH_TOZERO_INV | 大于阈值→0,小于阈值→保持原值 |
THRESH_BINARY
THRESH_BINARY_INV
THRESH_TRUNC
OTSU阈值法
当不确定使用什么阈值时,OTSU方法可以自动确定最优阈值:
# OTSU自动阈值二值化
ret, binary = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
OTSU原理
OTSU算法通过计算类间方差最大化来自动寻找最佳阈值,非常适合双峰图像(前景和背景对比明显)。
自适应二值化
在照明不均匀的情况下,全局二值化效果不佳,此时可以使用自适应二值化。
# 自适应阈值二值化
binary = cv2.adaptiveThreshold(
gray_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 11, 2
)
不均匀照明的图像
↙️
全局
↘️
自适应
全局二值化
(信息丢失)
自适应二值化
(细节保留)
自适应二值化参数
参数 | 说明 | 选项 |
---|---|---|
adaptiveMethod | 自适应方法 | ADAPTIVE_THRESH_MEAN_C : 邻域均值 ADAPTIVE_THRESH_GAUSSIAN_C : 高斯加权均值 |
blockSize | 邻域大小 | 奇数值(3,5,7...) |
C | 从均值减去的常数 | 通常为正值,用于微调阈值 |
形态学变换
形态学变换是基于图像形状的一系列操作,主要应用于二值图像。常用于去噪、连接断开的区域、查找图像中的明显凸起或凹陷等。
原始图像
→
形态学处理
基本概念
形态学操作的基础是结构元素(kernel),它决定了操作的效果。
结构元素 (3x3)
常见的形态学操作
1. 膨胀 (Dilation)
膨胀操作将图像中的物体扩大,可用于连接断开的部分。
kernel = np.ones((5,5), np.uint8)
dilation = cv2.dilate(binary_img, kernel, iterations=1)
原始图像
→
膨胀后
2. 腐蚀 (Erosion)
腐蚀操作将图像中的物体缩小,可用于去除小的噪点。
kernel = np.ones((5,5), np.uint8)
erosion = cv2.erode(binary_img, kernel, iterations=1)
原始图像
→
腐蚀后
3. 开运算 (Opening)
开运算是先腐蚀后膨胀,可以去除小的噪点,同时保持原有物体大小基本不变。
kernel = np.ones((5,5), np.uint8)
opening = cv2.morphologyEx(binary_img, cv2.MORPH_OPEN, kernel)
原始图像
→
开运算后
4. 闭运算 (Closing)
闭运算是先膨胀后腐蚀,可以填充物体内的小洞或连接邻近的物体。
kernel = np.ones((5,5), np.uint8)
closing = cv2.morphologyEx(binary_img, cv2.MORPH_CLOSE, kernel)
原始图像
→
闭运算后
5. 梯度 (Gradient)
形态学梯度是膨胀图像减去腐蚀图像的结果,用于突出物体的边缘。
kernel = np.ones((5,5), np.uint8)
gradient = cv2.morphologyEx(binary_img, cv2.MORPH_GRADIENT, kernel)
原始图像
→
梯度
高级形态学操作
1. 顶帽 (Top Hat)
顶帽运算是原始图像减去开运算的结果,用于突出比周围区域更亮的区域。
tophat = cv2.morphologyEx(gray_img, cv2.MORPH_TOPHAT, kernel)
2. 黑帽 (Black Hat)
黑帽运算是闭运算减去原始图像的结果,用于突出比周围区域更暗的区域。
blackhat = cv2.morphologyEx(gray_img, cv2.MORPH_BLACKHAT, kernel)
原始图像
顶帽运算
原始图像
黑帽运算
形态学操作的应用
- 噪点去除:使用开运算去除小的亮点噪声
- 填充孔洞:使用闭运算填充物体内的小孔洞
- 边缘检测:使用形态学梯度突出物体边缘
- 图像分割:结合顶帽和黑帽运算提高不均匀照明下的图像分割效果
- 骨架提取:通过多次腐蚀提取物体的"骨架"
实用技巧
- 对于不同的应用场景,尝试不同形状和大小的结构元素
- 通过调整
iterations
参数可以增强形态学操作的效果 - 复杂的形态学操作可以通过组合基本操作实现
实际应用流程
以下是一个简单的图像预处理流程,结合了灰度化、二值化和形态学操作:
import cv2
import numpy as np
# 读取图像
img = cv2.imread('image.jpg')
# 1. 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2. 高斯模糊 (减少噪声)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# 3. 二值化
_, binary = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 4. 形态学操作
kernel = np.ones((3, 3), np.uint8)
# 开运算去除噪点
opening = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)
# 闭运算填充小孔
result = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel)
# 显示结果
cv2.imshow('Original', img)
cv2.imshow('Result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
通过这些基本的图像处理技术,您可以为更高级的计算机视觉任务准备数据,如物体检测、特征提取等。