第三章:图像预处理——噪声滤波、图像增强与ROI提取

各位同学,大家好。欢迎来到《红外检测叶片温度异常分析与诊断》的第三讲。

上一章我们聊了红外图像的特点,说白了就是一张“温度分布图”。但现实很骨感——你拿到的原始图像,往往充满了噪声,对比度也差。直接分析?那结果肯定一塌糊涂。

所以,图像预处理这一步,是绕不开的。我个人习惯把预处理比作“给照片化妆”:先去掉脸上的痘印(噪声),再调亮肤色(增强),最后只盯着眼睛看(ROI提取)。

今天我们就来拆解这三个核心步骤。

3.1 噪声滤波:让图像“干净”起来

红外相机采集时,受传感器温度、电路干扰等因素影响,图像里总会有一些“雪花点”。这些点就是噪声。不处理的话,后续的温度分析会严重失真。

我常用的滤波方法有两种:中值滤波和高斯滤波。它们各有各的脾气。

3.1.1 中值滤波——专治“椒盐噪声”

中值滤波的原理很简单:把每个像素点的值,替换成它周围邻域内所有像素的中位数

为什么用中位数?因为椒盐噪声(那种黑白点)的像素值要么极大要么极小,取中位数就能把它们“剔除”掉。

我在项目中遇到过:有一次在温室大棚里检测叶片,因为环境湿度大,红外图像上全是细小的白点。用中值滤波一处理,叶片轮廓立刻清晰了。嗯,这里要注意:中值滤波对高斯噪声(那种均匀分布的模糊噪声)效果一般,别用错地方。

代码示例(OpenCV):

import cv2
import numpy as np

# 读取红外图像(灰度图)
img = cv2.imread('leaf_thermal.jpg', 0)

# 中值滤波,核大小设为5(奇数)
img_median = cv2.medianBlur(img, 5)

cv2.imshow('Original', img)
cv2.imshow('Median Filtered', img_median)
cv2.waitKey(0)
我的小技巧: 核大小一般选3、5、7。选太大,图像会变模糊,细节丢失。我通常从5开始试,效果不好再调。

3.1.2 高斯滤波——对付“高斯噪声”

高斯滤波用的是加权平均。它认为:离中心点越近的像素,贡献越大;越远的,贡献越小。权重服从高斯分布(也就是正态分布)。

说白了,它比中值滤波更“平滑”,适合处理那种均匀的、像蒙了一层雾的噪声。

我曾经犯过一个错:把高斯滤波用在椒盐噪声上,结果噪声点被“抹开”了,变成一片模糊区域,反而更难处理。所以,选对方法很重要。

代码示例:

# 高斯滤波,核大小(5,5),标准差sigmaX=0(自动计算)
img_gaussian = cv2.GaussianBlur(img, (5, 5), 0)

cv2.imshow('Gaussian Filtered', img_gaussian)
避坑指南: 高斯滤波的核大小必须是奇数,且两个方向可以不同(比如(5,3))。但一般用正方形核就够了。

3.2 图像增强:让温度差异“显眼”起来

滤波之后,图像干净了,但可能还是灰蒙蒙的。为什么?因为红外图像的像素值往往集中在某个狭窄的区间(比如120-150),对比度很低。

这时候就需要图像增强。我最常用的方法是直方图均衡化

3.2.1 直方图均衡化——拉伸对比度

直方图均衡化的核心思想:把原始图像的灰度分布,拉伸成均匀分布。原本集中在120-150的像素,会被映射到0-255整个范围。

效果就是:暗的地方更暗,亮的地方更亮,细节就出来了。

我记得有一次,在分析水稻叶片的温度时,原始图像几乎看不出温差。均衡化之后,叶脉和叶缘的温度差异一目了然。你想想看,如果没有这一步,后面的分析根本无从下手。

代码示例:

# 直方图均衡化
img_eq = cv2.equalizeHist(img_gaussian)

cv2.imshow('Equalized', img_eq)
重要提醒: 直方图均衡化会增强噪声。所以一定要先滤波,再增强。顺序别搞反了。

3.3 ROI区域提取:只关注“叶片”本身

整张红外图像里,可能只有一小块是叶片,其他都是背景(土壤、花盆、支架)。如果全图分析,计算量大,而且背景噪声会干扰结果。

所以,我们要提取ROI(Region of Interest,感兴趣区域)。说白了,就是只盯着叶片看。

3.3.1 基于阈值的ROI提取

红外图像中,叶片和背景的温度通常不同。我们可以设定一个温度阈值,把高于(或低于)某个值的像素提取出来。

比如,叶片温度在28-32°C,背景在22-25°C。那我们可以设定阈值28°C,提取所有高于28°C的区域。

我个人的习惯是:先用直方图看看像素分布,找到明显的“波谷”,那个位置就是最佳阈值。

代码示例:

# 假设图像是8位灰度图,像素值0-255对应温度0-50°C
# 设定阈值:对应28°C -> 像素值 = 28/50 * 255 ≈ 143
_, roi = cv2.threshold(img_eq, 143, 255, cv2.THRESH_BINARY)

cv2.imshow('ROI', roi)
进阶技巧: 如果光照不均匀,全局阈值效果不好。可以试试自适应阈值(cv2.adaptiveThreshold),它会根据局部区域自动调整阈值。

3.3.2 形态学操作——让ROI更“干净”

阈值提取后,ROI区域可能有一些小孔洞或毛刺。这时候可以用形态学操作(腐蚀、膨胀)来修整。

我一般先腐蚀去掉小噪点,再膨胀恢复叶片大小。

kernel = np.ones((5,5), np.uint8)
roi_cleaned = cv2.morphologyEx(roi, cv2.MORPH_CLOSE, kernel)

知识体系总览

下面这张图,是我自己画的预处理流程。你可以把它当作一个“检查清单”。

红外图像预处理流程 原始红外图像 噪声滤波 中值/高斯滤波 图像增强 直方图均衡化 ROI区域提取 阈值+形态学 关键点总结: 1. 先滤波,后增强,顺序不能乱 2. 中值滤波去椒盐噪声,高斯滤波去高斯噪声 3. 直方图均衡化能有效提升对比度,但会放大噪声 4. ROI提取时,阈值选择是关键,建议先看直方图 5. 形态学操作(腐蚀/膨胀)能让ROI更规整

本章小结

图像预处理,说白了就是三步走:去噪、增强、提ROI。每一步都有它的道理,也有它的坑。

我个人建议:在实际项目中,不要一上来就套用固定参数。多试试不同的核大小、阈值,看看效果。毕竟,每一张红外图像都有自己的“脾气”。

好了,这一章就到这里。记住:预处理做得好,后续分析才能事半功倍。


专注资料整理