K230基础-几种图像处理方式
第十六章 几种图像处理方式-K230图像增强与特征提取
🎯 本章目标:
掌握 K230(CanMV)平台上image
模块提供的多种图像处理方法,学会对摄像头采集的图像进行灰度化、二值化、滤波、边缘检测、形态学操作、几何变换等处理,为后续的 AI 推理、目标识别、机器视觉应用提供预处理支持。
1. 图像处理基础
1.1 图像处理的作用
在嵌入式视觉系统中,图像处理用于:
- 降噪:提升图像质量
- 增强对比度:便于特征提取
- 简化数据:降低 AI 推理复杂度
- 特征提取:为传统算法(非 AI)提供输入
✅ 典型流程:
摄像头采集 → 图像预处理 → AI 推理 / 特征分析 → 决策输出
1.2 image
模块核心函数
import image
K230 的 image
模块提供了丰富的图像处理功能,所有操作均作用于 image.Image
对象。
2. 常用图像处理方法详解
2.1 灰度化:to_grayscale()
将彩色图像转换为灰度图(单通道)。
img = sensor.snapshot()img.to_grayscale()
- 用途:人脸检测、OCR、边缘检测前的预处理
- 优势:减少数据量,提升处理速度
- 内存节省:RGB565(2B/像素)→ GRAYSCALE(1B/像素)
✅ 建议:对仅需亮度信息的场景优先转灰度。
2.2 二值化:binary()
将图像转换为黑白二值图(0 或 255)。
# 定义阈值:[(L, H)],L 和 H 为灰度值(0~255)
img.binary([(128, 255)])
- 用途:文档扫描、数字识别、运动检测
- 关键:选择合适的阈值
自动阈值示例
img.to_grayscale()
hist = img.get_histogram()
threshold = hist.get_threshold()
img.binary([threshold.value()])
2.3 反色:invert()
将图像像素值取反(255 - pixel)。
img.invert()
- 用途:白底黑字 → 黑底白字(便于 blob 检测)
- 示例:检测白色目标在深色背景上
2.4 滤波:morph()
与内置滤波器
自定义卷积核
# 锐化滤波
kernel = [-1, -1, -1,-1, 9, -1,-1, -1, -1]
img.morph(3, kernel)
常用滤波器
操作 | 代码 |
---|---|
均值滤波(降噪) | img.mean(3) |
中值滤波(去椒盐噪声) | img.median(3) |
高斯滤波 | img.gaussian(3) |
腐蚀(Erode) | img.erode(1) |
膨胀(Dilate) | img.dilate(1) |
✅ 形态学操作(Erode/Dilate)用于去除噪声或连接断点。
2.5 边缘检测
Canny 边缘检测
img.find_edges(image.EDGE_CANNY, threshold=(50, 80))
- 参数:
(low_threshold, high_threshold)
- 用途:轮廓提取、形状识别
Sobel 边缘检测
img.find_edges(image.EDGE_SOBEL)
- 仅检测梯度,不进行非极大抑制
- 更快,但边缘较粗
2.6 几何变换
缩放:resize()
img.resize(160, 120)
- 用途:调整图像大小以匹配模型输入
- AI 推理前常用操作
旋转:rotation_corr()
img.rotation_corr(theta=90) # 旋转90度
- 参数:
theta
:旋转角度zoom
:缩放因子x_translation
,y_translation
:平移
✅ 用途:校正摄像头安装角度
2.7 直方图与自动调节
获取直方图
hist = img.get_histogram()
print("直方图:", hist)
自动对比度增强
img.histeq()
- 直方图均衡化:提升图像对比度
- 用途:低对比度图像增强
3. 实战项目一:运动目标检测(帧差法)
import sensor
import image
import timesensor.reset()
sensor.set_pixformat(sensor.GRAYSCALE)
sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(time=2000)# 获取背景帧
bg = sensor.snapshot()while True:img = sensor.snapshot()# 与背景做差值diff = img.difference(bg)# 二值化diff.binary([(30, 255)])# 形态学滤波去噪diff.erode(1)diff.dilate(1)# 查找连通域blobs = diff.find_blobs([(100, 255)])for b in blobs:if b.pixels() > 100: # 过滤小区域img.draw_rectangle(b.rect(), color=(255, 0, 0))img.draw_cross(b.cx(), b.cy(), color=(0, 255, 0))print(f"运动目标: x={b.cx()}, y={b.cy()}, size={b.pixels()}")# 慢速更新背景(模拟动态背景)if time.ticks_ms() % 5000 == 0:bg = img.copy()
4. 实战项目二:数字/字符识别预处理
import sensor
import imagesensor.reset()
sensor.set_pixformat(sensor.GRAYSCALE)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time=2000)while True:img = sensor.snapshot()# 预处理流程img.histeq() # 增强对比度img.gaussian(3) # 高斯滤波降噪img.binary([(120, 255)]) # 二值化img.invert() # 反色(黑底白字)# 可继续进行字符分割、模板匹配等
✅ 输出:清晰的二值化字符图像,适合 OCR 或模板匹配。
5. 实战项目三:边缘轮廓识别
import sensor
import imagesensor.reset()
sensor.set_pixformat(sensor.GRAYSCALE)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time=2000)while True:img = sensor.snapshot()# 边缘检测edges = img.find_edges(image.EDGE_CANNY, threshold=(50, 80))# 查找轮廓contours = img.find_contours(threshold=50)# 绘制轮廓for c in contours:img.draw_line(c, color=(255, 0, 0))# 可进一步识别形状(矩形、圆等)
6. 高级技巧与优化
6.1 链式处理
img.to_grayscale() \.histeq() \.gaussian(3) \.binary([(100, 255)])
✅ 优点:代码简洁,逻辑清晰
6.2 局部处理
# 仅对图像某区域处理
roi = (80, 60, 160, 120) # x, y, w, h
img.binary([(128, 255)], roi=roi)
✅ 用途:只处理感兴趣区域(ROI),提升效率
6.3 条件处理
if img.format() != sensor.GRAYSCALE:img.to_grayscale()
✅ 建议:处理前检查图像状态
7. 常见问题与调试
❌ 问题1:binary()
效果差
解决:
- 调整阈值范围
- 先
histeq()
增强对比度- 使用
get_histogram()
辅助选择阈值
❌ 问题2:find_edges()
无输出
排查:
- 是否为灰度图?
- 阈值是否过高?
- 图像是否模糊?
❌ 问题3:形态学操作后图像断裂
解决:
- 腐蚀后用膨胀连接(开运算)
- 控制迭代次数(
erosion(1)
而非erosion(3)
)
8. 性能与内存管理
操作 | 耗时(QQVGA) |
---|---|
to_grayscale | ~1ms |
binary | ~2ms |
gaussian(3) | ~5ms |
find_edges | ~10ms |
find_blobs | ~8ms |
✅ 建议:
- 高帧率应用中减少复杂处理
- 优先使用硬件加速功能(如 JPEG 解码)
✅ 本章你已掌握:
- 灰度化、二值化、反色
- 滤波(均值、中值、高斯、形态学)
- 边缘检测(Canny、Sobel)
- 几何变换(缩放、旋转)
- 直方图与自动增强
- 运动检测、轮廓识别实战