• 方案介紹
  • 附件下載
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

3.4.9-識(shí)別形狀+顏色+最小變化閾值+增加最大變化閾值+卡爾曼濾波與運(yùn)動(dòng)估計(jì)

03/20 10:02
619
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

聯(lián)系方式.txt

共1個(gè)文件

**非常詳細(xì)的視頻和文字教程,講解常見(jiàn)的openmv教程包括 巡線、物體識(shí)別、圓環(huán)識(shí)別、閾值自動(dòng)獲取等。非常適合學(xué)習(xí)openmv、K210、K230等項(xiàng)目
視頻合集鏈接在


openmv教程合集 openmv入門(mén)到項(xiàng)目開(kāi)發(fā) openmv和STM32通信 openmv和opencv區(qū)別 openmv巡線 openmv數(shù)字識(shí)別教程LCD

3.4.9-識(shí)別形狀+顏色+最小變化閾值+增加最大變化閾值+卡爾曼濾波與運(yùn)動(dòng)估計(jì)+通過(guò)指定區(qū)域獲得閾值

我們要增加通過(guò)指定區(qū)域獲得閾值的功能,可以把"3.2.4-通過(guò)指定區(qū)域獲得閾值介紹和單獨(dú)實(shí)現(xiàn)"章節(jié)的代碼移植進(jìn) 到我們的"3.4.4章節(jié)"

先把函數(shù)復(fù)制過(guò)去
在這里插入圖片描述

#****************[0]-獲取指定位置閾值********************
threshold_calculated = False #控制閾值計(jì)算只執(zhí)行一次的標(biāo)志
threshold_roi = (70,50,20,20) #會(huì)通過(guò)這個(gè)位置獲得追蹤閾值
# 封裝為函數(shù):識(shí)別指定區(qū)域的閾值
def get_threshold(roi):
    # 循環(huán)多次(默認(rèn)150次)更新閾值
    threshold = [0, 0, 0, 0, 0, 0]  # LAB色彩通道的閾值 [Lmin, Lmax, Amin, Amax, Bmin, Bmax]
    for _ in range(150):
        img = sensor.snapshot()
        # 獲取指定區(qū)域的顏色直方圖
        hist = img.get_histogram(roi=roi)
        img.draw_rectangle(roi, color=(0, 255, 0), thickness=2)  # 使用綠色(0, 255, 0),厚度為2# 在圖像上繪制綠色矩形框標(biāo)識(shí)采集區(qū)域
        # 在綠色矩形框上方顯示“采集計(jì)算閾值中...”并加上省略號(hào)
        img.draw_string(roi[0], roi[1] - 10, "Collecting Threshold...", color=(0, 255, 0), scale=1)
        # 獲取L、A、B三個(gè)通道的5%和95%分位值
        lo = hist.get_percentile(0.05)  # 獲取5%分位值,表示顏色分布的下邊界
        hi = hist.get_percentile(0.95)  # 獲取95%分位值,表示顏色分布的上邊界
        print("采集計(jì)算閾值中...請(qǐng)等待")  # 打印檢查結(jié)果,1表示滿足,0表示不滿足
        # 輸出lo和hi的值
#        print(f"5% Percentile (lo): L={lo.l_value()} A={lo.a_value()} B={lo.b_value()}")
#        print(f"95% Percentile (hi): L={hi.l_value()} A={hi.a_value()} B={hi.b_value()}")
        # L通道的最小值和最大值平均后作為新的閾值
        threshold[0] = (threshold[0] + lo.l_value()) // 2  # L通道的最小值
        threshold[1] = (threshold[1] + hi.l_value()) // 2  # L通道的最大值
        # A通道的最小值和最大值平均后作為新的閾值
        threshold[2] = (threshold[2] + lo.a_value()) // 2  # A通道的最小值
        threshold[3] = (threshold[3] + hi.a_value()) // 2  # A通道的最大值
        # B通道的最小值和最大值平均后作為新的閾值
        threshold[4] = (threshold[4] + lo.b_value()) // 2  # B通道的最小值
        threshold[5] = (threshold[5] + hi.b_value()) // 2  # B通道的最大值

    print(f"計(jì)算閾值的位置區(qū)域是 ROI Info: x={roi[0]}, y={roi[1]}, width={roi[2]}, height={roi[3]}")  # 輸出roi區(qū)域的信息
    # 打印每個(gè)通道的閾值信息
    print("計(jì)算出的閾值  Threshold: Lmin={0} Lmax={1}, Amin={2} Amax={3}, Bmin={4} Bmax={5}".format(
        threshold[0], threshold[1], threshold[2], threshold[3], threshold[4], threshold[5]
    ))

    # 返回計(jì)算得到的閾值列表,包含L、A、B三個(gè)通道的最小值和最大值
    return threshold  # 返回最終的閾值數(shù)組

然后主函數(shù)執(zhí)行的前面增加獲得計(jì)算閾值的函數(shù),函數(shù)輸入一個(gè)要獲得區(qū)域,然后把計(jì)算的閾值輸出,后面就會(huì)使用到這個(gè)閾值
在這里插入圖片描述

#*****************[2]-獲取指定位置閾值-進(jìn)行閾值計(jì)算的內(nèi)容********************
    if not threshold_calculated:# 僅在閾值未計(jì)算時(shí)進(jìn)行計(jì)算
        # 調(diào)用函數(shù)獲取指定區(qū)域的閾值
        color_threshold = get_threshold(threshold_roi)

        # 設(shè)置閾值計(jì)算完成的標(biāo)志
        threshold_calculated = True

然后這個(gè)是所有的代碼如下還有如何使用的說(shuō)明
在這里插入圖片描述

import sensor, image, time
#*********************增加卡爾曼濾波*************************************************************************
import sensor, image, time, math
from ulab import numpy as np
#教程作者:好家伙VCC
#歡迎交流群QQ: 771027961 作者郵箱: 1930299709@qq.com
#更多教程B站主頁(yè):[好家伙VCC的個(gè)人空間-好家伙VCC個(gè)人主頁(yè)-嗶哩嗶哩視頻](https://space.bilibili.com/434192043)
#淘寶主頁(yè)鏈接:[首頁(yè)-好家伙VCC-淘寶網(wǎng)](https://shop415231378.taobao.com)
#更多嵌入式手把手教程-盡在好家伙VCC
# 定義顏色閾值(L, A, B),用于識(shí)別紅色
# L通道:亮度值,較小表示較暗的顏色
# A通道:綠色與紅色的色差,紅色偏大
# B通道:藍(lán)色與黃色的色差,紅色偏小
color_threshold = (0, 100, 0, 127, 0, 127)  # (L_min, L_max, A_min, A_max, B_min, B_max)

# 初始化攝像頭模塊
sensor.reset()  # 重置攝像頭,確保設(shè)備正常工作
sensor.set_pixformat(sensor.RGB565)  # 設(shè)置攝像頭的像素格式為RGB565,每個(gè)像素16位色深
sensor.set_framesize(sensor.QQVGA)  # 設(shè)置攝像頭的分辨率為QQVGA(160x120),適合快速處理

# *************************** 如果不需要鏡像就注釋掉以下代碼 **************************
# 攝像頭鏡像和翻轉(zhuǎn)設(shè)置,根據(jù)攝像頭的安裝方向調(diào)整
sensor.set_vflip(True)  # 設(shè)置垂直翻轉(zhuǎn),適用于攝像頭上下安裝的情況
sensor.set_hmirror(True)  # 設(shè)置水平翻轉(zhuǎn),適用于攝像頭左右安裝的情況
# *************************** 如果不需要鏡像就注釋掉以上代碼 **************************

sensor.skip_frames(time = 2000)  # 跳過(guò)前幾幀的圖像,確保圖像穩(wěn)定后再開(kāi)始處理
sensor.set_auto_gain(False)  # 必須關(guān)閉自動(dòng)增益,防止影響顏色追蹤
sensor.set_auto_whitebal(False)  # 必須關(guān)閉自動(dòng)白平衡,防止影響顏色追蹤

# 創(chuàng)建一個(gè)時(shí)鐘對(duì)象,用于計(jì)算和控制幀率
clock = time.clock()

# *************************** 最小變化閾值濾波 **************************
# 位置和半徑變化閾值,只有變化大于該閾值時(shí)才更新
position_threshold = 4  # 位置變化的最小閾值 兩個(gè)值越小小球識(shí)別更新的越頻繁,值越大小球的細(xì)微運(yùn)動(dòng)越不會(huì)更新識(shí)別
radius_threshold = 4    # 半徑變化的最小閾值 可以根據(jù)自己的需求測(cè)試調(diào)節(jié)這個(gè)兩個(gè)閾值
MAX_CHANGE_THRESHOLD = 80  # 最大變化閾值(例如位置或半徑變化超過(guò)此值時(shí)不更新)
# 上一幀的圓心坐標(biāo)和半徑
prev_x, prev_y, prev_r = None, None, None
# *************************** 最小變化閾值濾波 **************************
#****************[0]-獲取指定位置閾值********************
threshold_calculated = False #控制閾值計(jì)算只執(zhí)行一次的標(biāo)志
threshold_roi = (70,50,20,20) #會(huì)通過(guò)這個(gè)位置獲得追蹤閾值
# 封裝為函數(shù):識(shí)別指定區(qū)域的閾值
def get_threshold(roi):
    # 循環(huán)多次(默認(rèn)150次)更新閾值
    threshold = [0, 0, 0, 0, 0, 0]  # LAB色彩通道的閾值 [Lmin, Lmax, Amin, Amax, Bmin, Bmax]
    for _ in range(150):
        img = sensor.snapshot()
        # 獲取指定區(qū)域的顏色直方圖
        hist = img.get_histogram(roi=roi)
        img.draw_rectangle(roi, color=(0, 255, 0), thickness=2)  # 使用綠色(0, 255, 0),厚度為2# 在圖像上繪制綠色矩形框標(biāo)識(shí)采集區(qū)域
        # 在綠色矩形框上方顯示“采集計(jì)算閾值中...”并加上省略號(hào)
        img.draw_string(roi[0], roi[1] - 10, "Collecting Threshold...", color=(0, 255, 0), scale=1)
        # 獲取L、A、B三個(gè)通道的5%和95%分位值
        lo = hist.get_percentile(0.05)  # 獲取5%分位值,表示顏色分布的下邊界
        hi = hist.get_percentile(0.95)  # 獲取95%分位值,表示顏色分布的上邊界
        print("采集計(jì)算閾值中...請(qǐng)等待")  # 打印檢查結(jié)果,1表示滿足,0表示不滿足
        # 輸出lo和hi的值
#        print(f"5% Percentile (lo): L={lo.l_value()} A={lo.a_value()} B={lo.b_value()}")
#        print(f"95% Percentile (hi): L={hi.l_value()} A={hi.a_value()} B={hi.b_value()}")
        # L通道的最小值和最大值平均后作為新的閾值
        threshold[0] = (threshold[0] + lo.l_value()) // 2  # L通道的最小值
        threshold[1] = (threshold[1] + hi.l_value()) // 2  # L通道的最大值
        # A通道的最小值和最大值平均后作為新的閾值
        threshold[2] = (threshold[2] + lo.a_value()) // 2  # A通道的最小值
        threshold[3] = (threshold[3] + hi.a_value()) // 2  # A通道的最大值
        # B通道的最小值和最大值平均后作為新的閾值
        threshold[4] = (threshold[4] + lo.b_value()) // 2  # B通道的最小值
        threshold[5] = (threshold[5] + hi.b_value()) // 2  # B通道的最大值

    print(f"計(jì)算閾值的位置區(qū)域是 ROI Info: x={roi[0]}, y={roi[1]}, width={roi[2]}, height={roi[3]}")  # 輸出roi區(qū)域的信息
    # 打印每個(gè)通道的閾值信息
    print("計(jì)算出的閾值  Threshold: Lmin={0} Lmax={1}, Amin={2} Amax={3}, Bmin={4} Bmax={5}".format(
        threshold[0], threshold[1], threshold[2], threshold[3], threshold[4], threshold[5]
    ))

    # 返回計(jì)算得到的閾值列表,包含L、A、B三個(gè)通道的最小值和最大值
    return threshold  # 返回最終的閾值數(shù)組
#*********************增加卡爾曼濾波***************************8
Ts = 1/22 #Ts = 1  幀率的倒數(shù)
# 狀態(tài)空間矩陣定義
 # 狀態(tài)轉(zhuǎn)移矩陣 A,描述系統(tǒng)的狀態(tài)變化
#A = np.array([[1,0,0,0,Ts,0],[0,1,0,0,0,Ts],[0,0,1,0,0,0],[0,0,0,1,0,0],[0,0,0,0,1,0],[0,0,0,0,0,1]])
# 改進(jìn)狀態(tài)轉(zhuǎn)移矩陣A,將速度部分更明確地包含進(jìn)來(lái)A 是狀態(tài)轉(zhuǎn)移矩陣,描述了系統(tǒng)狀態(tài)(位置、速度等)的變化。該矩陣會(huì)把當(dāng)前的狀態(tài)轉(zhuǎn)換到下一時(shí)刻的狀態(tài)。
A = np.array([[1, 0, 0, 0, Ts, 0],
              [0, 1, 0, 0, 0, Ts],
              [0, 0, 1, 0, 0, 0],
              [0, 0, 0, 1, 0, 0],
              [0, 0, 0, 0, 1, 0],
              [0, 0, 0, 0, 0, 1]])


 # 觀測(cè)矩陣 C,描述從狀態(tài)到觀測(cè)值的映射關(guān)系  C 是觀測(cè)矩陣,它將狀態(tài)向量(位置、速度)與觀測(cè)量(圖像中的矩形框信息)聯(lián)系起來(lái)。這里假設(shè)觀測(cè)量是位置和速度。
C = np.array([[1,0,0,0,0,0],[0,1,0,0,0,0],[0,0,1,0,0,0],[0,0,0,1,0,0],[0,0,0,0,1,0],[0,0,0,0,0,1]])
# 過(guò)程噪聲協(xié)方差矩陣
# 過(guò)程噪聲協(xié)方差矩陣 Q,用于描述過(guò)程的隨機(jī)噪聲
#Q_value = [1e-8 for _ in range(6)]
#Q = np.diag(Q_value) #創(chuàng)建對(duì)角矩陣
# 增大過(guò)程噪聲矩陣Q_value,使得卡爾曼濾波更靈活地應(yīng)對(duì)物體快速運(yùn)動(dòng)
#Q 是過(guò)程噪聲協(xié)方差矩陣,用于描述系統(tǒng)過(guò)程中的不確定性。矩陣的對(duì)角元素表示每個(gè)狀態(tài)變量的噪聲水平。
Q_value = [1e-6 for _ in range(6)]  # 調(diào)整過(guò)程噪聲值Q_value = [1e-6 for _ in range(6)]
Q = np.diag(Q_value)  # 更新過(guò)程噪聲協(xié)方差矩陣

# 觀測(cè)噪聲協(xié)方差矩陣  R 是觀測(cè)噪聲協(xié)方差矩陣,表示觀測(cè)過(guò)程中測(cè)量誤差的大小。
R_value = [1e-6 for _ in range(6)]
R = np.diag(R_value)
# 定義觀測(cè)量Z
x = 0 #左頂點(diǎn)x坐標(biāo)
y = 0 #左頂點(diǎn)y坐標(biāo)
last_frame_x = x #上一幀左頂點(diǎn)x坐標(biāo)
last_frame_y = y #上一幀左頂點(diǎn)y坐標(biāo)
w = 0 #矩形框?qū)挾葁
h = 0 #矩形框高度h
dx = 0 #左頂點(diǎn)x坐標(biāo)移動(dòng)速度
dy = 0 #左頂點(diǎn)y坐標(biāo)移動(dòng)速度
Z = np.array([x,y,w,h,dx,dy])
# 定義卡爾曼濾波函數(shù)變量
#x_hat = np.array([80,60,30,30,2,2]) # 初始估計(jì)的狀態(tài)值(位置、速度等)
# 初始狀態(tài)估計(jì):根據(jù)實(shí)際應(yīng)用情況調(diào)整位置和速度的初值
x_hat = np.array([80, 60, 30, 30, 2, 2])  # 根據(jù)你的應(yīng)用需要調(diào)整這些值

x_hat_minus = np.array([0,0,0,0,0,0]) # 初始預(yù)測(cè)的狀態(tài)值
p_value = [10 for _ in range(6)] # 狀態(tài)誤差的初始值 p 是狀態(tài)誤差的初始協(xié)方差矩陣。
p = np.diag(p_value)# 創(chuàng)建誤差協(xié)方差矩陣 p
#*********************增加卡爾曼濾波*************************************************************************

# 卡爾曼濾波函數(shù)
#預(yù)測(cè)階段:利用狀態(tài)轉(zhuǎn)移矩陣和上一狀態(tài)估計(jì)預(yù)測(cè)當(dāng)前狀態(tài)。
#校正階段:通過(guò)卡爾曼增益對(duì)預(yù)測(cè)狀態(tài)進(jìn)行校正,使得估計(jì)值接近真實(shí)值。
#輸入 Z:觀測(cè)值(或測(cè)量值),通常是來(lái)自外部傳感器(例如相機(jī)、雷達(dá)等)的數(shù)據(jù)。在這個(gè)代碼中,Z 是一個(gè)包含目標(biāo)的位置信息(如矩形框的四個(gè)角坐標(biāo))的向量,格式為 [x, y, w, h, dx, dy],其中 x 和 y 是目標(biāo)的中心位置,w 和 h 是目標(biāo)的寬度和高度,dx 和 dy 是目標(biāo)的速度。
#輸出 x_hat:更新后的狀態(tài)估計(jì),包括位置(x, y)、寬度(w, h)、速度(dx, dy)。該值是通過(guò)卡爾曼濾波器的預(yù)測(cè)和校正步驟計(jì)算得到的最優(yōu)估計(jì)。
def Kalman_Filter(Z):
    global A,C,Q,R,x_hat,x_hat_minus,p
    # 預(yù)測(cè)部分
    x_hat_minus = np.dot(A,x_hat)
    p_minus = np.dot(A, np.dot(p, A.T)) + Q
    # 校正部分
    S = np.dot(np.dot(C, p_minus), C.T) + R
    # 選擇一個(gè)小的正則化項(xiàng)
    regularization_term = 1e-4
    # 正則化 S 矩陣
    S_regularized = S + regularization_term * np.eye(S.shape[0])
    # 計(jì)算正則化后的 S 矩陣的逆
    S_inv = np.linalg.inv(S_regularized)
    # 計(jì)算卡爾曼增益 K
    K = np.dot(np.dot(p_minus, C.T), S_inv)
    x_hat = x_hat_minus + np.dot(K,(Z - np.dot(C,x_hat_minus)))
    p = np.dot((np.eye(6) - np.dot(K,C)),p_minus)
    return x_hat
last_frame_location = [0 for _ in range(4)] #用于存儲(chǔ)上一幀的目標(biāo)位置,這通常用于目標(biāo)跟蹤和計(jì)算目標(biāo)移動(dòng)等任務(wù)。一個(gè)長(zhǎng)度為4的列表 last_frame_location,其中每個(gè)元素的初始值為 0
last_frame_rect = [0 for _ in range(4)]  #存儲(chǔ)上一幀檢測(cè)到的矩形框坐標(biāo) 成了一個(gè)長(zhǎng)度為4的列表 last_frame_rect,并且每個(gè)元素的初始值為 0。
box = [0 for _ in range(4)] #生成一個(gè)包含四個(gè)子列表的列表,存儲(chǔ)x1,y1,x2,y2

# 主循環(huán),不斷獲取攝像頭圖像并進(jìn)行處理
while(True):
    clock.tick()  # 計(jì)時(shí)當(dāng)前幀的處理時(shí)間,計(jì)算幀率

    # 獲取當(dāng)前圖像并進(jìn)行鏡頭畸變校正,糾正因鏡頭產(chǎn)生的畸變
    img = sensor.snapshot().lens_corr(1.8)  # 1.8是畸變系數(shù),適當(dāng)調(diào)整可以改善圖像質(zhì)量

#*****************[2]-獲取指定位置閾值-進(jìn)行閾值計(jì)算的內(nèi)容********************
    if not threshold_calculated:# 僅在閾值未計(jì)算時(shí)進(jìn)行計(jì)算
        # 調(diào)用函數(shù)獲取指定區(qū)域的閾值
        color_threshold = get_threshold(threshold_roi)

        # 設(shè)置閾值計(jì)算完成的標(biāo)志
        threshold_calculated = True

    # 使用霍夫變換查找圓形,并返回找到的圓的信息
    for c in img.find_circles(
        threshold = 2500,  # 設(shè)置圓形檢測(cè)的閾值。較高的值意味著需要更明顯的圓形才能被檢測(cè)到
        x_margin = 10,     # 圓心的X坐標(biāo)允許的誤差范圍
        y_margin = 10,     # 圓心的Y坐標(biāo)允許的誤差范圍
        r_margin = 10,     # 圓半徑的允許誤差范圍
        r_min = 2,         # 圓的最小半徑 單位為像素。
        r_max = 100,       # 圓的最大半徑 單位為像素。100 像素對(duì)應(yīng)多少毫米是一個(gè)動(dòng)態(tài)計(jì)算的問(wèn)題,需要根據(jù)具體的攝像頭視場(chǎng)角、分辨率和物體距離來(lái)調(diào)整。
        r_step = 2         # 圓半徑變化的步長(zhǎng) 單位為像素。
    ):
        # 計(jì)算圓形的外接矩形區(qū)域,這樣可以方便獲取圓的統(tǒng)計(jì)信息
        area = (c.x() - c.r(), c.y() - c.r(), 2 * c.r(), 2 * c.r())  # (x, y, width, height)
        # 獲取該區(qū)域內(nèi)的像素顏色統(tǒng)計(jì)信息
        statistics = img.get_statistics(roi=area)  # 獲取外接矩形區(qū)域的像素統(tǒng)計(jì)信息(顏色分布)

        # 打印該區(qū)域的顏色統(tǒng)計(jì)數(shù)據(jù),用于調(diào)試
        #print(statistics)

        # 判斷該區(qū)域是否為紅色圓
        # 使用L、A、B通道的眾數(shù)來(lái)判斷顏色是否符合紅色范圍
        if (
            color_threshold[0] < statistics.l_mode() < color_threshold[1] and  # L通道的眾數(shù)應(yīng)小于100,表示較暗的顏色
            color_threshold[2] < statistics.a_mode() < color_threshold[3] and  # A通道的眾數(shù)應(yīng)小于127,表示偏紅色
            color_threshold[4] < statistics.b_mode() < color_threshold[5]      # B通道的眾數(shù)應(yīng)小于127,表示偏藍(lán)色
        ):
            # 獲取當(dāng)前圓心和半徑
            x, y, r = c.x(), c.y(), c.r()


            # 如果是第一次檢測(cè),更新值
            if prev_x is None or prev_y is None or prev_r is None:
                prev_x, prev_y, prev_r = x, y, r  #更新上次的位置值
                # 繪制圓形
                img.draw_circle(x, y, r, color=(192, 255, 0)) #繪制圓為綠色
                # 輸出圓心坐標(biāo)和半徑
                print("第一次檢測(cè)       First detection: center_x = {}, center_y = {}, radius = {}".format(x, y, r))
                circle_center_x = x
                circle_center_y = y
                circle_radius = r

            else:
                # 判斷位置和半徑變化是否大于閾值
                x_change = abs(x - prev_x)#計(jì)算這次值和上次值 的絕對(duì)值
                y_change = abs(y - prev_y)
                r_change = abs(r - prev_r)

                # 判斷變化是否大于最小閾值,并且變化小于最大閾值
                if (
                    (x_change > position_threshold or y_change > position_threshold or r_change > radius_threshold) and
                    (x_change <= MAX_CHANGE_THRESHOLD and y_change <= MAX_CHANGE_THRESHOLD and r_change <= MAX_CHANGE_THRESHOLD)
                ):
                    # 變化大于閾值,更新值
                    prev_x, prev_y, prev_r = x, y, r
                    # 繪制更新后的圓形
                    img.draw_circle(x, y, r, color=(192, 255, 0))
                    # 輸出圓心坐標(biāo)和半徑
                    print("更新檢測(cè)       Updated detection: center_x = {}, center_y = {}, radius = {}".format(x, y, r))
                    circle_center_x = x
                    circle_center_y = y
                    circle_radius = r

                else :
                    # 變化小于閾值,繪制上次的坐標(biāo)和半徑
                    img.draw_circle(prev_x, prev_y, prev_r, color=(192, 255, 0))
                    # 輸出圓心坐標(biāo)和半徑(使用上次的坐標(biāo)和半徑)
                    print("沒(méi)有顯著變化 No significant change: center_x = {}, center_y = {}, radius = {}".format(prev_x, prev_y, prev_r))
                    circle_center_x = prev_x
                    circle_center_y = prev_y
                    circle_radius = prev_r


            # 假設(shè)圓的中心 (c.x(), c.y()) 和半徑 c.r()


            # 計(jì)算矩形框的左上角坐標(biāo)和寬高
            rect_x = int(circle_center_x - circle_radius)  # 矩形框左上角的 x 坐標(biāo)
            rect_y = int(circle_center_y - circle_radius)  # 矩形框左上角的 y 坐標(biāo)
            rect_w = int(2 * circle_radius)  # 矩形框的寬度,等于圓的直徑
            rect_h = int(2 * circle_radius)  # 矩形框的高度,等于圓的直徑

            # 將矩形框的四個(gè)參數(shù)存儲(chǔ)到 rect 數(shù)組中
            rect = [rect_x, rect_y, rect_w, rect_h]


            box = [rect[0], rect[1], rect[0] + rect[2], rect[1] + rect[3]] # 計(jì)算標(biāo)記框的四個(gè)角坐標(biāo)(左上角和右下角)
            x, y, w, h = rect[0], rect[1], rect[2], rect[3]# 獲取新的矩形框的坐標(biāo) 識(shí)別成功的時(shí)候這個(gè)值是識(shí)別值的數(shù)據(jù)賦值
            dx = (x - last_frame_x) / Ts# 計(jì)算x方向的速度,假設(shè) Ts 為時(shí)間步長(zhǎng)
            dy = (y - last_frame_y) / Ts# 計(jì)算y方向的速度
            Z = np.array([x, y, w, h, dx, dy]) # 構(gòu)造測(cè)量向量 Z,包括位置和速度
            x_hat = Kalman_Filter(Z)# 使用卡爾曼濾波器進(jìn)行狀態(tài)估計(jì)
            last_frame_x, last_frame_y = x, y # 更新上一幀的x, y坐標(biāo)
            #img.draw_rectangle(last_frame_rect, color = (0, 0, 255))
            #img.draw_rectangle(rect, color = (255, 0, 0)) # 用紅色矩形框繪制目標(biāo)位置
            last_frame_rect = rect# 更新上一幀的矩形框 識(shí)別成功的時(shí)候
            last_frame_location = box# 更新上一幀的位置 識(shí)別成功的時(shí)候




        else:
            # 如果不是紅色圓形,用白色矩形框標(biāo)記該區(qū)域
            #img.draw_circle(c.x(), c.y(), c.r(), color=(255, 255, 255))  # 白色



            # 如果不是紅色圓形,用白色矩形框標(biāo)記該區(qū)域
            #img.draw_circle(c.x(), c.y(), c.r(), color=(255, 255, 255))  # 白色
            #解釋?zhuān)焊鶕?jù)卡爾曼濾波的預(yù)測(cè)值和目標(biāo)的速度來(lái)更新目標(biāo)的位置:
            #x_hat[0] 和 x_hat[1] 是預(yù)測(cè)的位置,x_hat[4] 和 x_hat[5] 是目標(biāo)的速度(速度分別對(duì)應(yīng) dx 和 dy)。
            #Ts 是時(shí)間步長(zhǎng)。更新后的 x, y 位置是通過(guò)加入速度(dx 和 dy)的影響來(lái)計(jì)算的。
            #w 和 h 是目標(biāo)的寬度和高度,這些信息沒(méi)有改變,仍然使用 x_hat[2] 和 x_hat[3]。
            x,y,w,h = (x_hat[0] + (x_hat[4] * Ts)),(x_hat[1] + (x_hat[5] * Ts)),x_hat[2],x_hat[3]
            #解釋?zhuān)河?jì)算目標(biāo)在 X 方向的速度(dx),通過(guò)當(dāng)前幀的 x 位置與上一幀的 last_frame_x 位置之差來(lái)計(jì)算,除以時(shí)間步長(zhǎng) Ts
            dx = (x - last_frame_x) / Ts
            #解釋?zhuān)河?jì)算目標(biāo)在 Y 方向的速度(dy),通過(guò)當(dāng)前幀的 y 位置與上一幀的 last_frame_y 位置之差來(lái)計(jì)算,除以時(shí)間步長(zhǎng) Ts
            dy = (y - last_frame_y) / Ts
            #解釋?zhuān)簩⒛繕?biāo)的位置、寬高、速度(dx 和 dy)組合成一個(gè)狀態(tài)向量 Z,這個(gè)向量將作為卡爾曼濾波器的輸入
            Z = np.array([x, y, w, h, dx, dy])
            #解釋?zhuān)簩顟B(tài)向量 Z 傳遞給卡爾曼濾波器 Kalman_Filter,以獲得更新后的預(yù)測(cè)狀態(tài) x_hat
            x_hat = Kalman_Filter(Z)
            #更新上一幀的目標(biāo)位置 last_frame_x 和 last_frame_y 為當(dāng)前幀的目標(biāo)位置 x 和 y,以便在下一幀計(jì)算速度時(shí)使用
            last_frame_x, last_frame_y = x, y
            #更新上一幀的目標(biāo)矩形框 last_frame_rect 為當(dāng)前幀的矩形框 x, y, w, h。
            last_frame_rect = [x,y,w,h]
            #更新上一幀的目標(biāo)位置 last_frame_location 為當(dāng)前幀的目標(biāo)位置。這是一個(gè)矩形框的坐標(biāo),包括左上角 (x, y) 和右下角 (x + w, y + h)
            last_frame_location = [x,y,(x + w),(y + h)]

    predicted_rect = [ # 使用卡爾曼濾波的預(yù)測(cè)值繪制預(yù)測(cè)的矩形框
        int(x_hat[0]),# 預(yù)測(cè)的矩形框左上角x坐標(biāo)
        int(x_hat[1]),# 預(yù)測(cè)的矩形框左上角y坐標(biāo)
        int(x_hat[2]), # 預(yù)測(cè)的矩形框?qū)挾?
        int(x_hat[3]) # 預(yù)測(cè)的矩形框高度
    ]
    # 繪制矩形框
    img.draw_rectangle(predicted_rect, color=(100, 100, 100))  # 使用灰色繪制矩形框
    #下面是把矩形轉(zhuǎn)化會(huì)園繪制的,我們不需要
#    # 計(jì)算圓心坐標(biāo)和半徑
    center_x = int(x_hat[0] + x_hat[2] / 2)  # 圓心x坐標(biāo)(矩形框左上角x + 寬度的一半)
    center_y = int(x_hat[1] + x_hat[3] / 2)  # 圓心y坐標(biāo)(矩形框左上角y + 高度的一半)
    radius = int(min(x_hat[2], x_hat[3]) / 2)  # 半徑取矩形框?qū)挾群透叨鹊淖钚≈档囊话?
    # 輸出圓心坐標(biāo)和半徑信息
    print("卡爾曼計(jì)算       Predicted Circle: center_x = {}, center_y = {}, radius = {}".format(center_x, center_y, radius))

    # 打印當(dāng)前幀率(每秒幀數(shù)),便于調(diào)試性能
    print("FPS %f" % clock.fps())  # 輸出當(dāng)前的幀率

  • 聯(lián)系方式.txt
    下載

相關(guān)推薦

方案定制

去合作
方案開(kāi)發(fā)定制化,2000+方案商即時(shí)響應(yīng)!