python目标跟踪精度曲线图_Python+opencv3.4+Kalman滤波在视频中跟踪绘制运动目标,Pythonopencv34kalman,卡尔曼滤波,实现,物体,追踪,和,轨迹...
實驗環境:
Python3.6+OpenCV3.4+pycharm2019
代碼實現:
首先是一個
簡單的不用kalman濾波的運動目標追蹤代碼
這里可以根據需要進行攝像頭運動目標識別,只要把
camera = cv2.VideoCapture('./video/yellow_ball.mp4')
# 改成camera = cv2.VideoCapture(0) 就是攝像頭內識別
完整代碼:
from collections import deque
import numpy as np
import cv2
# imutils
import time
#設定閾值,HSV空間
redLower = np.array([11, 100, 100])
redUpper = np.array([20, 255, 255])
#初始化追蹤點的列表
mybuffer = 64
pts = deque(maxlen=mybuffer)
#打開攝像頭
camera = cv2.VideoCapture('./video/yellow_ball.mp4')
fourcc = cv2.VideoWriter_fourcc(*'XVID') # 保存文件為avi格式
fps = camera.get(cv2.CAP_PROP_FPS)
size = (int(camera.get(cv2.CAP_PROP_FRAME_WIDTH)), int(camera.get(cv2.CAP_PROP_FRAME_HEIGHT))) # 輸出視頻尺寸,長和寬
out = cv2.VideoWriter('new_yellow_ball.avi', fourcc, fps, size) # 輸出視頻
#等待兩秒
time.sleep(2)
#遍歷每一幀,檢測紅色瓶蓋
while True:
#讀取幀
(ret, frame) = camera.read()
if ret == False:
break
#判斷是否成功打開攝像頭
# if not ret:
# print('No Camera')
# break
#frame = imutils.resize(frame, width=600)
#轉到HSV空間
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
#根據閾值構建掩膜
mask = cv2.inRange(hsv, redLower, redUpper)
#腐蝕操作
mask = cv2.erode(mask, None, iterations=2)
#膨脹操作,其實先腐蝕再膨脹的效果是開運算,去除噪點
mask = cv2.dilate(mask, None, iterations=2)
#輪廓檢測
cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]
#初始化瓶蓋圓形輪廓質心
center = None
#如果存在輪廓
if len(cnts) > 0:
#找到面積最大的輪廓
c = max(cnts, key = cv2.contourArea)
#確定面積最大的輪廓的外接圓
((x, y), radius) = cv2.minEnclosingCircle(c)
#計算輪廓的矩
M = cv2.moments(c)
#計算質心
center = (int(M["m10"]/M["m00"]), int(M["m01"]/M["m00"]))
#只有當半徑大于10時,才執行畫圖
if radius > 10:
cv2.circle(frame, (int(x), int(y)), int(radius), (0, 255, 255), 2)
cv2.circle(frame, center, 5, (0, 0, 255), -1)
#把質心添加到pts中,并且是添加到列表左側
pts.appendleft(center)
#遍歷追蹤點,分段畫出軌跡
for i in range(1, len(pts)):
if pts[i - 1] is None or pts[i] is None:
continue
#計算所畫小線段的粗細
thickness = int(np.sqrt(mybuffer / float(i + 1)) * 2.5)
#畫出小線段
cv2.line(frame, pts[i - 1], pts[i], (0, 0, 255), thickness)
#res = cv2.bitwise_and(frame, frame, mask=mask)
cv2.imshow('Frame', frame)
out.write(frame)
#鍵盤檢測,檢測到esc鍵退出
k = cv2.waitKey(5)&0xFF
if k == 27:
break
#攝像頭釋放
camera.release()
#銷毀所有窗口
cv2.destroyAllWindows()
這里是
基于kalman濾波的運動目標識別與軌跡繪制
import cv2
import numpy as np
# hsv閾值,便于進行輪廓判斷及軌跡繪制,需要根據運動目標的顏色自己進行調整
min_hsv_bound = (35, 100, 100)
max_hsv_bound = (77, 255, 255)
#狀態向量
stateSize = 6
#觀測向量
measSize = 4
coutrSize = 0
kf = cv2.KalmanFilter(stateSize,measSize,coutrSize)
state = np.zeros(stateSize, np.float32)#[x,y,v_x,v_y,w,h],簇心位置,速度,高寬
meas = np.zeros(measSize, np.float32)#[z_x,z_y,z_w,z_h]
procNoise = np.zeros(stateSize, np.float32)
#狀態轉移矩陣
cv2.setIdentity(kf.transitionMatrix)#生成單位矩陣
# [1 0 dT 0 0 0]
# [0 1 0 dT 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]
#觀測矩陣
# [1 0 0 0 0 0]
# [0 1 0 0 0 0]
# [0 0 0 0 1 0]
# [0 0 0 0 0 1]
kf.measurementMatrix = np.zeros((measSize,stateSize),np.float32)
kf.measurementMatrix[0,0]=1.0
kf.measurementMatrix[1,1]=1.0
kf.measurementMatrix[2,4]=1.0
kf.measurementMatrix[3,5]=1.0
#預測噪聲
# [Ex 0 0 0 0 0]
# [0 Ey 0 0 0 0]
# [0 0 Ev_x 0 0 0]
# [0 0 0 Ev_y 0 0]
# [0 0 0 0 Ew 0]
# [0 0 0 0 0 Eh]
cv2.setIdentity(kf.processNoiseCov)
kf.processNoiseCov[0,0] = 1e-2
kf.processNoiseCov[1,1] = 1e-2
kf.processNoiseCov[2,2] = 5.0
kf.processNoiseCov[3,3] = 5.0
kf.processNoiseCov[4,4] = 1e-2
kf.processNoiseCov[5,5] = 1e-2
#測量噪聲
cv2.setIdentity(kf.measurementNoiseCov)
# for i in range(len(kf.measurementNoiseCov)):
# kf.measurementNoiseCov[i,i] = 1e-1
video_cap = cv2.VideoCapture('./video/green_ball.mp4')
# 視頻輸出
fps = video_cap.get(cv2.CAP_PROP_FPS) #獲得視頻幀率,即每秒多少幀
size = (int(video_cap.get(cv2.CAP_PROP_FRAME_WIDTH)),int(video_cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
videoWriter = cv2.VideoWriter('./video/new_green.mp4' ,cv2.VideoWriter_fourcc('m', 'p', '4', 'v'), fps, size)
ticks = 0
i=0
found = False
notFoundCount = 0
prePointCen = [] #存儲小球中心點位置
meaPointCen = []
while(True):
ret, frame = video_cap.read()
if ret is False:
break
cv2.imshow('frame',frame)
cv2.waitKey(1)
precTick = ticks
ticks = float(cv2.getTickCount())
res = frame.copy()
# dT = float(1/fps)
dT = float((ticks - precTick)/cv2.getTickFrequency())
if(found):
#預測得到的小球位置
kf.transitionMatrix[0,2] = dT
kf.transitionMatrix[1,3] = dT
state = kf.predict()
width = state[4]
height = state[5]
x_left = state[0] - width/2 #左上角橫坐標
y_left = state[1] - height/2 #左上角縱坐標
x_right = state[0] + width/2
y_right = state[1] + height/2
center_x = state[0]
center_y = state[1]
prePointCen.append((int(center_x),int(center_y)))
cv2.circle(res, (int(center_x),int(center_y)),2,(255,0,0),-1)
cv2.rectangle(res,(x_left,y_left),(x_right,y_right),(255,0,0),2)
#根據顏色二值化得到的小球位置
frame = cv2.GaussianBlur(frame, (5,5), 3.0, 3.0)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
rangeRes = cv2.inRange(frame, min_hsv_bound,max_hsv_bound)
kernel = np.ones((3, 3), np.uint8)
# 腐蝕膨脹
rangeRes = cv2.erode(rangeRes, kernel, iterations=2)
rangeRes = cv2.dilate(rangeRes, kernel, iterations=2)
# cv2.imshow("Threshold", rangeRes)
cv2.waitKey(1)
contours = cv2.findContours(rangeRes.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)[-2]
#檢測輪廓,只檢測最外圍輪廓,保存物體邊界上所有連續的輪廓點到contours向量內
balls = []
ballsBox = []
for i in range(len(contours)):
x, y, w, h = cv2.boundingRect(np.array(contours[i]))
ratio = float(w/h)
if(ratio > 1.0):
ratio = 1.0 / ratio
if(ratio > 0.75 and w*h>=400):
balls.append(contours[i])
ballsBox.append([x, y, w, h])
print( "Balls found:", len(ballsBox))
print("\n")
for i in range(len(balls)):
# 繪制小球輪廓
cv2.drawContours(res, balls, i, (20,150,20),1)
cv2.rectangle(res,(ballsBox[i][0],ballsBox[i][1]),(ballsBox[i][0]+ballsBox[i][2],ballsBox[i][1]+ballsBox[i][3]),(0,255,0),2) #二值化得到小球邊界
center_x = ballsBox[i][0] + ballsBox[i][2] / 2
center_y = ballsBox[i][1] + ballsBox[i][3] / 2
meaPointCen.append((int(center_x),int(center_y)))
cv2.circle(res,(int(center_x),int(center_y)), 2, (20,150,20) ,-1)
name = "(" + str(center_x) + "," + str(center_y) + ")"
cv2.putText(res, name, (int(center_x) + 3, int(center_y) - 3), cv2.FONT_HERSHEY_COMPLEX, 0.5, (20,150,20), 2)
n = len(prePointCen)
for i in range(1, n):
print(i)
if prePointCen[i-1] is None or prePointCen[i] is None:
continue
# 注釋掉的這塊是為了繪制能夠隨時間先后慢慢消失的追蹤軌跡,但是有一些小錯誤
# 計算所畫小線段的粗細
# thickness = int(np.sqrt(64 / float(n - i + 1))*2.5)
# print(thickness)
# 畫出小線段
# cv2.line(res, prePointCen[i-1], prePointCen[i], (0, 0, 255), thickness)
cv2.line(res, prePointCen[i-1], prePointCen[i], (0,0,255), 1, 4)
if(len(balls) == 0):
notFoundCount += 1
print("notFoundCount",notFoundCount)
print("\n")
if notFoundCount >= 100:
found = False
else:
#測量得到的物體位置
notFoundCount = 0
meas[0] = ballsBox[0][0] + ballsBox[0][2] / 2
meas[1] = ballsBox[0][1] + ballsBox[0][3] / 2
meas[2] = float(ballsBox[0][2])
meas[3] = float(ballsBox[0][3])
#第一次檢測
if not found:
for i in range(len(kf.errorCovPre)):
kf.errorCovPre[i,i] = 1
state[0] = meas[0]
state[1] = meas[1]
state[2] = 0
state[3] = 0
state[4] = meas[2]
state[5] = meas[3]
kf.statePost = state
found = True
else:
kf.correct(meas) #Kalman修正
print('rr',res.shape)
print("Measure matrix:", meas)
cv2.imshow("Tracking", res)
cv2.waitKey(1)
videoWriter.write(res)
大概就是這樣了,如果追蹤效果不好就自己調整一下閾值范圍吧
總結
以上是生活随笔為你收集整理的python目标跟踪精度曲线图_Python+opencv3.4+Kalman滤波在视频中跟踪绘制运动目标,Pythonopencv34kalman,卡尔曼滤波,实现,物体,追踪,和,轨迹...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: qq怎么删除收藏的表情包
- 下一篇: qq来电铃声怎么设置自己喜欢的音乐