4. 图像预处理(上):色彩空间转换与图像滤波

各位同学,大家好。今天我们进入图像预处理的第一部分。说实话,在农田环境里,摄像头采集到的原始图像,基本没法直接用。光线变化、尘土、枝叶晃动,各种干扰。所以预处理这一步,是决定后续检测成败的关键。

我个人习惯把预处理分成两大块:色彩空间转换图像滤波。今天咱们就把这两块的核心讲透。

4.1 色彩空间转换:从RGB到HSV,再到灰度

先问大家一个问题:为什么我们不用RGB直接做障碍物检测?

RGB三个通道,说白了就是红绿蓝的亮度叠加。但农田里的光照变化太剧烈了——早上是暖色调,中午是冷色调,树荫下又偏暗。RGB对光照变化特别敏感,同一个绿色物体,在阳光下和阴影里,RGB值能差好几倍。

所以我们需要更鲁棒的色彩空间。

4.1.1 HSV色彩空间

HSV把颜色拆成三个分量:色调(Hue)饱和度(Saturation)明度(Value)。说白了,H决定是什么颜色,S决定颜色有多纯,V决定有多亮。

我在项目中遇到过这样一个场景:要检测田里的红色障碍物(比如警示桩)。用RGB做阈值分割,上午调好的参数,下午就失效了。换成HSV后,只对H通道做范围筛选,S和V稍微放宽,效果稳定多了。

核心经验:在农田视觉中,HSV比RGB更适合做基于颜色的分割。因为H通道对光照变化不敏感。

下面是一个OpenCV的转换示例:

import cv2
import numpy as np

# 读取图像
img = cv2.imread('field.jpg')

# RGB转HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# 定义绿色的范围(在HSV中)
lower_green = np.array([35, 40, 40])
upper_green = np.array([85, 255, 255])

# 提取绿色区域
mask = cv2.inRange(hsv, lower_green, upper_green)
result = cv2.bitwise_and(img, img, mask=mask)

小技巧:OpenCV中HSV的H范围是0-180,不是0-360。绿色大约在35-85之间。这个范围我调了不下50次才找到最佳值。

4.1.2 灰度转换

灰度图,说白了就是扔掉颜色信息,只保留亮度。为什么需要它?因为很多算法(比如边缘检测、特征点提取)都是在灰度图上跑的。颜色信息反而会引入噪声。

转换公式很简单:Gray = 0.299*R + 0.587*G + 0.114*B。为什么权重不一样?因为人眼对绿色最敏感,对蓝色最不敏感。

嗯,这里要注意:不要直接用(R+G+B)/3做平均,那样会丢失对比度。我在早期项目里犯过这个错,结果边缘检测效果惨不忍睹。

# 灰度转换
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 或者直接读取为灰度
gray = cv2.imread('field.jpg', cv2.IMREAD_GRAYSCALE)

4.2 图像滤波:去噪是门手艺

农田里的噪声来源太多了:CMOS传感器的热噪声、风吹草动产生的随机像素、灰尘颗粒。滤波的目的就是把这些噪声干掉,同时尽量保留边缘信息。

我常用的三种滤波:高斯、中值、双边。各有各的脾气。

4.2.1 高斯滤波

高斯滤波,说白了就是用邻域像素的加权平均来替换中心像素。权重由高斯分布决定——离中心越近,权重越大。

它适合处理高斯噪声,也就是那种随机出现的、幅度不大的噪声。比如传感器在弱光下产生的噪点。

# 高斯滤波
# (5,5)是核大小,sigmaX是标准差
blurred = cv2.GaussianBlur(img, (5, 5), 1.5)

避坑指南:核大小必须是奇数。我曾经设成(4,4),程序直接报错。另外,核越大,图像越模糊,边缘信息丢失越严重。在农田场景里,我一般用(3,3)或(5,5),再大就过度平滑了。

4.2.2 中值滤波

中值滤波,就是把邻域内的像素排序,取中间值。它对椒盐噪声特别有效——就是那种黑白点状的噪声。

为什么?你想想看,椒盐噪声的像素值要么极大要么极小,排序后肯定被挤到两端,中间值大概率是正常像素。

我在处理无人机拍摄的农田图像时,经常遇到因为传输丢包产生的椒盐噪声。中值滤波一上,效果立竿见影。

# 中值滤波
# 参数是核大小,必须是奇数
median = cv2.medianBlur(img, 5)

个人经验:中值滤波的核大小不要超过7。我试过9x9的核,结果图像边缘全糊了,像水彩画一样。3x3或5x5就够用。

4.2.3 双边滤波

双边滤波,这是我最喜欢的一种。它能在去噪的同时,保留边缘

原理有点意思:它不光考虑空间距离(像高斯滤波那样),还考虑像素值的差异。如果两个像素的亮度差太大,就算挨得近,也不参与平均。这样边缘就不会被模糊掉。

在农田场景里,比如要检测田埂和作物之间的边界,双边滤波就特别合适。高斯滤波会把边界也抹掉,双边滤波不会。

# 双边滤波
# d:邻域直径
# sigmaColor:颜色空间标准差
# sigmaSpace:空间坐标标准差
bilateral = cv2.bilateralFilter(img, 9, 75, 75)

关键参数:sigmaColor控制颜色相似度的阈值。值越大,越多的颜色差异会被忽略。sigmaSpace控制空间距离的影响。我一般从(9, 75, 75)开始调,然后根据效果微调。

4.3 三种滤波的对比

为了方便大家选择,我整理了一个表格:

滤波类型 适用噪声 边缘保留 速度 推荐场景
高斯滤波 高斯噪声 光照均匀的农田
中值滤波 椒盐噪声 中等 中等 无人机传输图像
双边滤波 混合噪声 需要保留边缘的场景

嗯,这里要提醒一句:双边滤波虽然效果好,但计算量是高斯滤波的几十倍。在嵌入式设备上,如果帧率要求高,我建议先用高斯滤波快速处理,只在关键区域用双边滤波。

4.4 实战建议:预处理流程

我个人在农田项目中的标准流程是这样的:

  1. 先转灰度或HSV:根据任务需求选择。如果是颜色分割,用HSV;如果是边缘检测,用灰度。
  2. 再滤波去噪:优先尝试高斯滤波(速度快)。如果噪声是椒盐型,换中值。如果边缘信息重要,上双边。
  3. 最后做形态学操作:这个我们下一章讲。

曾经踩过的坑:有一次我直接对RGB图像做滤波,然后才转HSV。结果滤波把颜色边界模糊了,HSV分割出来的区域全是锯齿。后来改成先转HSV再滤波,效果好了很多。顺序很重要!

好了,今天的内容就到这里。色彩空间转换和滤波是预处理的基础,但也是决定成败的关键。下一章我们讲形态学操作和直方图均衡化,到时候会用到今天学的知识。

大家回去可以试试:找一张农田照片,分别用三种滤波处理,看看效果差异。有什么问题,我们下节课讨论。