文章目錄
-
- 概要
- 整體架構流程
- 技術名詞解釋
- 技術細節
-
- 1. 多閾值適配與目標識別邏輯
- 2. 動態ROI與狀態管理機制
- 3. 數據平滑與偏差計算
- 4. 硬件適配與UART通信
- 小結
- 靜態矩形框識別
- 動態矩形框追蹤
概要
本文分析的代碼是基于立創·廬山派K230CanMV開發板的目標追蹤系統實現,主要功能是通過GC2093傳感器采集圖像,識別特定"黑框白心"目標(如帶黑色邊框的白色標記物),計算目標位置偏差并通過UART串口發送數據,同時在顯示器(虛擬窗口、LCD或HDMI)上實時展示追蹤過程及調試信息。
整體架構流程
代碼整體遵循"初始化-循環處理-資源釋放"的經典嵌入式系統流程,具體步驟如下:
-
系統初始化
- 硬件配置:初始化FPIOA引腳映射,配置UART2(波特率115200)用于數據傳輸。
- 傳感器初始化:啟動GC2093傳感器,設置分辨率(400x240)和灰度模式,開始采集圖像。
- 顯示器初始化:根據
DISPLAY_MODE
(VIRT/LCD/HDMI)初始化對應顯示設備,設置顯示分辨率。 - 媒體管理:初始化
MediaManager
協調傳感器與顯示器資源。
-
主循環處理
- 圖像采集:通過
sensor.snapshot()
獲取實時圖像。 - 目標識別:調用
find_target_blob()
在當前ROI內搜索"黑框白心"目標,結合多閾值和形態篩選規則驗證目標。 - 動態ROI調整:若鎖定目標,縮小ROI至目標周圍(提高效率);若目標丟失,逐步擴大ROI至全視野(重新搜索)。
- 數據處理:計算目標與畫面中心的偏差,通過
smooth_target()
平滑坐標,減少抖動。 - 狀態管理:通過
is_locked
標記目標狀態,lost_frames
計數連續丟失幀數,超過閾值則重置狀態。 - 數據發送與顯示:通過UART發送目標狀態及坐標,在圖像上繪制輔助線、ROI和調試信息,最終通過顯示器展示。
- 圖像采集:通過
-
資源釋放
- 異常處理:捕獲鍵盤中斷或其他異常時,停止傳感器、關閉顯示器、釋放媒體資源,確保系統安全退出。
技術名詞解釋
-
HSV閾值(thr_white/thr_black)
用于顏色(灰度)識別的范圍參數。代碼中通過灰度值范圍定義"白色"和"黑色"區域,多閾值配置(列表形式)可適應不同光照下的顏色偏差(如強光/弱光下白色的灰度值范圍變化)。 -
ROI(Region of Interest,感興趣區域)
圖像中需要重點處理的區域。通過限制處理范圍減少計算量:目標鎖定時縮小ROI(圍繞目標),目標丟失時擴大ROI(逐步恢復全視野)。 -
Blob分析
對圖像中連通的像素區域(色塊)進行分析的技術。代碼中通過find_blobs()
識別黑色邊框和白色中心的色塊,結合面積、長寬比等特征篩選有效目標。 -
實心度(Solidity)
色塊實際像素數與外接矩形面積的比值,用于判斷色塊的"填充程度"。代碼中利用實心度篩選空心黑色邊框(實心度低),排除實心噪聲區域。 -
UART(通用異步收發傳輸器)
一種串行通信協議,代碼中用于將目標狀態、坐標等數據發送到外部設備(如控制器),波特率115200確保數據傳輸穩定。 -
幀率(FPS)
每秒處理的圖像幀數,反映系統實時性。代碼中通過time.ticks_ms()
計算幀率,用于評估系統性能。
技術細節
1. 多閾值適配與目標識別邏輯
代碼通過多閾值解決光照適應性問題,核心在于"黑框優先+白心驗證"的雙層識別策略:
# 多閾值配置(適應不同光照下的黑白識別)
thr_white = [(200, 255)] # 白色中心的灰度范圍(可擴展多組)
thr_black = [(0, 60)] # 黑色邊框的灰度范圍(可擴展多組)def find_target_blob(img, roi):# 1. 先找黑色邊框(多閾值遍歷+合并相鄰色塊)black_blobs = []for t in thr_black:blobs = img.find_blobs([t], roi=roi, merge=True) # merge=True合并相鄰色塊if blobs:black_blobs.extend(blobs)# 2. 對每個黑色邊框驗證是否包含白色中心for b_blob in black_blobs:# 篩選黑色邊框(面積、長寬比、實心度)if not (MIN_RECT_AREA < b_blob.area() < MAX_RECT_AREA and0.5 < b_blob.w()/b_blob.h() < 2.0 and0.1 < b_blob.solidity() < 0.35):continue# 在黑色邊框內部10%邊距內搜索白色中心inner_roi = b_blob.rect()inner_margin = int(min(inner_roi[2], inner_roi[3]) * 0.1)inner_roi = (inner_roi[0] + inner_margin,inner_roi[1] + inner_margin,inner_roi[2] - 2*inner_margin,inner_roi[3] - 2*inner_margin)# 驗證白色中心white_blobs = []for t in thr_white:w_blobs = img.find_blobs([t], roi=inner_roi)if w_blobs:white_blobs.extend(w_blobs)if white_blobs:w_blob = max(white_blobs, key=lambda b: b.area()) # 取最大白色塊# 檢查白心是否在黑框中心區域dx = abs(w_blob.cx() - b_blob.cx())dy = abs(w_blob.cy() - b_blob.cy())if dx < b_blob.w()*0.15 and dy < b_blob.h()*0.15:return (b_blob, w_blob) # 返回匹配的黑框白心return (None, None)
代碼解析:
- 多閾值遍歷:通過
thr_black
和thr_white
列表支持多組灰度范圍,解決單一閾值在強光/弱光下失效的問題。 - 合并相鄰色塊:
merge=True
確保斷裂的黑色邊框被識別為完整區域(如邊框有缺口時仍能正常識別)。 - 內邊距ROI:在黑色邊框內部10%區域搜索白色中心,避免背景干擾,確保"心在框內"的特征匹配。
2. 動態ROI與狀態管理機制
通過ROI自適應調整平衡搜索效率與范圍,結合狀態標記實現穩定跟蹤:
# 初始化全視野ROI
current_roi = (0, 0, sensor.width(), sensor.height())
is_locked = False
lost_frames = 0
MAX_LOST_FRAMES = 8 # 連續丟失8幀則重置狀態while True:img = sensor.snapshot()b_blob, w_blob = find_target_blob(img, current_roi)if b_blob and w_blob:# 目標鎖定:縮小ROI至目標周圍is_locked = Truelost_frames = 0# 計算鎖定狀態下的ROI(目標周圍90%范圍)lock_roi = (max(0, b_blob.x() - int(b_blob.w()*0.05)),max(0, b_blob.y() - int(b_blob.h()*0.05)),min(sensor.width(), b_blob.w()*1.1),min(sensor.height(), b_blob.h()*1.1))current_roi = lock_roielse:# 目標丟失:逐步擴大ROIlost_frames += 1if lost_frames > MAX_LOST_FRAMES:is_locked = False# 每次擴大100像素(限制在全視野內)new_x = max(0, current_roi[0] - 50)new_y = max(0, current_roi[1] - 50)new_w = min(sensor.width(), current_roi[2] + 100)new_h = min(sensor.height(), current_roi[3] + 100)current_roi = (new_x, new_y, new_w, new_h)
代碼解析:
- 鎖定狀態優化:目標鎖定時ROI縮小為目標尺寸的1.1倍,減少背景處理量(如400x240圖像中,ROI縮小后計算量可降低60%以上)。
- 丟失恢復策略:目標丟失后,ROI每次向外擴展50像素(橫向/縱向),逐步恢復全視野,避免瞬間擴大導致的計算量激增。
- 狀態容錯機制:
MAX_LOST_FRAMES=8
允許短時間遮擋(約0.2~0.3秒,按30FPS計算),防止誤判丟失。
3. 數據平滑與偏差計算
通過指數平滑減少抖動,結合視角補償提升跟蹤穩定性:
# 數據平滑與偏差計算
prev_x, prev_y = 0