python進階:帶你學習實時目標跟蹤

2023-03-20 21:00:35
摘要:本程式主要實現了python的opencv人工智慧視覺模組的目標跟蹤功能。

本文分享自華為雲社群《python進階——人工智慧實時目標跟蹤,這一篇就夠用了!》,作者:lqj_本人 。

前言

本程式主要實現了python的opencv人工智慧視覺模組的目標跟蹤功能。

專案介紹

區域性鎖定目標實時動態跟蹤(適用 警方追捕,無人機鎖定拍攝等)

首先先介紹幾種AI視覺演演算法

特性:

1.BOOSTING:演演算法原理類似於Harr cascdes(AdaBoost),是一種很老的演演算法。這個演演算法速度慢並且不準。

2.MIL:比BOOSTING準一點

3.KCF:速度比BOOSTING和MIL更快,與BOOSTING和MIL一樣不能很好的處理遮擋問題。

4.CSRT:比KCF更準一些,但是速度比KCF慢

5.MedianFlow:對於快速移動的目標和外形比那花迅速的目標效果不好

6.TLD:會產生朵的false-posittives

7.MOSSE:演演算法速度非常快,但是準確率比不上KCF和CSRT,在一些追求演演算法的速度場合很適用

8.GOTURN:OpenCV中自帶的唯一一個基於深度學習的演演算法,執行短髮需要提前下載好模型檔案

分別對應的伴生的函數:

kcf:cv2.legacy.TrackerKCF_create
csrt:cv2.legacy.TrackerCSRT_create
boosting:cv2.legacy.TrackerBoosting_create
mil:cv2.legacy.TrackerMIL_create
tld:cv2.legacy.TrackerTLD_create
medianflow:cv2.legacy.TrackerMedianFlow_create
mosse:cv2.legacy.TrackerMOSSE_create

詳細程式碼講解

匯入cv模組

ret,frame = cap.read()
import cv2

使用csrt演演算法,參照伴生函數,並賦值給tracker

tracker = cv2.legacy.TrackerCSRT_create()

讀取視訊流

cap = cv2.VideoCapture('11.mp4')

先讀取到第一幀

ret,frame = cap.read()

使用selectROI(前景),畫框將目標框起,並賦值給bbox

bbox = cv2.selectROI('A',frame,fromCenter=False,showCrosshair=True)

初始化tracker,將上面的兩個值傳入

tracker.init(frame,bbox)

讀取每一幀

ret,frame = cap.read()

根據每一幀來更新tracker

ok,box = tracker.update(frame)

若讀取成功,就定位畫框,並跟隨

if ok :
        (x,y,w,h) = [int(v) for v in box]
        cv2.rectangle(frame,pt1=(int(x),int(y)),pt2=(int(x)+int(w),int(y)+int(h)),color=(0,255,0),thickness=2)

顯示視訊流

cv2.imshow('A', frame)

等待50毫秒或按空格鍵退出

if cv2.waitKey(50) == ord(' '):
    break

釋放視訊流和釋放視窗

cap.release()
cv2.destroyAllWindows()

完整程式碼及註釋:

import cv2
tracker = cv2.legacy.TrackerCSRT_create()#使用csrt演演算法,參照伴生函數,並賦值給tracker

cap = cv2.VideoCapture('11.mp4')#讀取視訊流

ret,frame = cap.read()#先讀取第一幀

bbox = cv2.selectROI('A',frame,fromCenter=False,showCrosshair=True)#使用selectROI(前景),畫框將目標框起,並賦值給bbox

tracker.init(frame,bbox)#初始化tracker,將上面的兩個值傳入

while True:
    ret,frame = cap.read()#讀取每一幀

    ok,box = tracker.update(frame)#根據每一幀來跟新tracker

    # 若讀取成功,我們就定位畫框,並跟隨
    if ok :
        (x,y,w,h) = [int(v) for v in box]
        cv2.rectangle(frame,pt1=(int(x),int(y)),pt2=(int(x)+int(w),int(y)+int(h)),color=(0,255,0),thickness=2)

    cv2.imshow('A', frame)#顯示視訊流

    if cv2.waitKey(50) == ord(' '):#等待50毫秒或鍵盤按空格鍵退出
        break

# 釋放視訊流,釋放視窗
cap.release()
cv2.destroyAllWindows()

結果演示

動圖封面
 

區域性全部實時動態目標跟蹤(適用夜視跟蹤,範圍性觀察等)

思路構建

1.先將實時攝像流或錄製視訊流,灰度轉化並高斯模糊

2.用二值化演演算法將流中的物體輪廓擴充

3.分別先讀到第一幀和第二幀,讓其對比

4.尋找對比後,流的輪廓位置,並開啟簡易模式

5.過濾物體的矩陣輪廓將其定位繪出

詳細程式碼講解

匯入cv模組

import cv2

將視訊流轉換並讓其高斯模糊

gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray,(5,5),0)

二值化擴充

_,thresh = cv2.threshold(blur,20,255,cv2.THRESH_BINARY)
dilated = cv2.dilate(thresh,None,iterations=3)
return dilated

讀取視訊流或實時攝像流

cap = cv2.VideoCapture('11.mp4')

讀取第一幀

ret,frame1 = cap.read()

讀取第二幀

ret,frame2 = cap.read()

判斷cap是否為開啟狀態

while cap.isOpened():

若為開啟,則第一幀與第二幀比較

diff = cv2.absdiff(frame1,frame2)
mask = filter_img(diff)

尋找比較後的物體輪廓,並開啟簡易模式

contours,_ = cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

使用方框將視訊流中的物體框出,得到矩陣的寬高

(x,y,w,h) = cv2.boundingRect(contour)

若矩陣的面積小於10(根據視訊流中物體的大小來定義),直接無視

if cv2.contourArea(contour) < 10:

將過濾的物體的矩陣輪廓繪出(一定要用int整形)

cv2.rectangle(frame1,pt1=(int(x),int(y)),pt2=(int(x)+int(w),int(y)+int(h)),color=(0,255,0),thickness=1)

將第一幀顯示

cv2.imshow('A',frame1)

將上面賦值的mask顯示

cv2.imshow('B',mask)

實現前後幀對比,並定位物體運動軌跡

1.將第二幀賦值給第一幀

frame1 = frame2

2.再將cap讀到的賦值給第二幀()

ret,frame2 = cap.read()

等待50毫秒或者按空格結束

if cv2.waitKey(50) == ord(' '):
    break

釋放視訊流及釋放視窗

cap.release()
cv2.destroyAllWindows()

完整程式碼及註釋:

import cv2
def filter_img(frame):
    #將視訊流轉換灰度並讓其高斯模糊
    gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray,(5,5),0)
    #二值化將其擴充
    _,thresh = cv2.threshold(blur,20,255,cv2.THRESH_BINARY)
    dilated = cv2.dilate(thresh,None,iterations=3)
    return dilated
# 讀取視訊流
cap = cv2.VideoCapture('11.mp4')

ret,frame1 = cap.read()#讀到第一幀
ret,frame2 = cap.read()#讀到第二幀

while cap.isOpened():#判斷cap是否開啟
    diff = cv2.absdiff(frame1,frame2)#若開啟,則第一幀和第二幀作比較

    mask = filter_img(diff)

    contours,_ = cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)#尋找視訊流的輪廓,簡單模式

    #用方框將視訊流中的物體用矩形框出
    for contour in contours:
        (x,y,w,h) = cv2.boundingRect(contour)#得到矩陣的寬高
        if cv2.contourArea(contour) < 10:#若矩陣的面積小於200,就無視(太小了)
            continue
        cv2.rectangle(frame1,pt1=(int(x),int(y)),pt2=(int(x)+int(w),int(y)+int(h)),color=(0,255,0),thickness=1)#將過濾的物體的矩陣輪廓繪出

    # cv2.drawContours(frame1,contours,-1,(0,255,0),2)#將視訊流中的物體輪廓畫出

    cv2.imshow('A',frame1)#將第一幀顯示
    cv2.imshow('B',mask)#將mask也顯示

    frame1 = frame2#將第二幀賦值給第一幀
    ret,frame2 = cap.read()#再將cap讀到的賦值給第二幀

    if cv2.waitKey(50) == ord(' '):#等待五十毫秒或者按空格結束
        break
#銷燬cap流
cap.release()
#釋放視窗
cv2.destroyAllWindows()

結果顯示

動圖封面
 

點選關注,第一時間瞭解華為雲新鮮技術~