From sztu 自动化专业的小菜鸡。
本篇将介绍计算机视觉的落点预测,基于python的opencv。
实战阶段,运用卡尔曼滤波的相关知识去做落点预测。
卡尔曼滤波(Kalman filtering)是一种利用线性系统状态方程,通过系统输入输出观测数据,对系统状态进行最优估计的算法。由于观测数据中包括系统中的噪声和干扰的影响,所以最优估计也可看作是滤波过程。
数据滤波是去除噪声还原真实数据的一种数据处理技术,Kalman滤波在测量方差已知的情况下能够从一系列存在测量噪声的数据中,估计动态系统的状态。由于它便于计算机编程实现,并能够对现场采集的数据进行实时的更新和处理,Kalman滤波是目前应用最为广泛的滤波方法,在通信,导航,制导与控制等多领域得到了较好的应用。
import cv2
import numpy as np
class KalmanFilter:
kf = cv2.KalmanFilter(4, 2)
kf.measurementMatrix = np.array([[1, 0, 0, 0], [0, 1, 0, 0]], np.float32)
kf.transitionMatrix = np.array([[1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]], np.float32)
def predict(self, coordX, coordY):
''' This function estimates the position of the object'''
measured = np.array([[np.float32(coordX)], [np.float32(coordY)]])
self.kf.correct(measured)
predicted = self.kf.predict()
x, y = int(predicted[0]), int(predicted[1])
return x, y
上述代码是整个代码文件的内核,也就是用卡尔曼滤波进行落点预测必须用到的文件。
from kalmanfilter import KalmanFilter
import cv2
# Kalman Filter
kf = KalmanFilter()
img = cv2.imread("blue_background.webp")
ball1_positions = [(50, 100), (100, 100), (150, 100), (200, 100), (250, 100), (300, 100), (350, 100), (400, 100), (450, 100)]
ball2_positions = [(4, 300), (61, 256), (116, 214), (170, 180), (225, 148), (279, 120), (332, 97),
(383, 80), (434, 66), (484, 55), (535, 49), (586, 49), (634, 50),
(683, 58), (731, 69), (778, 82), (824, 101), (870, 124), (917, 148),
(962, 169), (1006, 212), (1051, 249), (1093, 290)]
for pt in ball2_positions:
cv2.circle(img, pt, 15, (0, 20, 220), -1)
predicted = kf.predict(pt[0], pt[1])
cv2.circle(img, predicted, 15, (20, 220, 0), 4)
for i in range(10):
predicted = kf.predict(predicted[0], predicted[1])
cv2.circle(img, predicted, 15, (20, 220, 0), 4)
print(predicted)
cv2.imshow("Img", img)
cv2.waitKey(0)
结果展示:
可以看到我们成功的对落点进行了预测,其中红色是实际情况,绿色为落点预测。
在进行落点预测之前,需要对目标进行识别,基础知识这块可以参考博主之前写的文章,这儿直接上代码。
import cv2
import numpy as np
class OrangeDetector:
def __init__(self):
# Create mask for orange color
self.low_orange = np.array([100, 43, 46])
self.high_orange = np.array([124, 255, 255])
def detect(self, frame):
hsv_img = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# Create masks with color ranges
mask = cv2.inRange(hsv_img, self.low_orange, self.high_orange)
# Find Contours
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key=lambda x: cv2.contourArea(x), reverse=True)
box = (0, 0, 0, 0)
for cnt in contours:
(x, y, w, h) = cv2.boundingRect(cnt)
box = (x, y, x + w, y + h)
break
return box
ok,以hsv的目标识别为例,我们来看看调用摄像头进行落点预测的相关代码。
import cv2
from orange_detector import OrangeDetector
from kalmanfilter import KalmanFilter
cap = cv2.VideoCapture(0)
# Load detector
od = OrangeDetector()
# Load Kalman filter to predict the trajectory
kf = KalmanFilter()
while True:
ret, frame = cap.read()
if ret is False:
break
orange_bbox = od.detect(frame)
x, y, x2, y2 = orange_bbox
cx = int((x + x2) / 2)
cy = int((y + y2) / 2)
predicted = kf.predict(cx, cy)
#cv2.rectangle(frame, (x, y), (x2, y2), (255, 0, 0), 4)
cv2.circle(frame, (cx, cy), 20, (0, 0, 255), 4)
cv2.circle(frame, (predicted[0], predicted[1]), 20, (255, 0, 0), 4)
cv2.imshow("Frame", frame)
key = cv2.waitKey(150)
if key == 27:
break
so,运行这串代码就可以调用笔记本内置的摄像头进行落点预测,这儿不对运行结果进行展示(上传视频需要时间~~~)
希望大家看了这篇博客能有所收获~