第三章:图像预处理——噪声滤波、图像增强与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.1.2 高斯滤波——对付“高斯噪声”
高斯滤波用的是加权平均。它认为:离中心点越近的像素,贡献越大;越远的,贡献越小。权重服从高斯分布(也就是正态分布)。
说白了,它比中值滤波更“平滑”,适合处理那种均匀的、像蒙了一层雾的噪声。
我曾经犯过一个错:把高斯滤波用在椒盐噪声上,结果噪声点被“抹开”了,变成一片模糊区域,反而更难处理。所以,选对方法很重要。
代码示例:
# 高斯滤波,核大小(5,5),标准差sigmaX=0(自动计算)
img_gaussian = cv2.GaussianBlur(img, (5, 5), 0)
cv2.imshow('Gaussian Filtered', img_gaussian)
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)
3.3.2 形态学操作——让ROI更“干净”
阈值提取后,ROI区域可能有一些小孔洞或毛刺。这时候可以用形态学操作(腐蚀、膨胀)来修整。
我一般先腐蚀去掉小噪点,再膨胀恢复叶片大小。
kernel = np.ones((5,5), np.uint8)
roi_cleaned = cv2.morphologyEx(roi, cv2.MORPH_CLOSE, kernel)
知识体系总览
下面这张图,是我自己画的预处理流程。你可以把它当作一个“检查清单”。
本章小结
图像预处理,说白了就是三步走:去噪、增强、提ROI。每一步都有它的道理,也有它的坑。
我个人建议:在实际项目中,不要一上来就套用固定参数。多试试不同的核大小、阈值,看看效果。毕竟,每一张红外图像都有自己的“脾气”。
好了,这一章就到这里。记住:预处理做得好,后续分析才能事半功倍。