3. 图像处理基础:像素操作、图像滤波与形态学操作
各位同学,欢迎来到第三章。说实话,这一章是整个光效提取流程的「地基」。你后面做的所有炫酷效果——光晕分离、高光保留、边缘羽化——底层都离不开今天讲的这几个操作。
我刚开始做图像处理那会儿,总觉得滤波不就是「模糊一下」嘛,形态学不就是「膨胀腐蚀」嘛,有啥好学的?直到有一次做工业检测项目,光源不均匀导致光效提取总是带噪点,折腾了两天才发现是滤波参数没调对。嗯,从那以后我再也不敢小看这些基础操作了。
3.1 像素操作:你看到的图,其实是个数字矩阵
先问个问题:一张图片在计算机眼里是什么?
说白了,就是一个多维数组。灰度图是二维矩阵,每个元素值 0-255 代表亮度。彩色图是三维矩阵,多了一个通道维度(RGB)。
我习惯把像素操作分成三类:
- 点运算:每个像素独立处理,比如亮度调整、对比度拉伸
- 邻域运算:像素值由周围像素决定,比如滤波、边缘检测
- 几何变换:像素位置改变,比如旋转、缩放
光效提取中最常用的是点运算中的阈值分割和通道分离。举个例子,你要提取一个发光物体的高光区域,通常会在某个颜色通道上做阈值处理:
# 伪代码示例:基于亮度阈值提取高光区域
import numpy as np
def extract_highlight(image, threshold=200):
# 转为灰度
gray = np.mean(image, axis=2)
# 生成二值掩码
mask = (gray > threshold).astype(np.uint8) * 255
return mask
3.2 图像滤波:去噪与保留的博弈
滤波的本质是什么?用一个「窗口」扫过整张图,每个像素的新值由窗口内的邻居决定。你想想看,这其实就是一种「信息交换」。
3.2.1 高斯滤波:平滑但不生硬
高斯滤波用的是加权平均——离中心越近的像素权重越大,权重分布服从高斯函数。我做过对比测试:同样半径下,高斯滤波比均值滤波保留的边缘细节多 30% 左右。
| 参数 | 作用 | 典型值 |
|---|---|---|
| 核大小 (ksize) | 窗口尺寸,越大越模糊 | 3, 5, 7 |
| 标准差 (sigma) | 控制权重衰减速度 | 0.5 ~ 2.0 |
# OpenCV 实现高斯滤波
import cv2
img = cv2.imread('light_effect.jpg')
blurred = cv2.GaussianBlur(img, (5, 5), 1.0)
3.2.2 中值滤波:对付椒盐噪声的利器
中值滤波不取平均,取窗口内所有像素的中位数。这招对付椒盐噪声特别管用——因为噪声点的值要么极大要么极小,取中位数直接把它「踢出局」。
我有个实际案例:某次拍摄的光效图里有零星的高光噪点(类似盐粒噪声),用高斯滤波怎么调都去不干净,换成中值滤波,核大小设 3,一遍就干净了。
# 中值滤波
denoised = cv2.medianBlur(img, 3) # 核大小 3
核心区别:
- 高斯滤波:适合去除高斯噪声,保留边缘能力中等
- 中值滤波:适合去除椒盐噪声,保留边缘能力强
- 光效提取场景:先中值去噪,再高斯平滑,效果最好
3.3 形态学操作:让光效形状更「干净」
形态学操作处理的是二值图像(黑白图)。它的核心思想是用一个「结构元素」去探测图像中的形状。我常用它来修正光效提取后的掩码——去掉孤立噪点、填补空洞、平滑边缘。
3.3.1 膨胀与腐蚀:最基础的两个操作
膨胀:让白色区域「变胖」。结构元素扫过图像,只要窗口内有一个白点,中心就变白。
腐蚀:让白色区域「变瘦」。只有窗口内全是白点,中心才保留白色。
| 操作 | 效果 | 光效提取中的应用 |
|---|---|---|
| 膨胀 | 扩大高光区域,连接断裂部分 | 修复光效掩码中的细小断裂 |
| 腐蚀 | 缩小高光区域,去除孤立噪点 | 去掉误检的零星光点 |
# OpenCV 形态学操作
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dilated = cv2.dilate(mask, kernel, iterations=1)
eroded = cv2.erode(mask, kernel, iterations=1)
3.3.2 开运算与闭运算:组合拳更实用
实际项目中我很少单独用膨胀或腐蚀,而是用它们的组合:
- 开运算:先腐蚀后膨胀 → 去除小白点噪点,保持主体大小不变
- 闭运算:先膨胀后腐蚀 → 填补小空洞,连接邻近区域
我记得有一次做舞台灯光提取,光效掩码里全是细小的断裂(因为灯光闪烁导致亮度不均)。闭运算跑一遍,iterations=2,断裂全接上了,效果立竿见影。
# 开运算 & 闭运算
opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
closing = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
3.4 本章知识体系总览
下面这张图把本章的核心逻辑串起来了。你可以把它当作一个「操作决策树」:拿到一张光效图,先做什么后做什么,一目了然。
3.5 实战建议:先搭框架,再调参数
学完这一章,你可能会觉得「操作好多,记不住」。我的建议是:别死记参数,先记住每种操作能解决什么问题。
- 图像有噪点 → 滤波
- 光效区域有断裂 → 闭运算
- 光效区域有杂点 → 开运算
- 需要调整亮度范围 → 像素点运算