# （项目笔记）OpenCV目标检测程序

1 Tacker类：标记并更新获取到的目标

``````import math

class EuclideanDistTracker:
def __init__(self):
# Store the center positions of the objects
self.center_points = {}
# Keep the count of the IDs
# each time a new object id detected, the count will increase by one
self.id_count = 0

# record IDs of objects tracked
# @param: the rectangular frame that captures an object
# @return: objects boxes and ids
def update(self, objects_rect):
# Objects boxes and ids
objects_bbs_ids = []

# Get center point of new object
# time complexity O(N^2)
for rect in objects_rect:
# find the center of the object
x, y, w, h = rect
cx = (x + x + w) // 2
cy = (y + y + h) // 2

# Find out if that object was detected already
same_object_detected = False
# search the objects stored for the same object
for id, pt in self.center_points.items():
distance = math.hypot(cx - pt[0], cy - pt[1])

# if the distance between two objects detected are very close, we consider
# them to be one object
if distance < 25:
self.center_points[id] = (cx, cy)
print(self.center_points)
objects_bbs_ids.append([x, y, w, h, id])
same_object_detected = True
break

# New object is detected we assign the ID to that object
if same_object_detected is False:
self.center_points[self.id_count] = (cx, cy)    # update center coordinates
objects_bbs_ids.append([x, y, w, h, self.id_count])
self.id_count += 1

# Clean the dictionary by center points to remove IDS not used anymore
new_center_points = {}
for obj_bb_id in objects_bbs_ids:
_, _, _, _, object_id = obj_bb_id
center = self.center_points[object_id]
new_center_points[object_id] = center

# Update dictionary with IDs not used removed
self.center_points = new_center_points.copy()
return objects_bbs_ids

``````

1

``````self.center_points = {}
self.id_count = 0
``````

center_points字典用于保存记录的中心点坐标。其键为物体标记，值为该物体的中心点x和y坐标

2

``````for id, pt in self.center_points.items():
distance = math.hypot(cx - pt[0], cy - pt[1])

# if the distance between two objects detected are very close, we consider
# them to be one object
if distance < 25:
self.center_points[id] = (cx, cy)
print(self.center_points)
objects_bbs_ids.append([x, y, w, h, id])
same_object_detected = True
break
``````

distance = math.hypot(cx - pt[0], cy - pt[1])

math.hypot(x, y)计算该点到原点的距离，相当于math.sqrt(x * x + y * y)。这一函数用于算出当前物体和已记录的第id个物体之间距离绝对值。如果此值小于25，我们认为这两个物体为同一个。接下来更新第id物体中心点坐标，并把更新后坐标和id添加到objects_bbs_ids，该二维列表保存每个物体的x,y坐标及长宽

3

``````            if same_object_detected is False:
self.center_points[self.id_count] = (cx, cy)    # update center coordinates
objects_bbs_ids.append([x, y, w, h, self.id_count])
self.id_count += 1
``````

4

``````		new_center_points = {}
for obj_bb_id in objects_bbs_ids:
_, _, _, _, object_id = obj_bb_id
center = self.center_points[object_id]
new_center_points[object_id] = center

# Update dictionary with IDs not used removed
self.center_points = new_center_points.copy()
return objects_bbs_ids
``````

2 主方法

``````import cv2
from tracker import *

# Create tracker object
tracker = EuclideanDistTracker()

cap = cv2.VideoCapture("highway.mp4")

# Object detection from Stable camera
object_detector = cv2.createBackgroundSubtractorMOG2(history = 100, varThreshold = 50, detectShadows = True)

while True:
# get video height and width
height, width = frame.shape[0:2]

# Extract Region of interest
roi = frame[340: 720,500: 800]

# 1. Object Detection
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
detections = []
for cnt in contours:
# Calculate area and remove small objects
area = cv2.contourArea(cnt)
if area > 100:
# cv2.drawContours(roi, [cnt], -1, (0, 255, 0), 2)
x, y, w, h = cv2.boundingRect(cnt)

detections.append([x, y, w, h])

# 2. Object Tracking
boxes_ids = tracker.update(detections)
for box_id in boxes_ids:
x, y, w, h, id = box_id
cv2.putText(roi, str(id), (x, y - 15), cv2.FONT_HERSHEY_PLAIN, 2, (255, 0, 0), 2)
cv2.rectangle(roi, (x, y), (x + w, y + h), (0, 255, 0), 3)

cv2.imshow("roi", roi)
cv2.imshow("Frame", frame)

key = cv2.waitKey(30)
if key == 27:
break

cap.release()
cv2.destroyAllWindows()
``````

1

``````object_detector = cv2.createBackgroundSubtractorMOG2(history = 100, varThreshold = 50, detectShadows = True)
``````

1 int history:用于训练背景的帧数。这一参数会影响训练背景的学习率（如果不手动设置学习率），帧数越大，学习率越小，训练越慢
2 int varThreshould: 方差阈值，用于判断当前像素前景和背景，如当前像素和背景图片差大于阈值及认定为前景。一般阈值设为16，在光照变化明显的情况下要提高，阈值越大检测越不灵敏

2

`````` mask = object_detector.apply(roi)
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
detections = []
for cnt in contours:
# Calculate area and remove small objects
area = cv2.contourArea(cnt)
if area > 100:
# cv2.drawContours(roi, [cnt], -1, (0, 255, 0), 2)
x, y, w, h = cv2.boundingRect(cnt)
``````

cv2.threshold(src, thresh, maxval, type[, dist])
src：传入灰度图像
thresh: 起始阈值
maxval：最大值
type：图像处理类型

3

``````    boxes_ids = tracker.update(detections)
for box_id in boxes_ids:
x, y, w, h, id = box_id
cv2.putText(roi, str(id), (x, y - 15), cv2.FONT_HERSHEY_PLAIN, 2, (255, 0, 0), 2)
cv2.rectangle(roi, (x, y), (x + w, y + h), (0, 255, 0), 3)
``````

2

THE END