Skip to main content

图像处理基础

图像处理是计算机视觉的核心,本章介绍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大于阈值→阈值,小于阈值→保持原值
阈值为0cv2.THRESH_TOZERO大于阈值→保持原值,小于阈值→0
反阈值为0cv2.THRESH_TOZERO_INV大于阈值→0,小于阈值→保持原值
THRESH_BINARY
2550阈值
THRESH_BINARY_INV
2550阈值
THRESH_TRUNC
阈值0阈值

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)
原始图像
顶帽运算
原始图像
黑帽运算

形态学操作的应用

  1. 噪点去除:使用开运算去除小的亮点噪声
  2. 填充孔洞:使用闭运算填充物体内的小孔洞
  3. 边缘检测:使用形态学梯度突出物体边缘
  4. 图像分割:结合顶帽和黑帽运算提高不均匀照明下的图像分割效果
  5. 骨架提取:通过多次腐蚀提取物体的"骨架"
实用技巧
  • 对于不同的应用场景,尝试不同形状和大小的结构元素
  • 通过调整 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()

通过这些基本的图像处理技术,您可以为更高级的计算机视觉任务准备数据,如物体检测、特征提取等。