**非常详细的视频和文字教程,讲解常见的openmv教程包括 巡线、物体识别、圆环识别、阈值自动获取等。非常适合学习openmv、K210、K230等项目
视频合集链接在
openmv教程合集 openmv入门到项目开发 openmv和STM32通信 openmv和opencv区别 openmv巡线 openmv数字识别教程LCD
专刊openmv视觉文章链接:
https://blog.csdn.net/qq_46187594/category_12900902.html
5-识别可能的色块的区域缩放-到和模板大小一样
下面的思路和程序参考程欢欢大佬的作品(大佬视频中使用的他的板子,所以程序是想要修改的 下面会提供修改好的,还有大佬是使用PS整理的想要模板,后面我会演示使用更简单的方法.视频里面也有对优化思路的讲解可以看一下): https://www.bilibili.com/video/BV1G3411t7HX/?share_source=copy_web&vd_source=f5d5850ab773377dff308188468fbc77
程序思路:
先找色块找到可能是数字的黑色色块,
做缩放把黑色色块尺寸缩放到和模板一样,
简单方法制作统一40像素模板:
使用QQ或者微信等截图工具把之前1-8数字截图小一些,如下数字整个刚刚在框里面
然后使用win10系统自带的编辑图片工具打开(win10是画图工具这个软件,不确定win7或者win11里面编辑图片的有这个功能,如果没有自行下载ps等更专业软件学习如何修改大小)
然后使用转化网站,把刚刚的jpg格式转成为pgm,可以使用的网站如下(如果都能用了,自行百度搜索一个可以的,如果网站让你设置大小等你无需设置让他保持默认大小就行)JPG 到 PGM - 将您的 JPG 转换为 PGM 的在线工具
JPG转PGM批量转换器 | 线上 免费
把处理的好的复制到openmv里面
然后下面是程序
下面的程序会有一些问题,在较新版固件比如4.5.9上 执行下面代码显示在openmv IDE帧缓冲区的图像没有把数字圈出来(通过观察串行端口 发现也已经识别到了数字),而使用4.4.1固件数字会被圈出来也就是说openmv IDE显示的是处理绘制的图像。
# -*- coding: utf-8 -*-
"""
OpenMV数字识别程序(彩色显示版)
功能:识别摄像头中的数字并用红色字体标注
特点:保持灰度处理流程,最终输出彩色标注画面
"""
# *************************** 硬件初始化部分 ***************************
# 导入机器视觉库和时钟模块
import sensor, image, time
# 初始化摄像头硬件
sensor.reset() # 复位摄像头硬件,清空初始化参数
# 设置摄像头采集模式(核心参数设置)
sensor.set_pixformat(sensor.RGB565) # 设置为彩色模式(16位RGB,每个像素2字节)
sensor.set_framesize(sensor.QQVGA) # 分辨率160x120(用于保证处理速度)
sensor.set_contrast(3) # 设置对比度+3(增强明暗对比,提升识别率)
# *************************** 图像镜像设置 ***************************
# (根据摄像头物理安装方向调整,不需要可注释)
sensor.set_vflip(True) # 垂直翻转:适用于摄像头倒置安装的情况
sensor.set_hmirror(True) # 水平镜像:适用于需要镜像显示的场景
# *************************** 数字模板配置 ***************************
num_quantity = 8 # 定义要识别的数字范围(1-8)
num_model = [] # 创建空列表存储模板图像
# 加载预存数字模板(需提前准备1.pgm~8.pgm文件)
for n in range(1, num_quantity+1):
# 加载PGM格式模板(建议使用白底黑字40像素高度图片)
num_model.append(image.Image(str(n) + '.pgm')) # 将模板图像存入列表
# *************************** 性能监测配置 ***************************
clock = time.clock() # 创建帧率计算时钟对象
# *************************** 图像缓冲区配置 ***************************
# 分配模板匹配专用缓冲区(优化处理速度)
img_to_matching = sensor.alloc_extra_fb(35, 45, sensor.GRAYSCALE) # 35x45灰度缓冲区
# 说明:该缓冲区用于存储缩放后的待匹配区域图像
# *************************** 算法参数设置 ***************************
threshold = (0, 70) # 灰度阈值范围:0-70(用于检测深色数字区域)
scale = 1 # 图像缩放比例初始化值
# *************************** 主循环处理逻辑 ***************************
while(True):
# 【阶段1】帧率计算与图像采集
clock.tick() # 开始帧计时(必须在循环开头调用)
img = sensor.snapshot() # 捕获一帧RGB565彩色图像(160x120像素)
# 【阶段2】创建灰度处理副本
img_gray = img.to_grayscale(copy=True) # 生成灰度副本(保持原图不变)
# 注意:所有图像处理操作在灰度副本上进行以保证算法稳定性
# 【阶段3】色块检测
blobs = img_gray.find_blobs([threshold]) # 在灰度图像中查找符合阈值的色块
# 【阶段4】候选区域处理
if blobs: # 如果检测到有效色块
# 遍历所有检测到的色块(blobs对象包含多个blob)
for blob in blobs:
# 色块有效性过滤条件(排除噪声干扰)
if blob.pixels() > 50 and 100 > blob.h() > 10 and blob.w() > 3:
# 【步骤4.1】在彩色图像上绘制检测框
# 绘制绿色预备框(比实际区域大4像素)
img.draw_rectangle(
blob.x()-2, blob.y()-2, # 起点坐标(左上角)
blob.w()+4, blob.h()+4, # 框体尺寸(宽度+高度)
color=(0, 255, 0) # 颜色:纯绿色
)
# 在色块左上角显示当前缩放比例(调试信息,白色文字)
img.draw_string(blob[0], blob[1], str(round(scale, 2)), color=(255, 255, 255))
# 【步骤4.2】计算缩放比例
scale = 40 / blob.h() # 根据色块高度计算缩放比例(模板高度为40像素)
# 【步骤4.3】提取待匹配区域
img_to_matching.draw_image(
img_gray, # 源图像(使用灰度副本保证处理一致性)
0, 0, # 目标位置(缓冲区左上角)
roi=( # 源图像感兴趣区域(Region of Interest)
blob.x()-2, # x起点(左扩2像素)
blob.y()-2, # y起点(上扩2像素)
blob.w()+4, # 宽度(左右各扩2像素)
blob.h()+4 # 高度(上下各扩2像素)
),
x_scale=scale, # 水平缩放比例
y_scale=scale # 垂直缩放比例
)
# 【阶段5】模板匹配识别
# 遍历所有数字模板进行匹配
for n in range(0, num_quantity):
# 执行模板匹配(核心识别函数)
r = img_to_matching.find_template(
num_model[n], # 当前数字模板(n对应数字1-8)
0.7, # 相似度阈值(0.0-1.0,越大匹配越严格)
step=2, # 搜索步长(2表示隔行扫描,加快速度)
search=image.SEARCH_EX # 搜索模式:穷举搜索(精度最高)
)
if r: # 如果匹配结果有效(相似度超过阈值)
# 【步骤5.1】在彩色图像上绘制橙色确认框
img.draw_rectangle(
blob[0:4], # 矩形参数(x,y,w,h)
color=(255, 100, 0) # 橙色边框(BGR格式)
)
# 【步骤5.2】显示识别结果(核心修改点)
img.draw_string(
blob[0], blob[1], # 显示位置(色块左上角)
str(n+1), # 显示内容(识别到的数字)
scale=5, # 字体放大倍数(原始5倍)
color=(255, 0, 0) # 字体颜色:纯红色(BGR格式)
)
# 【新增】输出识别结果:数字ID,X坐标,Y坐标
print("DETECT: num={}, x={}, y={}".format(n+1, blob.cx(), blob.cy()))
# 【阶段6】显示帧率信息
# 在画面左上角显示当前帧率(白色文字)
img.draw_string(0, 0, str(round(clock.fps(), 2)), color=(255, 255, 255))
# *************************** 注意事项 ***************************
"""
1. 必须准备数字模板:在存储卡根目录放置1.pgm~8.pgm文件
2. 模板建议规格:白底黑字、高度40像素、PGM格式
3. 实际显示效果:
- 绿色框:初步检测区域
- 橙色框:成功匹配区域
- 红色数字:识别结果
- 白色文字:帧率信息
4. 性能参数:QQVGA分辨率下典型帧率15-30fps(取决于处理复杂度)
5. 调试技巧:可通过调整threshold阈值和scale计算优化识别效果
"""
下面的代码 解决显示问题:
使用img.copy 可以复制一份图像方便openmv IDE显示和后面处理图像
img_copy = img.copy()#img复制到img_copy上一份 两个参数分别是
# -*- coding: utf-8 -*-
"""
OpenMV数字识别程序(彩色显示版)
功能:识别摄像头中的数字并用红色字体标注
特点:保持灰度处理流程,最终输出彩色标注画面
"""
# *************************** 硬件初始化部分 ***************************
# 导入机器视觉库和时钟模块
import sensor, image, time
# 初始化摄像头硬件
sensor.reset() # 复位摄像头硬件,清空初始化参数
# 设置摄像头采集模式(核心参数设置)
sensor.set_pixformat(sensor.RGB565) # 设置为彩色模式(16位RGB,每个像素2字节)
sensor.set_framesize(sensor.QQVGA) # 分辨率160x120(用于保证处理速度)
sensor.set_contrast(3) # 设置对比度+3(增强明暗对比,提升识别率)
# *************************** 图像镜像设置 ***************************
# (根据摄像头物理安装方向调整,不需要可注释)
sensor.set_vflip(True) # 垂直翻转:适用于摄像头倒置安装的情况
sensor.set_hmirror(True) # 水平镜像:适用于需要镜像显示的场景
# *************************** 数字模板配置 ***************************
num_quantity = 8 # 定义要识别的数字范围(1-8)
num_model = [] # 创建空列表存储模板图像
# 加载预存数字模板(需提前准备1.pgm~8.pgm文件)
for n in range(1, num_quantity+1):
# 加载PGM格式模板(建议使用白底黑字40像素高度图片)
num_model.append(image.Image(str(n) + '.pgm')) # 将模板图像存入列表
# *************************** 性能监测配置 ***************************
clock = time.clock() # 创建帧率计算时钟对象
# *************************** 图像缓冲区配置 ***************************
# 分配模板匹配专用缓冲区(优化处理速度)
img_to_matching = sensor.alloc_extra_fb(35, 45, sensor.GRAYSCALE) # 35x45灰度缓冲区
# 说明:该缓冲区用于存储缩放后的待匹配区域图像
# *************************** 算法参数设置 ***************************
threshold = (0, 70) # 灰度阈值范围:0-70(用于检测深色数字区域)
scale = 1 # 图像缩放比例初始化值
# *************************** 主循环处理逻辑 ***************************
while(True):
# 【阶段1】帧率计算与图像采集
clock.tick() # 开始帧计时(必须在循环开头调用)
img = sensor.snapshot() # 捕获一帧RGB565彩色图像(160x120像素)
img_copy = img.copy()#img复制到img_copy上一份 两个参数分别是
#这样操作更方便后面 openmvIDE帧缓冲区显示的是img 图像,后面如果比如训练可以使用彩色的img_copy 进行循迹
# 【阶段2】创建灰度处理副本
#img_gray = img.to_grayscale(copy=True, allocator=image.ALLOCATOR_CB)
img_gray = img_copy.to_grayscale(copy=True) # 生成灰度副本(保持原图不变)
# 注意:所有图像处理操作在灰度副本上进行以保证算法稳定性
# 【阶段3】色块检测
blobs = img_gray.find_blobs([threshold]) # 在灰度图像中查找符合阈值的色块
# 【阶段4】候选区域处理
if blobs: # 如果检测到有效色块
# 遍历所有检测到的色块(blobs对象包含多个blob)
for blob in blobs:
# 色块有效性过滤条件(排除噪声干扰)
if blob.pixels() > 50 and 100 > blob.h() > 10 and blob.w() > 3:
# 【步骤4.1】在彩色图像上绘制检测框
# 绘制绿色预备框(比实际区域大4像素)
img.draw_rectangle(
blob.x()-2, blob.y()-2, # 起点坐标(左上角)
blob.w()+4, blob.h()+4, # 框体尺寸(宽度+高度)
color=(0, 255, 0) # 颜色:纯绿色
)
# 在色块左上角显示当前缩放比例(调试信息,白色文字)
img.draw_string(blob[0], blob[1], str(round(scale, 2)), color=(255, 255, 255))
# 【步骤4.2】计算缩放比例
scale = 40 / blob.h() # 根据色块高度计算缩放比例(模板高度为40像素)
# 【步骤4.3】提取待匹配区域
img_to_matching.draw_image(
img_gray, # 源图像(使用灰度副本保证处理一致性)
0, 0, # 目标位置(缓冲区左上角)
roi=( # 源图像感兴趣区域(Region of Interest)
blob.x()-2, # x起点(左扩2像素)
blob.y()-2, # y起点(上扩2像素)
blob.w()+4, # 宽度(左右各扩2像素)
blob.h()+4 # 高度(上下各扩2像素)
),
x_scale=scale, # 水平缩放比例
y_scale=scale # 垂直缩放比例
)
# 【阶段5】模板匹配识别
# 遍历所有数字模板进行匹配
for n in range(0, num_quantity):
# 执行模板匹配(核心识别函数)
r = img_to_matching.find_template(
num_model[n], # 当前数字模板(n对应数字1-8)
0.7, # 相似度阈值(0.0-1.0,越大匹配越严格)
step=2, # 搜索步长(2表示隔行扫描,加快速度)
search=image.SEARCH_EX # 搜索模式:穷举搜索(精度最高)
)
if r: # 如果匹配结果有效(相似度超过阈值)
# 【步骤5.1】在彩色图像上绘制橙色确认框
img.draw_rectangle(
blob[0:4], # 矩形参数(x,y,w,h)
color=(255, 100, 0) # 橙色边框(BGR格式)
)
# 【步骤5.2】显示识别结果(核心修改点)
img.draw_string(
blob[0], blob[1], # 显示位置(色块左上角)
str(n+1), # 显示内容(识别到的数字)
scale=5, # 字体放大倍数(原始5倍)
color=(255, 0, 0) # 字体颜色:纯红色(BGR格式)
)
# 【新增】输出识别结果:数字ID,X坐标,Y坐标
print("DETECT: num={}, x={}, y={}".format(n+1, blob.cx(), blob.cy()))
# 【阶段6】显示帧率信息
# 在画面左上角显示当前帧率(白色文字)
img.draw_string(0, 0, str(round(clock.fps(), 2)), color=(255, 255, 255))