**非常詳細(xì)的視頻和文字教程,講解常見的openmv教程包括 巡線、物體識別、圓環(huán)識別、閾值自動獲取、垃圾識別等。非常適合學(xué)習(xí)openmv、K210、K230等項目
視頻合集鏈接在
openmv教程合集 openmv入門到項目開發(fā) openmv和STM32通信 openmv和opencv區(qū)別 openmv巡線 openmv數(shù)字識別教程LCD
??痮penmv視覺文章鏈接:
https://blog.csdn.net/qq_46187594/category_12900902.html
會發(fā)現(xiàn)很多角度識別不到,比如數(shù)字靠邊或者斜著歪著識別經(jīng)常會識別不到,
嘗試進(jìn)行優(yōu)化,之前是每個數(shù)字只放一張照片,下面嘗試每個數(shù)字識別放多個賬號,比如數(shù)字1,放一個正視數(shù)字1模板和斜視數(shù)字1模板。
可以openmv插入電腦,然后在我的電腦看到,現(xiàn)在openmv上面沒有插SD卡,現(xiàn)在0-9的十個模板大概占用4/11,所以我們還是可以繼續(xù)放很多照片的。
運行下面這個代碼獲得圖像截圖
# 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) 設(shè)置像素格式為RGB565(或者灰度)
sensor.set_framesize(sensor.QVGA) # Set frame size to QVGA (320x240) 設(shè)置幀大小為QVGA(320x240分辨率)
#***************************如果不需要鏡像就注釋掉 下面 的代碼********************
# 設(shè)置攝像頭鏡像/翻轉(zhuǎn)操作,根據(jù)攝像頭安裝的方向決定是否需要
sensor.set_vflip(True) # 垂直方向翻轉(zhuǎn)。根據(jù)實際攝像頭模塊的安裝位置調(diào)整是否需要此操作
#?。。≈匾翰煌瑪z像頭是否需要鏡像,根據(jù)實際情況定。如果不需要鏡像,請注釋掉以下代碼:
sensor.set_hmirror(True) # 水平方向反轉(zhuǎn)。根據(jù)實際攝像頭模塊的安裝位置調(diào)整是否需要此操作
#?。?!重要:不同攝像頭是否需要鏡像,根據(jù)實際情況定。如果不需要鏡像,請注釋掉上述代碼。
#***************************如果不需要鏡像就注釋掉 上面 的代碼********************
sensor.skip_frames(time=2000) # Wait for settings take effect. 等待2秒鐘讓設(shè)置生效
clock = time.clock() # Create a clock object to track the FPS. 創(chuàng)建一個時鐘對象,用于追蹤FPS(每秒幀數(shù))
while True:
clock.tick() # Update the FPS clock. 更新FPS時鐘
img = sensor.snapshot() # Take a picture and return the image. 拍攝一張照片并返回圖像
print(clock.fps()) # 輸出當(dāng)前的幀率(FPS),用來衡量攝像頭的拍攝速度
# Note: OpenMV Cam runs about half as fast when connected
# to the IDE. The FPS should increase once disconnected.
# 注意:當(dāng)OpenMV相機(jī)連接到IDE時,速度大約是平時的一半。斷開連接后,F(xiàn)PS應(yīng)該會提高。
然后我們這次采集的時候變化一些傾角或者一些光照比如下圖的傾角,注意還是調(diào)整到四個模板都可以在畫面中的距離或者角度。
比如把這個帶角度的3保存在 傾斜角度文件夾,然后我們后綴增加_A
然后依次保存傾斜角度的0-9比如下面
然后我們把這些模板還是去前面說過的格式轉(zhuǎn)化網(wǎng)站 轉(zhuǎn)化一下
可以在這個網(wǎng)站進(jìn)行在線轉(zhuǎn)換https://convertio.co/zh/bmp-pgm/ 或者BMP 到 PGM - 將您的 BMP 轉(zhuǎn)換為 PGM 的在線工具 或者免費BMP轉(zhuǎn)PGM在線轉(zhuǎn)換器 三個網(wǎng)站都可以,或者也可以百度上搜索BMP格式轉(zhuǎn)pgm格式。
這個是轉(zhuǎn)化好的格式
然后我們現(xiàn)在需要修改一下代碼,在上一小節(jié)的基礎(chǔ)上進(jìn)行修改,主要相比上小節(jié)不同地方是,上小節(jié)是進(jìn)行通過和 “0.pgm”, “1.pgm”, “2.pgm”, “3.pgm”, “4.pgm”, “5.pgm”, “6.pgm”, “7.pgm”, “8.pgm”, “9.pgm”,這幾個文件模板進(jìn)行識別對比的,然后根據(jù)閾值進(jìn)行判定最符合那個模板。
我們這次要修改代碼,不僅根據(jù)"0.pgm", “1.pgm”, “2.pgm”, “3.pgm”, “4.pgm”, “5.pgm”, “6.pgm”, “7.pgm”, “8.pgm”, “9.pgm”,這個10個模板了,還要根據(jù)"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"這十個,也就是根據(jù)識別20個模板。比如如果識別到滿足 5_A 的匹配相似度為0.7 和其他模板的匹配率都低于那么我們認(rèn)為就是數(shù)字5。
把新增的模型復(fù)制到U盤里面,也就是現(xiàn)在一共u盤20個模板
下是修改好的代碼
# 多模板匹配系統(tǒng) - 數(shù)字識別增強(qiáng)版(支持雙模板集)
# 核心功能:
# 1. 支持0-9數(shù)字基礎(chǔ)模板及_A擴(kuò)展模板集
# 2. 區(qū)域去重機(jī)制
# 3. 優(yōu)化識別結(jié)果顯示邏輯
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)
# ******************** 用戶可配置參數(shù) ********************
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
# ******************** 模板預(yù)加載系統(tǒng) ********************
class TemplateLoader:
"""
增強(qiáng)版模板加載器:
1. 自動提取數(shù)字主體名稱(去除_A等后綴)
2. 提供模板加載狀態(tài)報告
"""
def __init__(self):
self.templates = []
self.load_templates()
print(f"總計加載模板:{len(self.templates)}個")
def extract_digit_name(self, path):
"""從文件路徑提取規(guī)范化的數(shù)字名稱"""
filename = path.split("/")[-1] # 獲取文件名
basename = filename.split(".")[0] # 去除擴(kuò)展名
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)})")
# 初始化模板系統(tǒng)
template_loader = TemplateLoader()
clock = time.clock()
# ******************** 區(qū)域去重算法 ********************
def check_overlap(new_rect, existing_rects):
"""
區(qū)域重疊檢測算法:
檢測新矩形中心點是否存在于已有矩形區(qū)域內(nèi)
返回True表示存在重疊
"""
nx, ny, nw, nh = new_rect
cx = nx + nw//2 # 中心點坐標(biāo)
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
# ******************** 主處理循環(huán) ********************
while(True):
clock.tick()
img = sensor.snapshot()
#img = sensor.snapshot().lens_corr(strength = 1.8, zoom = 1.0)
processed_areas = [] # 本幀已處理區(qū)域記錄
# 遍歷所有模板進(jìn)行匹配
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)
# 區(qū)域去重檢查
if not check_overlap(current_rect, processed_areas):
# 可視化標(biāo)注
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)
# 數(shù)據(jù)輸出
print("[{:.0f}] 識別到 {} 坐標(biāo): ({},{})".format(
time.ticks_ms(),
template["name"],
x + w//2,
y + h//2
))
processed_areas.append(current_rect) # 記錄已處理區(qū)域
# 性能信息顯示
fps = clock.fps()
img.draw_string(5, 5, "FPS:%.1f" % fps, color=TEXT_COLOR)
識別的幀率會很低效果不是特別好