基本设计思路
基于YOLOv8对象检测/实例分割模型,实现一个基于检测的对象跟踪算法,YOLOv8支持两种主流的对象跟踪算法ByteTrack与Botsort。通过自定义数据训练YOLOv8对象检测器可以实现不同类别的对象的跟踪。同时基于检测与跟踪模型的输出,实现了对象计数、指定类别跟踪、区域流量统计、指定ID跟踪、单对象与多对象跟踪等操作。
应用开发层面,需要三个主要的交互与显示界面,一个是针对YOLOv8检测与跟踪模型的模型参数设置;第二个是针对YOLOv8检测与跟踪结果的显示过滤与输出过滤的后处理;第三个是针对后处理数据的显示包括流量出入、是否需要语音报警等应用层面的数据展示。
整个程序开发实现了跟踪线程与界面线程分别独立工作,支持数据交互,实时显示运行结果与流量统计信息展示。最终完成的界面设计如下:
运行截图
实时车辆流量统计
基于对象ID的单对象跟踪:
人流量出入统计
代码
启动跟踪开始交通流量统计线程的代码如下:
def on_yolov8_track(self): image_file = self.image_file_edit.text() label_file = self.label_file_path.text() model_file = self.weight_file_path.text() if len(image_file) == 0 or len(label_file) == 0 or len(model_file) == 0: QtWidgets.QMessageBox.warning(self, "警告", "参数文件未选择...") return self.traffic_delta_label.setText("流量净值: 0") self.traffic_jam_label.setText("总流量: 0") self.input_traffic_label.setText("进流量: 0") self.output_traffic_label.setText("出流量: 0") settings = DLInferSettings() settings.weight_file_path = self.weight_file_path.text() settings.label_map_file_path = self.label_file_path.text() settings.score_threshold = self.conf_spinbox.value() settings.input_image = image_file settings.track_vehicle = self.vehicle_chkbox.isChecked() settings.track_person = self.person_chkbox.isChecked() settings.track_by_category_index = self.category_combox.currentIndex() settings.track_id = self.track_by_id_spin_box.value() settings.target_deploy = 1 if self.hline_rbtn.isChecked(): settings.track_line_type = 0 if self.vline_rbtn.isChecked(): settings.track_line_type = 1 if self.diagonal_rbtn.isChecked(): settings.track_line_type = 2 self.work_thread = InferenceThread(settings) self.work_thread.fire_stats_signal.connect(self.on_update_result_image) self.work_thread.finished.connect(self.work_thread.deleteLater) self.work_thread.start() self.startBtn.setStyleSheet("background-color:gray; color: white") self.startBtn.setEnabled(False) self.stopBtn.setStyleSheet("background-color:cyan; color: black") self.stopBtn.setEnabled(True)使用槽函数更新界面,实现实时分析结果显示的代码如下:
def on_update_result_image(self, outs): image = outs.get("result") done = outs.get("done") num_in = outs.get("num_in") num_out = outs.get("num_out") if image is not None: dst = cv.cvtColor(image, cv.COLOR_BGR2RGB) height, width, channel = dst.shape bytesPerLine = 3 * width img = QtGui.QImage(dst.data, width, height, bytesPerLine, QtGui.QImage.Format_RGB888) pixmap = QtGui.QPixmap(img) pix = pixmap.scaled(QtCore.QSize(1280, 720), QtCore.Qt.KeepAspectRatio) self.label.setPixmap(pix) self.show_text("OpenCV开发者联盟-跟踪演示") self.traffic_delta_label.setText("流量净值: %d" % (num_in - num_out)) self.traffic_jam_label.setText("总流量: %d" % (num_in + num_out)) self.input_traffic_label.setText("进流量: %d" % num_in) self.output_traffic_label.setText("出流量: %d" % num_out) if done is not None: self.stopBtn.setStyleSheet("background-color:gray; color: white") self.stopBtn.setEnabled(False) self.startBtn.setStyleSheet("background-color:cyan; color: black") self.startBtn.setEnabled(True)
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !