这是deepsort类下的update函数
def update(self, bbox_xywh, confidences, class_labels, ori_img):
self.height, self.width = ori_img.shape[:2]
# generate detections
features = self._get_features(bbox_xywh, ori_img)
bbox_tlwh = self._xywh_to_tlwh(bbox_xywh)
detections = [Detection(bbox_tlwh[i], conf, features[i], class_labels[i]) for i, conf in enumerate(
confidences) if conf > self.min_confidence]
# run on non-maximum supression
boxes = np.array([d.tlwh for d in detections])
scores = np.array([d.confidence for d in detections])
indices = non_max_suppression(boxes, self.nms_max_overlap, scores)
detections = [detections[i] for i in indices]
# update tracker
self.tracker.predict()
self.tracker.update(detections)
# output bbox identities
outputs = []
for track in self.tracker.tracks:
if not track.is_confirmed() or track.time_since_update > 1:
continue
box = track.to_tlwh()
x1, y1, x2, y2 = self._tlwh_to_xyxy(box)
track_id = track.track_id
class_label = track.class_label
outputs.append(np.array([x1, y1, x2, y2, track_id, class_label], dtype=np.int))
if len(outputs) > 0:
outputs = np.stack(outputs, axis=0)
return np.array(outputs)
这是track.py的一部分
outputs = deepsort.update(xywhs, confss, leibies, im0)
if len(outputs) > 0:
bbox_xyxy = outputs[:, :4] # 提取前四列 坐标
identities = outputs[:, -1] # 提取最后一列 ID
box_xywh = xyxy2tlwh(bbox_xyxy)
# xyxy2tlwh是坐标格式转换,从x1, y1, x2, y2转为top left x ,top left y, w, h
for j in range(len(box_xywh)):
x_center = box_xywh[j][0] + box_xywh[j][2] / 2 # 求框的中心x坐标
y_center = box_xywh[j][1] + box_xywh[j][3] / 2 # 求框的中心y坐标
id = outputs[j][-1]
center = [x_center, y_center]
dict_box.setdefault(id, []).append(center)
COLORS_10 = (188, 143, 143)
if len(outputs) > 0:
# outputs = np.append(outputs,leibie,axis=1)
bbox_xyxy = outputs[:, :4]
identities = outputs[:, -1]
draw_boxes(im0, bbox_xyxy, identities)
bbox_cen = 0
if save_txt and len(outputs) != 0:
video_name = os.path.splitext(os.path.basename(vid_path))[0]
txt_path = os.path.join(out, video_name + '.txt')
targets = []
with open(txt_path, 'a') as f:
for j, output in enumerate(outputs):
bbox_left = output[0]
bbox_top = output[1]
bbox_w = output[2]
bbox_h = output[3]
identity = output[-2]
car_class = output[-1]
a = bbox_left + (bbox_w - bbox_left) / 2
b = bbox_top + (bbox_h - bbox_top) / 2
with open(txt_path, 'a') as f:
f.write(('%g ' * 9 + '\n') % (identity, car_class, bbox_left,
bbox_top, bbox_w, bbox_h, a, b, frame_idx)) # label format
class DeepSort(object):
def __init__(self, model_path, max_dist=0.2, min_confidence=0.3, nms_max_overlap=1.0, max_iou_distance=0.7, max_age=70, n_init=3, nn_budget=100, use_cuda=True, video_folder=None):
self.min_confidence = min_confidence
self.nms_max_overlap = nms_max_overlap
self.extractor = Extractor(model_path, use_cuda=use_cuda)
max_cosine_distance = max_dist
nn_budget = 100
metric = NearestNeighborDistanceMetric(
"cosine", max_cosine_distance, nn_budget)
self.tracker = Tracker(
metric, max_iou_distance=max_iou_distance, max_age=max_age, n_init=n_init)
self.video_folder = video_folder
# initialize deepsort
cfg = get_config()
cfg.merge_from_file(opt.config_deepsort)
deepsort = DeepSort(cfg.DEEPSORT.REID_CKPT,
max_dist=cfg.DEEPSORT.MAX_DIST, min_confidence=cfg.DEEPSORT.MIN_CONFIDENCE,
nms_max_overlap=cfg.DEEPSORT.NMS_MAX_OVERLAP, max_iou_distance=cfg.DEEPSORT.MAX_IOU_DISTANCE,
max_age=cfg.DEEPSORT.MAX_AGE, n_init=cfg.DEEPSORT.N_INIT, nn_budget=cfg.DEEPSORT.NN_BUDGET,
use_cuda=True)
大致思路:
在程序开头添加一个变量来跟踪当前处理的视频文件名,可以命名为current_video_name
在读取视频帧的循环中,在每次处理帧之前,将current_video_name设置为当前视频文件的名称
在update函数中,添加一个条件判断,根据current_video_name来保存检测结果,示例:
if current_video_name not in outputs:
outputs[current_video_name] = np.array([x1, y1, x2, y2, track_id, class_label], dtype=np.int)
这将确保每个视频的检测结果将保存在各自对应的输出txt文件中,而不是连续保存在一个txt文件中
来自GPT的回答:
要实现多个视频的检测和追踪,并将结果保存到各自的文本文件中,可以对代码进行如下修改:
在保存文本文件时,使用视频文件的名称作为文本文件的命名。你可以通过将视频文件的基本名称与 ".txt" 扩展名结合来实现。例如,将 video_name 与 ".txt" 拼接在一起。
python
Copy code
video_name = os.path.splitext(os.path.basename(vid_path))[0]
txt_path = os.path.join(out, video_name + '.txt')
在每个视频处理的循环内,使用一个新的字典来存储每个视频的结果。可以在循环的开头使用 dict_box = {} 来创建一个空的字典。
在追踪和绘制边界框之后,将结果保存到各自的视频字典中,而不是全局的 dict_box 中。这可以通过将 dict_box 替换为视频特定的字典来实现。这样,每个视频的结果将被保存在它们自己的字典中,互不干扰。
python
Copy code
# 创建视频特定的字典
video_dict_box = {}
...
# 将结果保存到视频特定的字典中
video_dict_box.setdefault(id, []).append(center)
...
# 在绘制边界框之后,将结果保存到视频特定的字典中
if save_txt and len(outputs) != 0:
...
with open(txt_path, 'a') as f:
for j, output in enumerate(outputs):
...
video_dict_box.setdefault(identity, []).append((bbox_left, bbox_top, bbox_w, bbox_h, a, b, frame_idx))
在处理完每个视频后,将视频字典中的结果保存到对应的文本文件中。这可以通过在视频循环的末尾添加保存到文本文件的代码来实现。
python
Copy code
# 保存视频字典中的结果到文本文件
with open(txt_path, 'a') as f:
for id, bbox_list in video_dict_box.items():
for bbox in bbox_list:
f.write(('%g ' * 9 + '\n') % (id, bbox[0], bbox[1], bbox[2], bbox[3], bbox[4], bbox[5], bbox[6], frame_idx))
通过上述修改,你将能够实现多个视频的检测和追踪,每个视频的结果将保存在各自的文本文件中,而且彼此之间不会产生干扰。请注意,你需要根据实际情况进行适当的调整和修改,以确保代码在你的环境中能够正常运行。
烟火数据集 10000+
安全帽数据集 11000+
口罩数据集 8000+
抽烟数据集 7000+
打电话数据集 10000+
电动车数据集 未知
睡觉数据集 未知
利用 yolov5 的高效目标检测和 deepsort 的运动和外观信息来跟踪视频中的不同对象,并为每个对象分配一个唯一的 ID
参考 https://blog.csdn.net/qq_42722197/article/details/130256915
OLOv5+DeepSORT多目标跟踪深入解读
可以参考下
https://blog.csdn.net/yohnyang/article/details/127458513
https://cloud.tencent.com/developer/article/2121746
定义一个全局的标识变量,用于记录当前跟踪的视频是哪一个,然后在记录保存信息到txt的代码中,根据这个变量的值,就可以知道当前是在跟踪哪一个视频,然后用这个变量的值,或者另取一个名称,作为文件名称作为存储txt信息的名称。
检测到视频切换后,重新保存txt
依次保存到不同的txt
import os
import threading
from yolov5s import YOLOv5S, DeepSort
# 定义检测函数
def detect_video(video_path):
# 加载模型和配置文件
yolo = YOLOv5S()
config = yolo.get_config()
model = yolo.load_model(config)
# 加载跟踪器
tracker = DeepSort()
# 读取视频文件
cap = cv2.VideoCapture(video_path)
fps = int(cap.get(cv2.CAP_PROP_FPS))
num_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# 初始化跟踪器
track_ids = []
tracks = []
for i in range(num_frames):
ret, frame = cap.read()
if not ret:
break
# 对每一帧进行目标检测和跟踪
detections, tracking_ids = model.detect(frame)
tracked_objects = tracker.update(detections, tracking_ids)
# 将跟踪结果添加到tracks列表中
for obj in tracked_objects:
tlbr = obj['bbox']
track_id = obj['track_id']
track_ids.append(track_id)
tracks.append((tlbr[0], tlbr[1], track_id))
# 将当前帧写入输出文件中
output_path = os.path.splitext(video_path)[0] + '-frame{}.jpg'.format(i)
cv2.imwrite(output_path, frame)
# 将跟踪结果保存到txt文件中
with open('{}-tracks.txt'.format(os.path.splitext(video_path)[0]), 'w') as f:
for track in tracks:
tlbr = track[0:3]
track_id = track[3]
f.write('{} {} {} \n'.format(tlbr[0], tlbr[1], track_id))
cap.release()
yolo.destroy()
# 在主函数中调用检测函数,并使用多线程处理多个视频文件
if __name__ == '__main__':
video_folder = 'path/to/video/folder'
os.chdir(video_folder)
num_threads = 4 # 根据需要调整线程数
tlist = [] # 用列表存储所有线程对象,用于启动和停止它们
for video_name in os.listdir(): # 对于每个视频文件执行以下操作:
video_path = os.path.join(video_folder, video_name) # 获取视频路径
t = threading.Thread(target=detect_video, args=(video_path,)) # 为每个视频创建一个线程对象,并将其添加到列表中
tlist.append(t) # 将线程对象添加到列表中以便启动和停止它们
t.start() # 启动线程对象,开始处理视频文件
for i in range(len(tlist)): # 确保所有线程都已启动后,等待它们完成任务:
tlist[i].join() # 加入此行以防止程序退出之前未完成所有任务。如果不需要等待所有线程完成,请删除此行。
两个方法:
在处理每个新视频时重置DeepSORT跟踪器,调用DeepSORT实例的reset()方法来完成这一操作。但是你的代码中没有显示如何创建DeepSORT的实例。如果你的DeepSORT实例的名称是deepsort,可以在处理每个新视频之前,用下面的代码来重置DeepSORT:
deepsort.tracker.reset()
只重置DeepSORT的跟踪器部分,而不会影响其它部分(例如特征提取器)。如果DeepSORT的其他部分也需要被重置,可能要创建一个新的DeepSORT实例。
另一种方法是在每个视频开始时创建一个新的DeepSORT实例。将确保所有的状态都被重置,但可能会导致更高的计算开销。如果选择这种方式,可以在处理每个新视频之前使用下面的代码来创建新的DeepSORT实例:
deepsort = DeepSort(...)
以下答案参考newbing,回答由博主波罗歌编写:
根据你的描述,你想实现使用yolov5s+deepsort对多个视频进行检测和追踪,并将每个视频的结果保存到不同的txt文件中。
首先,你需要获取视频文件夹中的所有视频文件路径。你可以使用Python的os模块来实现这个功能。以下是一个示例代码:
import os
video_folder = '/path/to/video/folder'
video_files = [os.path.join(video_folder, file) for file in os.listdir(video_folder) if file.endswith('.mp4')]
接下来,你需要遍历每个视频文件,并在每个视频上运行yolov5s+deepsort。在这个过程中,你可以将每个视频的结果保存到不同的txt文件中。你可以使用视频文件的名称作为txt文件的名称。以下是一个示例代码:
for video_file in video_files:
# 运行yolov5s+deepsort,并获取结果outputs
# 保存输出到txt文件
video_name = os.path.splitext(os.path.basename(video_file))[0]
txt_path = os.path.join(out, video_name + '.txt')
with open(txt_path, 'a') as f:
# 将outputs写入txt文件
for j, output in enumerate(outputs):
# 写入output到txt文件
f.write(('%g ' * 9 + '\n') % (identity, car_class, bbox_left, bbox_top, bbox_w, bbox_h, a, b, frame_idx))
在这段代码中,video_file
是当前处理的视频文件路径,outputs
是yolov5s+deepsort的输出结果。你需要将输出结果写入到对应的txt文件中,使用视频文件名作为txt文件名。
请记住,在你的代码中要正确导入所需的库,并将变量和参数调整到适当的位置。希望这个回答能对你有帮助!如果还有其他问题,请随时提问。
如果我的回答解决了您的问题,请采纳!