边缘检测
1.实验目的
实现K230对图像进行Canny边缘检测。
2.实验原理
2.1 原理解析
Canny 边缘检测是一种经典的图像处理算法,用于检测图像中的“边缘”,即像素值变化明显的区域。它是由 John F. Canny 在 1986 年提出的,至今仍是最广泛使用的边缘检测算法之一。
Canny 边缘检测的五个步骤
- 高斯滤波(Gaussian Filter)——平滑图像去噪
- 目的:去除图像中的噪声,以避免检测出伪边缘。
- 方法:使用高斯核对图像进行卷积(模糊处理),相当于对图像“柔化”。
- 示意图:原图像 → 平滑模糊图像。
噪声越小,边缘检测越准确;否则噪声也会被误认为是边缘。
- 计算图像梯度(Sobel 算子)——提取边缘强度和方向
-
目的:检测图像中像素值的急剧变化区域(即边缘)。
-
方法:
-
使用 Sobel 算子分别计算 水平方向 Gx 和 垂直方向 Gy 的灰度变化。
-
计算每个像素的梯度幅度(强度):
-
计算梯度方向(边缘的方向):
-
- 非极大值抑制(NMS)——细化边缘
- 目的:保留边缘的中心像素,去除边缘上的非最大值,使边缘线更细、更准确。
- 方法:
- 沿着梯度方向检查像素是否为局部最大值。
- 如果不是局部最大值,则将该像素设为 0。
举例:一个边缘是粗的白线,非极大值抑制后只保留中间那一列像素点,形成清晰细线。
- 双阈值检测(Hysteresis Thresholding)——筛选强边缘和弱边缘
- 目的:区分“真正的边缘”、“可能的边缘”和“非边缘”。
- 方法:
- 设置两个阈值:高阈值
T_high
和低阈值T_low
。 - 强边缘:梯度值 > 高阈值 → 保留;
- 弱边缘:梯度值在
T_low ~ T_high
之间 → 保留,但只有当它与强边缘相连时; - 非边缘:梯度值 < 低阈值 → 丢弃。
- 设置两个阈值:高阈值
- 边缘连接(Edge Tracking by Hysteresis)——保持边缘连续性
- 目的:连接弱边缘与强边缘,使边缘线不间断。
- 方法:
- 追踪所有强边缘;
- 如果一个弱边缘像素与强边缘连接,则认为它也是有效边缘;
- 否则将其丢弃。
2.2 API
image.find_edges(edge_type[, threshold])
将图像变为黑白,仅将边缘保留为白色像素。
image.EDGE_SIMPLE - 简单的阈值高通滤波算法 image.EDGE_CANNY - Canny边缘检测算法 threshold 是一个包含一个低阈值和一个高阈值的二值元组。您可以通过调整该值来控制边缘质量。
默认为 (100, 200)。
仅支持灰度图像。
3.代码解析
摄像头初始化函数
def camera_init():
定义摄像头初始化函数。
global sensor
声明使用全局变量 sensor
。
sensor = Sensor(width=DETECT_WIDTH, height=DETECT_HEIGHT)
创建一个 Sensor
对象,分辨率为 800x480
,开始进行视频采集准备。
sensor.reset()
重置传感器硬件(相当于重启摄像头,清空内部状态)。
sensor.set_framesize(width=DETECT_WIDTH, height=DETECT_HEIGHT)
设置通道 0 的图像尺寸。
sensor.set_pixformat(Sensor.GRAYSCALE)
设置图像格式为灰度图(Canny 算子适用于单通道图像)。
初始化虚拟显示器
Display.init(Display.ST7701, width=DETECT_WIDTH, height=DETECT_HEIGHT, fps=60, to_ide=True)
初始化虚拟显示器(ST7701 模式),支持在 IDE 显示图像;
设置分辨率、帧率(60 FPS);
to_ide=True
表示同时输出到 IDE 中。
初始化媒体资源管理器
MediaManager.init()
初始化媒体资源管理器(底层分配缓存区,支持 DMA 等)。
启动摄像头
sensor.run()
- 启动摄像头采集。
摄像头资源释放函数
def camera_deinit():
global sensor
sensor.stop()
停止摄像头采集。
Display.deinit()
关闭显示输出设备。
os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)
通知 IDE 当前模块可以进入休眠状态。
MediaManager.deinit()
释放媒体资源池(避免内存泄漏或冲突)。
图像采集与处理主循环
dect_img = sensor.snapshot()