**非常详细的视频和文字教程,讲解常见的openmv教程包括 巡线、物体识别、圆环识别、阈值自动获取、垃圾识别等。非常适合学习openmv、K210、K230等项目
视频合集链接在
openmv教程合集 openmv入门到项目开发 openmv和STM32通信 openmv和opencv区别 openmv巡线 openmv数字识别教程LCD
专刊openmv视觉文章链接:
https://blog.csdn.net/qq_46187594/category_12900902.html
会发现很多角度识别不到,比如数字靠边或者斜着歪着识别经常会识别不到,
尝试进行优化,之前是每个数字只放一张照片,下面尝试每个数字识别放多个账号,比如数字1,放一个正视数字1模板和斜视数字1模板。
可以openmv插入电脑,然后在我的电脑看到,现在openmv上面没有插SD卡,现在0-9的十个模板大概占用4/11,所以我们还是可以继续放很多照片的。
运行下面这个代码获得图像截图
# This work is licensed under the MIT license.
# Copyright (c) 2013-2023 OpenMV LLC. All rights reserved.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# Hello World Example
#
# Welcome to the OpenMV IDE! Click on the green run arrow button below to run the script!
import sensor # 引入感光元件的模块,用于操作摄像头传感器
import time # 引入时间模块,用于控制时间延迟和FPS计算
# 初始化传感器
sensor.reset() # Reset and initialize the sensor. 重置并初始化传感器
sensor.set_pixformat(sensor.RGB565) # Set pixel format to RGB565 (or GRAYSCALE) 设置像素格式为RGB565(或者灰度)
sensor.set_framesize(sensor.QVGA) # Set frame size to QVGA (320x240) 设置帧大小为QVGA(320x240分辨率)
#***************************如果不需要镜像就注释掉 下面 的代码********************
# 设置摄像头镜像/翻转操作,根据摄像头安装的方向决定是否需要
sensor.set_vflip(True) # 垂直方向翻转。根据实际摄像头模块的安装位置调整是否需要此操作
#!!!重要:不同摄像头是否需要镜像,根据实际情况定。如果不需要镜像,请注释掉以下代码:
sensor.set_hmirror(True) # 水平方向反转。根据实际摄像头模块的安装位置调整是否需要此操作
#!!!重要:不同摄像头是否需要镜像,根据实际情况定。如果不需要镜像,请注释掉上述代码。
#***************************如果不需要镜像就注释掉 上面 的代码********************
sensor.skip_frames(time=2000) # Wait for settings take effect. 等待2秒钟让设置生效
clock = time.clock() # Create a clock object to track the FPS. 创建一个时钟对象,用于追踪FPS(每秒帧数)
while True:
clock.tick() # Update the FPS clock. 更新FPS时钟
img = sensor.snapshot() # Take a picture and return the image. 拍摄一张照片并返回图像
print(clock.fps()) # 输出当前的帧率(FPS),用来衡量摄像头的拍摄速度
# Note: OpenMV Cam runs about half as fast when connected
# to the IDE. The FPS should increase once disconnected.
# 注意:当OpenMV相机连接到IDE时,速度大约是平时的一半。断开连接后,FPS应该会提高。
然后我们这次采集的时候变化一些倾角或者一些光照比如下图的倾角,注意还是调整到四个模板都可以在画面中的距离或者角度。
比如把这个带角度的3保存在 倾斜角度文件夹,然后我们后缀增加_A
然后依次保存倾斜角度的0-9比如下面
然后我们把这些模板还是去前面说过的格式转化网站 转化一下
可以在这个网站进行在线转换https://convertio.co/zh/bmp-pgm/ 或者BMP 到 PGM - 将您的 BMP 转换为 PGM 的在线工具 或者免费BMP转PGM在线转换器 三个网站都可以,或者也可以百度上搜索BMP格式转pgm格式。
这个是转化好的格式
然后我们现在需要修改一下代码,在上一小节的基础上进行修改,主要相比上小节不同地方是,上小节是进行通过和 “0.pgm”, “1.pgm”, “2.pgm”, “3.pgm”, “4.pgm”, “5.pgm”, “6.pgm”, “7.pgm”, “8.pgm”, “9.pgm”,这几个文件模板进行识别对比的,然后根据阈值进行判定最符合那个模板。
我们这次要修改代码,不仅根据"0.pgm", “1.pgm”, “2.pgm”, “3.pgm”, “4.pgm”, “5.pgm”, “6.pgm”, “7.pgm”, “8.pgm”, “9.pgm”,这个10个模板了,还要根据"0_A.pgm", “1_A.pgm”, “2_A.pgm”, “3_A.pgm”, “4_A.pgm”, “5_A.pgm”, “6_A.pgm”, “7_A.pgm”, “8_A.pgm”, "9_A.pgm"这十个,也就是根据识别20个模板。比如如果识别到满足 5_A 的匹配相似度为0.7 和其他模板的匹配率都低于那么我们认为就是数字5。
把新增的模型复制到U盘里面,也就是现在一共u盘20个模板
下是修改好的代码
# 多模板匹配系统 - 数字识别增强版(支持双模板集)
# 核心功能:
# 1. 支持0-9数字基础模板及_A扩展模板集
# 2. 区域去重机制
# 3. 优化识别结果显示逻辑
import time
import sensor
import image
from image import SEARCH_EX
# ******************** 摄像头初始化配置 ********************
sensor.reset()
sensor.set_contrast(1)
sensor.set_gainceiling(16)
sensor.set_framesize(sensor.QQVGA)
sensor.set_pixformat(sensor.GRAYSCALE)
sensor.set_vflip(True)
sensor.set_hmirror(True)
# ******************** 用户可配置参数 ********************
BASE_DIGITS = ["0", "1", "2", "3", "4",
"5", "6", "7", "8", "9"]
TEMPLATE_PATHS = [f"/{d}.pgm" for d in BASE_DIGITS] +
[f"/{d}_A.pgm" for d in BASE_DIGITS]
MATCH_THRESHOLD = 0.70
SEARCH_STEP = 4
TEXT_COLOR = 255
TEXT_OFFSET = 5
# ******************** 模板预加载系统 ********************
class TemplateLoader:
"""
增强版模板加载器:
1. 自动提取数字主体名称(去除_A等后缀)
2. 提供模板加载状态报告
"""
def __init__(self):
self.templates = []
self.load_templates()
print(f"总计加载模板:{len(self.templates)}个")
def extract_digit_name(self, path):
"""从文件路径提取规范化的数字名称"""
filename = path.split("/")[-1] # 获取文件名
basename = filename.split(".")[0] # 去除扩展名
return basename.split("_")[0] # 提取主名称
def load_templates(self):
for path in TEMPLATE_PATHS:
try:
template_img = image.Image(path)
self.templates.append({
"image": template_img,
"name": self.extract_digit_name(path),
"path": path
})
except Exception as e:
print(f"模板加载异常:{path} ({str(e)})")
# 初始化模板系统
template_loader = TemplateLoader()
clock = time.clock()
# ******************** 区域去重算法 ********************
def check_overlap(new_rect, existing_rects):
"""
区域重叠检测算法:
检测新矩形中心点是否存在于已有矩形区域内
返回True表示存在重叠
"""
nx, ny, nw, nh = new_rect
cx = nx + nw//2 # 中心点坐标
cy = ny + nh//2
for ex, ey, ew, eh in existing_rects:
if (ex <= cx < ex+ew) and (ey <= cy < ey+eh):
return True
return False
# ******************** 主处理循环 ********************
while(True):
clock.tick()
img = sensor.snapshot()
#img = sensor.snapshot().lens_corr(strength = 1.8, zoom = 1.0)
processed_areas = [] # 本帧已处理区域记录
# 遍历所有模板进行匹配
for template in template_loader.templates:
result = img.find_template(
template["image"],
MATCH_THRESHOLD,
step=SEARCH_STEP,
search=SEARCH_EX
)
if result:
x, y, w, h = result
current_rect = (x, y, w, h)
# 区域去重检查
if not check_overlap(current_rect, processed_areas):
# 可视化标注
img.draw_rectangle(x, y, w, h, color=TEXT_COLOR)
text_y = max(y - TEXT_OFFSET, 0)
img.draw_string(x, text_y, template["name"],
color=TEXT_COLOR,
scale=1,
mono_space=True)
# 数据输出
print("[{:.0f}] 识别到 {} 坐标: ({},{})".format(
time.ticks_ms(),
template["name"],
x + w//2,
y + h//2
))
processed_areas.append(current_rect) # 记录已处理区域
# 性能信息显示
fps = clock.fps()
img.draw_string(5, 5, "FPS:%.1f" % fps, color=TEXT_COLOR)
识别的帧率会很低效果不是特别好