ESP-VISION图像处理算法全家桶:从滤波到AprilTag,14个API一次讲透

ESP-VISION图像处理算法全家桶:从滤波到AprilTag,14个API一次讲透 ESP-VISION图像处理算法全家桶从滤波到AprilTag14个API一次讲透文章目录ESP-VISION图像处理算法全家桶从滤波到AprilTag14个API一次讲透一、图像处理不是炫技是解决问题二、典型处理流水线三、滤波算法降噪是第一要务3.1 高斯滤波——标准降噪3.2 各滤波算法对比3.3 双边滤波保边去噪的王者四、阈值化与分割把目标从背景中分离4.1 二值化4.2 Blob检测——颜色追踪的核心4.3 形态学清理二值图像的利器五、特征检测找线、找圆、找矩形5.1 霍夫变换5.2 矩形检测5.3 模板匹配六、标记识别二维码、条形码、AprilTag6.1 二维码6.2 条形码仅ESP32-P46.3 AprilTag——6自由度位姿估计七、直方图与统计自动调参的秘密武器7.1 自动计算阈值7.2 快速统计八、一个完整的工业检测案例参考链接总结与下篇预告一、图像处理不是炫技是解决问题我见过不少嵌入式视觉项目明明一个高斯滤波二值化Blob检测就能搞定非得上深度学习模型。结果帧率从15fps掉到3fps功耗从0.5W飙到2W检测精度却没提升多少。ESP-VISION的图像处理模块继承自OpenMV的imlib库包含数十种经过嵌入式优化的算法。这些算法零依赖、纯C实现、内存占用可控在MCU上跑起来比你想的流畅得多。今天这篇文章我把14个最常用的API按场景分类讲透。二、典型处理流水线大多数视觉检测脚本遵循这个流程采集sensor.snapshot()预处理灰度/高斯/直方图分割二值化/阈值分析Blob/特征检测输出绘制/计数/控制三、滤波算法降噪是第一要务3.1 高斯滤波——标准降噪# 基础用法img.gaussian(ksize3)# 3×3高斯核标准降噪# 锐化模式img.gaussian(ksize3,unsharpTrue)# 反锐化掩膜增强边缘# 配合阈值一次遍历完成滤波二值化img.gaussian(ksize3,threshold128)# 滤波后大于128的像素变白3.2 各滤波算法对比算法适用场景速度效果mean()快速模糊降低噪声最快边缘模糊严重gaussian()标准降噪保留边缘快平衡好median()椒盐噪声中等去噪极佳边缘保留好bilateral()保边去噪慢平滑平面保留锐利边缘laplacian()边缘检测快二阶导数边缘响应morph()自定义卷积核取决于核大小灵活3.3 双边滤波保边去噪的王者# 双边滤波同时考虑空间距离和颜色相似度img.bilateral(ksize3,color_sigma0.1,space_sigma1)# space_sigma: 空间距离权重越大越模糊# color_sigma: 颜色相似度权重越大越不保边使用建议先用gaussian()快速试效果不够再用bilateral()。bilateral虽然效果好但计算量是gaussian的3-5倍。四、阈值化与分割把目标从背景中分离4.1 二值化# 颜色阈值二值化LAB空间img.binary([(30,100,15,127,15,127)])# 红色二值化# 灰度阈值grayimg.to_grayscale()gray.binary([(128,255)])# 大于128的变白# 多阈值同时跟踪多种颜色img.binary([red_threshold,blue_threshold,green_threshold])4.2 Blob检测——颜色追踪的核心blobsimg.find_blobs([red_threshold],# 颜色阈值列表pixels_threshold200,# 最小像素数过滤噪声area_threshold200,# 最小面积过滤小目标mergeTrue,# 合并重叠区域margin10# 合并边距)forblobinblobs:print(f质心: ({blob.cx()},{blob.cy()}))print(f外接框:{blob.rect()})# (x, y, w, h)print(f面积:{blob.area()})print(f圆度:{blob.roundness()})# 1完美圆print(f实心度:{blob.solidity()})# 面积/外接凸包面积print(f旋转角度:{blob.rotation_deg()})4.3 形态学清理二值图像的利器# 腐蚀消除小白点img.erode(ksize3)# 膨胀填充小黑洞img.dilate(ksize3)# 开运算先腐蚀再膨胀去噪点img.open(ksize3)# 闭运算先膨胀再腐蚀填孔洞img.close(ksize3)五、特征检测找线、找圆、找矩形5.1 霍夫变换# 找直线linesimg.find_lines(threshold1000,theta_margin25,rho_margin25)forlineinlines:img.draw_line(line.line())# 找圆circlesimg.find_circles(threshold2000,# 累加器阈值越高越严格x_margin10,y_margin10,# 合并近似重复的圆r_margin10,r_min10,r_max100# 半径范围)forcircleincircles:img.draw_circle(circle.x(),circle.y(),circle.r())5.2 矩形检测rectsimg.find_rects(threshold10000)forrectinrects:# rect.corners() 返回四个角点img.draw_rectangle(rect.rect())5.3 模板匹配# 加载模板templateimage.Image(template.pgm)# 匹配resultsimg.find_template(template,threshold0.7)forrinresults:img.draw_rectangle(r.rect())六、标记识别二维码、条形码、AprilTag6.1 二维码qrcodesimg.find_qrcodes()forqrinqrcodes:print(f内容:{qr.payload()})img.draw_rectangle(qr.rect())6.2 条形码仅ESP32-P4# 需要ZXing-C后端P4板级配置启用barcodesimg.find_barcodes()forbcinbarcodes:print(f类型:{bc.type()}, 内容:{bc.payload()})6.3 AprilTag——6自由度位姿估计# AprilTag检测最有含金量的功能tagsimg.find_apriltags()fortagintags:print(fID:{tag.id()}, Family:{tag.family()})print(f位置: ({tag.cx()},{tag.cy()}))print(f旋转:{tag.rotation()})# 如果提供了相机内参还能获取6自由度位姿# tag.x_translation(), tag.y_translation(), tag.z_translation()# tag.x_rotation(), tag.y_rotation(), tag.z_rotation()七、直方图与统计自动调参的秘密武器7.1 自动计算阈值# 获取直方图histimg.get_histogram()# 自动计算Otsu阈值thresholdhist.get_threshold()# Otsu算法print(f最优阈值:{threshold.value()})# 获取统计量statshist.get_statistics()print(f均值:{stats.mean()}, 中位数:{stats.median()})print(f标准差:{stats.stdev()}, 四分位数:{stats.lq()}-{stats.uq()})# 用统计量自动设置阈值binary_threshold(stats.median()-stats.stdev(),stats.median()stats.stdev())7.2 快速统计# 直接获取图像统计量不生成直方图statsimg.get_statistics()print(fL mean:{stats.l_mean()}, A mean:{stats.a_mean()}, B mean:{stats.b_mean()})print(fMin:{stats.min()}, Max:{stats.max()})八、一个完整的工业检测案例 零件缺陷检测 - 基于Blob形状分析 importsensor,image,timefrommicropythonimportconst# 配置MIN_AREAconst(200)MAX_AREAconst(5000)MIN_ROUNDNESSconst(0.7)# 圆度阈值MAX_HOLE_AREAconst(100)# 允许的最大孔洞sensor.reset()sensor.set_pixformat(sensor.RGB565)sensor.set_framesize(sensor.QVGA)sensor.skip_frames(time2000)clocktime.clock()definspect_part(img):检测零件缺陷# 1. 预处理灰度高斯滤波grayimg.to_grayscale()gray.gaussian(ksize3)# 2. 二值化Otsu自动阈值histgray.get_histogram()thresholdhist.get_threshold().value()gray.binary([(threshold,255)])# 3. 形态学去噪点填孔洞gray.open(ksize3)gray.close(ksize3)# 4. Blob检测blobsgray.find_blobs([],pixels_thresholdMIN_AREA)defects[]forblobinblobs:issueNoneifblob.area()MIN_AREA:issue太小elifblob.area()MAX_AREA:issue太大elifblob.roundness()MIN_ROUNDNESS:issuef不够圆({blob.roundness():.2f})elifblob.solidity()0.9:issuef有孔洞({blob.solidity():.2f})ifissue:img.draw_rectangle(blob.rect(),color(255,0,0))img.draw_string(blob.x(),blob.y()-10,issue,color(255,0,0))else:img.draw_rectangle(blob.rect(),color(0,255,0))returndefectswhileTrue:clock.tick()imgsensor.snapshot()defectsinspect_part(img)print(fFPS:{clock.fps():.1f}| 缺陷:{len(defects)})参考链接ESP-VISION 图像处理ESP-VISION API - image模块总结与下篇预告ESP-VISION的图像处理算法虽然多但大部分场景只需要掌握高斯→二值化→Blob这个三段式就够了。遇到复杂场景再加形态学或特征检测。记住先降噪再分割能ROI就不要全图能用灰度就不用RGB。下篇我们拆解摄像头流水线——sensor.snapshot()这一行代码背后从光子到image.Image经历了什么。作者码农阿虎关键词图像处理、滤波、Blob检测、AprilTag、霍夫变换、Otsu阈值