车辆违规开启远光灯检测系统:融合YOLO-MS改进YOLOv8

1.研究背景与意义

项目参考AAAI Association for the Advancement of Artificial Intelligence

研究背景与意义

随着社会的不断发展和交通工具的普及,车辆违规行为成为了一个严重的问题。其中,车辆违规开启远光灯是一种常见的违规行为,给其他车辆和行人带来了安全隐患。因此,开发一种有效的车辆违规开启远光灯检测系统具有重要的现实意义。

违规开启远光灯的行为主要有两个方面的危害。首先,违规开启远光灯会对其他车辆的驾驶造成干扰,降低其他车辆的视线,增加交通事故的风险。特别是在夜间或恶劣的天气条件下,远光灯的强光会直接照射到其他车辆的驾驶员眼睛,导致视线模糊,容易发生事故。其次,违规开启远光灯也会对行人的安全构成威胁。当行人在夜间或者路灯较暗的地方行走时,远光灯的强光会使行人视线受到干扰,增加行人被撞的风险。

目前,已经有一些研究关注车辆违规开启远光灯的检测问题。传统的方法主要基于图像处理和计算机视觉技术,通过提取图像中的特征来判断车辆是否开启了远光灯。然而,由于图像中的光照条件、车辆姿态和背景干扰等因素的影响,传统方法在检测准确性和鲁棒性方面存在一定的局限性。

为了解决这些问题,本研究提出了一种融合YOLO-MS改进YOLOv8的车辆违规开启远光灯检测系统。YOLO-MS是一种基于深度学习的目标检测算法,能够实现实时的目标检测任务。通过融合YOLO-MS和改进的YOLOv8算法,我们可以有效地提高车辆违规开启远光灯的检测准确性和鲁棒性。

本研究的意义主要体现在以下几个方面。首先,通过开发一种有效的车辆违规开启远光灯检测系统,可以提高交通安全水平,减少交通事故的发生。其次,该系统可以帮助交警部门更好地监管道路交通秩序,提高交通管理的效率。同时,该系统还可以为车辆驾驶员提供一个良好的驾驶环境,减少驾驶员的驾驶压力和疲劳程度。

此外,本研究还具有一定的学术意义。通过融合YOLO-MS和改进的YOLOv8算法,可以为目标检测领域的研究提供一个新的思路和方法。同时,本研究还可以为其他类似的违规行为检测问题提供参考和借鉴,推动相关领域的研究和发展。

综上所述,开发一种融合YOLO-MS改进YOLOv8的车辆违规开启远光灯检测系统具有重要的现实意义和学术价值。通过该系统的应用,可以提高交通安全水平,减少交通事故的发生,为交通管理和驾驶员提供更好的服务。同时,该系统的研究也为目标检测领域的发展提供了新的思路和方法。

2.图片演示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.视频演示

车辆违规开启远光灯检测系统:融合YOLO-MS改进YOLOv8_哔哩哔哩_bilibili

4.数据集的采集&标注和整理

图片的收集

首先,我们需要收集所需的图片。这可以通过不同的方式来实现,例如使用现有的公开数据集YGDatasets。

在这里插入图片描述

labelImg是一个图形化的图像注释工具,支持VOC和YOLO格式。以下是使用labelImg将图片标注为VOC格式的步骤:

(1)下载并安装labelImg。
(2)打开labelImg并选择“Open Dir”来选择你的图片目录。
(3)为你的目标对象设置标签名称。
(4)在图片上绘制矩形框,选择对应的标签。
(5)保存标注信息,这将在图片目录下生成一个与图片同名的XML文件。
(6)重复此过程,直到所有的图片都标注完毕。

由于YOLO使用的是txt格式的标注,我们需要将VOC格式转换为YOLO格式。可以使用各种转换工具或脚本来实现。

下面是一个简单的方法是使用Python脚本,该脚本读取XML文件,然后将其转换为YOLO所需的txt格式。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-import xml.etree.ElementTree as ET
import osclasses = []  # 初始化为空列表CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))def convert(size, box):dw = 1. / size[0]dh = 1. / size[1]x = (box[0] + box[1]) / 2.0y = (box[2] + box[3]) / 2.0w = box[1] - box[0]h = box[3] - box[2]x = x * dww = w * dwy = y * dhh = h * dhreturn (x, y, w, h)def convert_annotation(image_id):in_file = open('./label_xml\%s.xml' % (image_id), encoding='UTF-8')out_file = open('./label_txt\%s.txt' % (image_id), 'w')  # 生成txt格式文件tree = ET.parse(in_file)root = tree.getroot()size = root.find('size')w = int(size.find('width').text)h = int(size.find('height').text)for obj in root.iter('object'):cls = obj.find('name').textif cls not in classes:classes.append(cls)  # 如果类别不存在,添加到classes列表中cls_id = classes.index(cls)xmlbox = obj.find('bndbox')b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),float(xmlbox.find('ymax').text))bb = convert((w, h), b)out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')xml_path = os.path.join(CURRENT_DIR, './label_xml/')# xml list
img_xmls = os.listdir(xml_path)
for img_xml in img_xmls:label_name = img_xml.split('.')[0]print(label_name)convert_annotation(label_name)print("Classes:")  # 打印最终的classes列表
print(classes)  # 打印最终的classes列表
整理数据文件夹结构

我们需要将数据集整理为以下结构:

-----data|-----train|   |-----images|   |-----labels||-----valid|   |-----images|   |-----labels||-----test|-----images|-----labels

确保以下几点:

所有的训练图片都位于data/train/images目录下,相应的标注文件位于data/train/labels目录下。
所有的验证图片都位于data/valid/images目录下,相应的标注文件位于data/valid/labels目录下。
所有的测试图片都位于data/test/images目录下,相应的标注文件位于data/test/labels目录下。
这样的结构使得数据的管理和模型的训练、验证和测试变得非常方便。

模型训练
 Epoch   gpu_mem       box       obj       cls    labels  img_size1/200     20.8G   0.01576   0.01955  0.007536        22      1280: 100%|██████████| 849/849 [14:42<00:00,  1.04s/it]Class     Images     Labels          P          R     mAP@.5 mAP@.5:.95: 100%|██████████| 213/213 [01:14<00:00,  2.87it/s]all       3395      17314      0.994      0.957      0.0957      0.0843Epoch   gpu_mem       box       obj       cls    labels  img_size2/200     20.8G   0.01578   0.01923  0.007006        22      1280: 100%|██████████| 849/849 [14:44<00:00,  1.04s/it]Class     Images     Labels          P          R     mAP@.5 mAP@.5:.95: 100%|██████████| 213/213 [01:12<00:00,  2.95it/s]all       3395      17314      0.996      0.956      0.0957      0.0845Epoch   gpu_mem       box       obj       cls    labels  img_size3/200     20.8G   0.01561    0.0191  0.006895        27      1280: 100%|██████████| 849/849 [10:56<00:00,  1.29it/s]Class     Images     Labels          P          R     mAP@.5 mAP@.5:.95: 100%|███████   | 187/213 [00:52<00:00,  4.04it/s]all       3395      17314      0.996      0.957      0.0957      0.0845

5.核心代码讲解

5.1 dark.py

封装为类后的代码如下:

from PIL import Image
import osclass ImageProcessor:def __init__(self, folder):self.folder = folderdef process_images(self):img_files = [f for f in os.listdir(self.folder) if f.endswith('.jpg') or f.endswith('.png')]for img_file in img_files:img_path = os.path.join(self.folder, img_file)img = Image.open(img_path)img_05 = img.point(lambda x: x * 0.5)img_05_path = os.path.join(self.folder, '05_' + img_file)img_05.save(img_05_path)img_2 = img.point(lambda x: x * 2)img_2_path = os.path.join(self.folder, '2_' + img_file)img_2.save(img_2_path)

这样封装为类后,可以通过创建一个ImageProcessor对象来处理指定文件夹中的图片。在process_images方法中,会逐一处理每张图片,调整亮度为0.5倍和2倍,并保存到指定的文件夹中。

这个程序文件名为dark.py,主要功能是对指定文件夹中的图片进行亮度调整,并保存处理后的图片。

首先,程序使用os模块中的listdir函数获取指定文件夹(‘src’文件夹)中所有的图片文件名,并将其存储在img_files列表中。这里使用了列表推导式,筛选出以’.jpg’或’.png’结尾的文件。

然后,程序使用循环逐一处理每张图片。首先,通过os模块中的join函数将图片文件名与文件夹路径拼接,得到图片的完整路径。然后,使用PIL库中的Image.open函数打开图片。

接下来,程序使用point方法对图片进行亮度调整。对于每个像素点,使用lambda函数将其亮度乘以0.5,得到调整亮度为0.5倍的图片img_05。然后,使用os模块中的join函数将新图片的文件名与文件夹路径拼接,得到新图片的完整路径img_05_path。最后,使用img_05对象的save方法将调整后的图片保存到指定路径。

然后,程序再次使用point方法对原始图片进行亮度调整。对于每个像素点,使用lambda函数将其亮度乘以2,得到调整亮度为2倍的图片img_2。然后,使用os模块中的join函数将新图片的文件名与文件夹路径拼接,得到新图片的完整路径img_2_path。最后,使用img_2对象的save方法将调整后的图片保存到指定路径。

整个程序的功能就是对指定文件夹中的图片进行亮度调整,并保存处理后的图片。

5.2 demo.py
class CarNumberRecognition:def __init__(self):self.model = pr.LPR("model/cascade.xml", "model/model12.h5", "model/ocr_plate_all_gru.h5")self.fontC = ImageFont.truetype("./Font/platech.ttf", 14, 0)def speed_test(self, image_path):grr = cv2.imread(image_path)self.model.SimpleRecognizePlateByE2E(grr)t0 = time.time()for x in range(20):self.model.SimpleRecognizePlateByE2E(grr)t = (time.time() - t0) / 20.0print("Image size :" + str(grr.shape[1]) + "x" + str(grr.shape[0]) + " need " + str(round(t * 1000, 2)) + "ms")def draw_rect_box(self, image, rect, add_text):cv2.rectangle(image, (int(rect[0]), int(rect[1])), (int(rect[0] + rect[2]), int(rect[1] + rect[3])), (0, 0, 255), 2, cv2.LINE_AA)cv2.rectangle(image, (int(rect[0] - 1), int(rect[1]) - 16), (int(rect[0] + 115), int(rect[1])), (0, 0, 255), -1, cv2.LINE_AA)img = Image.fromarray(image)draw = ImageDraw.Draw(img)draw.text((int(rect[0] + 1), int(rect[1] - 16)), add_text, (255, 255, 255), font=self.fontC)imagex = np.array(img)return imagexdef carnum_rec(self, grr):for pstr, confidence, rect in self.model.SimpleRecognizePlateByE2E(grr):if confidence > 0.7:image = self.draw_rect_box(grr, rect, pstr + " " + str(round(confidence, 3)))print("plate_str:")print(pstr)print("plate_confidence")print(confidence)cv2.imshow("enhanced", image)def video_capture(self):capture = cv2.VideoCapture("src/carnum.avi")i = 1while (True):ref, frame = capture.read()if ref:cv2.imshow("enhanced", frame)i = i + 1if i % 10 == 0:i = 0self.carnum_rec(frame)c = cv2.waitKey(30) & 0xffif c == 27:capture.release()breakelse:break

程序的主要逻辑是在if name == ‘main’:部分,首先初始化了一个LPR对象,然后调用video_capture函数进行视频捕获,最后关闭窗口。

5.3 hyper_test.py
class CarNumberRecognition:def __init__(self, video_path):self.video_path = video_pathdef recognize(self):capture = cv.VideoCapture(self.video_path)j = 1while (True):ref, frame = capture.read()if ref:j = j + 1if j % 5 == 0:j = 0image = frameresult = HyperLPR_plate_recognition(image)for i in result:p1, p2 = (i[2][0], i[2][1]), (i[2][2], i[2][3])cv2.rectangle(image, p1, p2, [0, 0, 255], thickness=3, lineType=cv2.LINE_AA)cv2.putText(image, str(i[0]), (i[2][0], i[2][1] - 10),cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2)cv2.imshow('result',image)cv2.waitKey(1)c = cv.waitKey(5) & 0xffif c == 27:capture.release()breakelse:breakif __name__ == '__main__':cr = CarNumberRecognition("car.mp4")cr.recognize()cv.destroyAllWindows()

这个程序文件名为hyper_test.py,主要功能是通过摄像头或者读取视频文件来进行车牌识别。程序使用了hyperlpr包和OpenCV库。其中,video_demo()函数通过读取视频文件,循环读取每一帧图像并在按下ESC键时退出程序。

5.4 predict.py

封装为类后的代码如下:

from ultralytics.engine.predictor import BasePredictor
from ultralytics.engine.results import Results
from ultralytics.utils import opsclass DetectionPredictor(BasePredictor):def postprocess(self, preds, img, orig_imgs):preds = ops.non_max_suppression(preds,self.args.conf,self.args.iou,agnostic=self.args.agnostic_nms,max_det=self.args.max_det,classes=self.args.classes)if not isinstance(orig_imgs, list):orig_imgs = ops.convert_torch2numpy_batch(orig_imgs)results = []for i, pred in enumerate(preds):orig_img = orig_imgs[i]pred[:, :4] = ops.scale_boxes(img.shape[2:], pred[:, :4], orig_img.shape)img_path = self.batch[0][i]results.append(Results(orig_img, path=img_path, names=self.model.names, boxes=pred))return results

这个程序文件是一个名为predict.py的文件,它是一个用于预测基于检测模型的类DetectionPredictor的定义。这个类继承自BasePredictor类,并实现了postprocess方法用于后处理预测结果。该文件还导入了一些需要的模块和函数,如BasePredictor类、Results类和ops模块。在文件中还提供了一个示例用法,展示了如何使用DetectionPredictor类进行预测。

5.6 train.py
from copy import copy
import numpy as np
from ultralytics.data import build_dataloader, build_yolo_dataset
from ultralytics.engine.trainer import BaseTrainer
from ultralytics.models import yolo
from ultralytics.nn.tasks import DetectionModel
from ultralytics.utils import LOGGER, RANK
from ultralytics.utils.torch_utils import de_parallel, torch_distributed_zero_firstclass DetectionTrainer(BaseTrainer):def build_dataset(self, img_path, mode='train', batch=None):gs = max(int(de_parallel(self.model).stride.max() if self.model else 0), 32)return build_yolo_dataset(self.args, img_path, batch, self.data, mode=mode, rect=mode == 'val', stride=gs)def get_dataloader(self, dataset_path, batch_size=16, rank=0, mode='train'):assert mode in ['train', 'val']with torch_distributed_zero_first(rank):dataset = self.build_dataset(dataset_path, mode, batch_size)shuffle = mode == 'train'if getattr(dataset, 'rect', False) and shuffle:LOGGER.warning("WARNING ⚠️ 'rect=True' is incompatible with DataLoader shuffle, setting shuffle=False")shuffle = Falseworkers = 0return build_dataloader(dataset, batch_size, workers, shuffle, rank)def preprocess_batch(self, batch):batch['img'] = batch['img'].to(self.device, non_blocking=True).float() / 255return batchdef set_model_attributes(self):self.model.nc = self.data['nc']self.model.names = self.data['names']self.model.args = self.argsdef get_model(self, cfg=None, weights=None, verbose=True):model = DetectionModel(cfg, nc=self.data['nc'], verbose=verbose and RANK == -1)if weights:model.load(weights)return modeldef get_validator(self):self.loss_names = 'box_loss', 'cls_loss', 'dfl_loss'return yolo.detect.DetectionValidator(self.test_loader, save_dir=self.save_dir, args=copy(self.args))def label_loss_items(self, loss_items=None, prefix='train'):keys = [f'{prefix}/{x}' for x in self.loss_names]if loss_items is not None:loss_items = [round(float(x), 5) for x in loss_items]return dict(zip(keys, loss_items))else:return keysdef progress_string(self):return ('\n' + '%11s' *(4 + len(self.loss_names))) % ('Epoch', 'GPU_mem', *self.loss_names, 'Instances', 'Size')def plot_training_samples(self, batch, ni):plot_images(images=batch['img'],batch_idx=batch['batch_idx'],cls=batch['cls'].squeeze(-1),bboxes=batch['bboxes'],paths=batch['im_file'],fname=self.save_dir / f'train_batch{ni}.jpg',on_plot=self.on_plot)def plot_metrics(self):plot_results(file=self.csv, on_plot=self.on_plot)def plot_training_labels(self):boxes = np.concatenate([lb['bboxes'] for lb in self.train_loader.dataset.labels], 0)cls = np.concatenate([lb['cls'] for lb in self.train_loader.dataset.labels], 0)plot_labels(boxes, cls.squeeze(), names=self.data['names'], save_dir=self.save_dir, on_plot=self.on_plot)

这是一个用于训练基于检测模型的程序文件。它使用Ultralytics YOLO库进行目标检测模型的训练。

该文件包含了一个名为DetectionTrainer的类,它继承自BaseTrainer类,用于训练基于检测模型的任务。

该类具有以下主要方法和功能:

  • build_dataset方法:构建YOLO数据集。
  • get_dataloader方法:构建并返回数据加载器。
  • preprocess_batch方法:对图像批次进行预处理,包括缩放和转换为浮点数。
  • set_model_attributes方法:设置模型的属性,包括类别数量、类别名称和超参数。
  • get_model方法:返回一个YOLO检测模型。
  • get_validator方法:返回一个用于YOLO模型验证的DetectionValidator对象。
  • label_loss_items方法:返回一个带有标记的训练损失项的损失字典。
  • progress_string方法:返回一个格式化的训练进度字符串,包括当前的训练轮数、GPU内存、损失、实例数量和数据集大小。
  • plot_training_samples方法:绘制训练样本及其注释。
  • plot_metrics方法:绘制来自CSV文件的指标。
  • plot_training_labels方法:创建一个带有标签的训练模型的绘图。

if __name__ == '__main__':部分,创建了一个DetectionTrainer对象,并使用给定的参数进行训练。

该程序文件使用了Ultralytics YOLO库中的各种模块和工具来实现目标检测模型的训练,并提供了一些方便的方法来处理数据集、模型和训练过程中的可视化。

6.系统整体结构

根据以上分析,可以对程序的整体功能和构架进行如下概括:

整体功能:远光灯检测系统,融合了YOLO-MS改进YOLOv8模型,用于检测车辆违规开启远光灯的行为。

整体构架:程序包含多个文件,每个文件负责不同的功能模块。以下是每个文件的功能概述:

文件名功能
predict.py实现远光灯检测模型的预测功能
test.py进行远光灯检测的测试
train.py训练远光灯检测模型
ui.py实现用户界面的交互
backbone/convnextv2.pyConvNextV2模型的实现
backbone/CSwomTramsformer.pyCSwomTramsformer模型的实现
backbone/EfficientFormerV2.pyEfficientFormerV2模型的实现
backbone/efficientViT.pyefficientViT模型的实现
backbone/fasternet.pyFasternet模型的实现
backbone/lsknet.pyLSKNet模型的实现
backbone/repvit.pyRepVIT模型的实现
backbone/revcol.pyRevCol模型的实现
backbone/SwinTransformer.pySwinTransformer模型的实现
backbone/VanillaNet.pyVanillaNet模型的实现
extra_modules/afpn.pyAFPN模块的实现
extra_modules/attention.pyAttention模块的实现
extra_modules/block.pyBlock模块的实现
extra_modules/dynamic_snake_conv.pyDynamic Snake Conv模块的实现
extra_modules/head.pyHead模块的实现
extra_modules/kernel_warehouse.pyKernel Warehouse模块的实现
extra_modules/orepa.pyOREPA模块的实现
extra_modules/rep_block.pyRep Block模块的实现
extra_modules/RFAConv.pyRFAConv模块的实现
models/common.py通用模型函数
models/experimental.py实验性模型的实现
models/tf.pyTensorFlow模型的实现
models/yolo.pyYOLO模型的实现
ultralytics/init.pyUltralytics库的初始化文件
ultralytics/cfg/init.pyUltralytics库的配置文件初始化
ultralytics/data/annotator.py数据标注工具
ultralytics/data/augment.py数据增强工具
ultralytics/data/base.py数据集基类
ultralytics/data/build.py构建数据集的工具
ultralytics/data/converter.py数据转换工具
ultralytics/data/dataset.py数据集类
ultralytics/data/loaders.py数据加载器
ultralytics/data/utils.py数据集工具函数
ultralytics/engine/exporter.py模型导出工具
ultralytics/engine/model.py模型类
ultralytics/engine/predictor.py模型预测类
ultralytics/engine/results.py结果类
ultralytics/engine/trainer.py训练器类
ultralytics/engine/tuner.py调参器类
ultralytics/engine/validator.py验证器类

7.YOLOv8简介

按照官方描述,YOLOv8 是一个 SOTA 模型,它建立在以前 YOLO 版本的成功基础上,并引入了新的功能和改进,以进一步提升性能和灵活性。具体创新包括一个新的骨干网络、一个新的 Ancher-Free 检测头和一个新的损失函数,可以在从 CPU 到 GPU 的各种硬件平台上运行。

不过 ultralytics 并没有直接将开源库命名为 YOLOv8,而是直接使用 ultralytics 这个词,原因是 ultralytics 将这个库定位为算法框架,而非某一个特定算法,一个主要特点是可扩展性。其希望这个库不仅仅能够用于 YOLO 系列模型,而是能够支持非 YOLO 模型以及分类分割姿态估计等各类任务。
总而言之,ultralytics 开源库的两个主要优点是:

融合众多当前 SOTA 技术于一体
未来将支持其他 YOLO 系列以及 YOLO 之外的更多算法
在这里插入图片描述

下表为官方在 COCO Val 2017 数据集上测试的 mAP、参数量和 FLOPs 结果。可以看出 YOLOv8 相比 YOLOv5 精度提升非常多,但是 N/S/M 模型相应的参数量和 FLOPs 都增加了不少,从上图也可以看出相比 YOLOV5 大部分模型推理速度变慢了。

在这里插入图片描述

额外提一句,现在各个 YOLO 系列改进算法都在 COCO 上面有明显性能提升,但是在自定义数据集上面的泛化性还没有得到广泛验证,至今依然听到不少关于 YOLOv5 泛化性能较优异的说法。对各系列 YOLO 泛化性验证也是 MMYOLO 中一个特别关心和重点发力的方向。

8.YOLO-MS简介

实时目标检测,以YOLO系列为例,已在工业领域中找到重要应用,特别是在边缘设备(如无人机和机器人)中。与之前的目标检测器不同,实时目标检测器旨在在速度和准确性之间追求最佳平衡。为了实现这一目标,提出了大量的工作:从第一代DarkNet到CSPNet,再到最近的扩展ELAN,随着性能的快速增长,实时目标检测器的架构经历了巨大的变化。

尽管性能令人印象深刻,但在不同尺度上识别对象仍然是实时目标检测器面临的基本挑战。这促使作者设计了一个强大的编码器架构,用于学习具有表现力的多尺度特征表示。具体而言,作者从两个新的角度考虑为实时目标检测编码多尺度特征:

从局部视角出发,作者设计了一个具有简单而有效的分层特征融合策略的MS-Block。受到Res2Net的启发,作者在MS-Block中引入了多个分支来进行特征提取,但不同的是,作者使用了一个带有深度卷积的 Inverted Bottleneck Block块,以实现对大Kernel的高效利用。

从全局视角出发,作者提出随着网络加深逐渐增加卷积的Kernel-Size。作者在浅层使用小Kernel卷积来更高效地处理高分辨率特征。另一方面,在深层中,作者采用大Kernel卷积来捕捉广泛的信息。

基于以上设计原则,作者呈现了作者的实时目标检测器,称为YOLO-MS。为了评估作者的YOLO-MS的性能,作者在MS COCO数据集上进行了全面的实验。还提供了与其他最先进方法的定量比较,以展示作者方法的强大性能。如图1所示,YOLO-MS在计算性能平衡方面优于其他近期的实时目标检测器。

在这里插入图片描述

具体而言,YOLO-MS-XS在MS COCO上获得了43%+的AP得分,仅具有450万个可学习参数和8.7亿个FLOPs。YOLO-MS-S和YOLO-MS分别获得了46%+和51%+的AP,可学习参数分别为810万和2220万。此外,作者的工作还可以作为其他YOLO模型的即插即用模块。通常情况下,作者的方法可以将YOLOv8的AP从37%+显著提高到40%+,甚至还可以使用更少的参数和FLOPs。

Multi-Scale Building Block Design

CSP Block是一个基于阶段级梯度路径的网络,平衡了梯度组合和计算成本。它是广泛应用于YOLO系列的基本构建块。已经提出了几种变体,包括YOLOv4和YOLOv5中的原始版本,Scaled YOLOv4中的CSPVoVNet,YOLOv7中的ELAN,以及RTMDet中提出的大Kernel单元。作者在图2(a)和图2(b)中分别展示了原始CSP块和ELAN的结构。

在这里插入图片描述

上述实时检测器中被忽视的一个关键方面是如何在基本构建块中编码多尺度特征。其中一个强大的设计原则是Res2Net,它聚合了来自不同层次的特征以增强多尺度表示。然而,这一原则并没有充分探索大Kernel卷积的作用,而大Kernel卷积已经在基于CNN的视觉识别任务模型中证明有效。将大Kernel卷积纳入Res2Net的主要障碍在于它们引入的计算开销,因为构建块采用了标准卷积。在作者的方法中,作者提出用 Inverted Bottleneck Block替代标准的3 × 3卷积,以享受大Kernel卷积的好处。

基于前面的分析,作者提出了一个带有分层特征融合策略的全新Block,称为MS-Block,以增强实时目标检测器在提取多尺度特征时的能力,同时保持快速的推理速度。

MS-Block的具体结构如图2©所示。假设是输入特征。通过1×1卷积的转换后,X的通道维度增加到n*C。然后,作者将X分割成n个不同的组,表示为,其中。为了降低计算成本,作者选择n为3。

注意,除了之外,每个其他组都经过一个 Inverted Bottleneck Block层,用表示,其中k表示Kernel-Size,以获得。的数学表示如下:

在这里插入图片描述

根据这个公式,该博客的作者不将 Inverted Bottleneck Block层连接,使其作为跨阶段连接,并保留来自前面层的信息。最后,作者将所有分割连接在一起,并应用1×1卷积来在所有分割之间进行交互,每个分割都编码不同尺度的特征。当网络加深时,这个1×1卷积也用于调整通道数。

Heterogeneous Kernel Selection Protocol

除了构建块的设计外,作者还从宏观角度探讨了卷积的使用。之前的实时目标检测器在不同的编码器阶段采用了同质卷积(即具有相同Kernel-Size的卷积),但作者认为这不是提取多尺度语义信息的最佳选项。

在金字塔结构中,从检测器的浅阶段提取的高分辨率特征通常用于捕捉细粒度语义,将用于检测小目标。相反,来自网络较深阶段的低分辨率特征用于捕捉高级语义,将用于检测大目标。如果作者在所有阶段都采用统一的小Kernel卷积,深阶段的有效感受野(ERF)将受到限制,影响大目标的性能。在每个阶段中引入大Kernel卷积可以帮助解决这个问题。然而,具有大的ERF的大Kernel可以编码更广泛的区域,这增加了在小目标外部包含噪声信息的概率,并且降低了推理速度。

在这项工作中,作者建议在不同阶段中采用异构卷积,以帮助捕获更丰富的多尺度特征。具体来说,在编码器的第一个阶段中,作者采用最小Kernel卷积,而最大Kernel卷积位于最后一个阶段。随后,作者逐步增加中间阶段的Kernel-Size,使其与特征分辨率的增加保持一致。这种策略允许提取细粒度和粗粒度的语义信息,增强了编码器的多尺度特征表示能力。

正如图所示,作者将k的值分别分配给编码器中的浅阶段到深阶段,取值为3、5、7和9。作者将其称为异构Kernel选择(HKS)协议。

在这里插入图片描述

作者的HKS协议能够在深层中扩大感受野,而不会对浅层产生任何其他影响。此外,HKS不仅有助于编码更丰富的多尺度特征,还确保了高效的推理。

如表1所示,将大Kernel卷积应用于高分辨率特征会产生较高的计算开销。然而,作者的HKS协议在低分辨率特征上采用大Kernel卷积,从而与仅使用大Kernel卷积相比,大大降低了计算成本。

在这里插入图片描述

在实践中,作者经验性地发现,采用HKS协议的YOLO-MS的推理速度几乎与仅使用深度可分离的3 × 3卷积相同。

Architecture

如图所示,作者模型的Backbone由4个阶段组成,每个阶段后面跟随1个步长为2的3 × 3卷积进行下采样。在第3个阶段后,作者添加了1个SPP块,与RTMDet中一样。在作者的编码器上,作者使用PAFPN作为Neck来构建特征金字塔[31, 35]。它融合了从Backbone不同阶段提取的多尺度特征。Neck中使用的基本构建块也是作者的MS-Block,在其中使用3 × 3深度可分离卷积进行快速推理。

此外,为了在速度和准确性之间取得更好的平衡,作者将Backbone中多级特征的通道深度减半。作者提供了3个不同尺度的YOLO-MS变体,即YOLO-MS-XS、YOLO-MS-S和YOLO-MS。不同尺度的YOLO-MS的详细配置列在表2中。对于YOLO-MS的其他部分,作者将其保持与RTMDet相同。

在这里插入图片描述

9.系统整合

下图完整源码&数据集&环境部署视频教程&自定义UI界面

在这里插入图片描述

参考博客《车辆违规开启远光灯检测系统:融合YOLO-MS改进YOLOv8》

10.参考文献


[1]张富凯,杨峰,李策.基于改进YOLOv3的快速车辆检测方法[J].计算机工程与应用.2019,(2).DOI:10.3778/j.issn.1002-8331.1810-0333 .

[2]徐义鎏,贺鹏.改进损失函数的Yolov3车型检测算法[J].信息通信.2019,(12).4-7.

[3]戴伟聪,金龙旭,李国宁,等.遥感图像中飞机的改进YOLOv3实时检测算法[J].光电工程.2018,(12).DOI:10.12086/oee.2018.180350 .

[4]官阳.从技术角度看十大"最反感交通陋习"[J].汽车与安全.2014,(7).56-63.

[5]Ross Girshick.Fast R-CNN[C].

[6]Girshick, R.,Donahue, J.,Darrell, T.,等.Rich Feature Hierarchies for Accurate Object Detection and Semantic Segmentation[C].

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/221699.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV技术应用(8)— 如何将视频分解

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。本节课就手把手教大家如何将一幅图像转化成热力图&#xff0c;希望大家学习之后能够有所收获~&#xff01;&#x1f308; 目录 &#x1f680;1.技术介绍 &#x1f680;2.实现代码 &#x1f680;1.技术介绍 视频是…

Open5GSUeRANSim2:对安装在同一个VM上的OPEN5GS和UERANSIM进行配置和抓取wireshark报文

参考链接&#xff1a; Configuring SCTP & NGAP with UERANSIM and Open5GS on a Single VM for the Open5GS & UERANSIM Series https://www.youtube.com/watch?vINgEX5L5fkE&listPLZqpS76PykwIoqMdUt6noAor7eJw83bbp&index5 Configuring RRC with UERANSI…

Python | Flask测试:发送post请求的接口测试

HTTP/1.1 协议规定的 HTTP 请求方法有OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 几种。POST通常用来向服务端提交数据&#xff0c;主要用于提交表单、上传文件。 HTTP 协议是以ASCII码传输&#xff0c;建立在 TCP/IP 协议之上的应用层规范。规范把 HTTP 请求分为…

微信小程序管理奖品(抽奖)

话不多说直接上代码 功能&#xff1a; 使用微信小程序vant-weapp 组件库中的upload组件以及两个input框 最后拿到的值是一个数组对象的形式 主要代码如下&#xff1a; wxml <view wx:for"{{prizes}}" wx:key"index" class"inputs"><i…

IDEA 黑色主题很难看到鼠标

“控制面板”—搜索“鼠标”关键字—选择“更改鼠标设置” 参考&#xff1a; IDEA 黑色主题很难看到鼠标

【实战】如何在Docker Image中轻松运行MySQL

定义 使用Docker运行MySQL有许多优势。它允许数据库程序和数据分离&#xff0c;增强了数据的安全性和可靠性。Docker Image的轻便性简化了MySQL的部署和迁移&#xff0c;而Docker的资源隔离功能确保了应用程序之间无冲突。结合中间件和容器化系统&#xff0c;Docker为MySQL提供…

Android Canvas状态save与restore,Kotlin

Android Canvas状态save与restore&#xff0c;Kotlin private fun f1() {val bitmap BitmapFactory.decodeResource(resources, R.mipmap.pic).copy(Bitmap.Config.ARGB_8888, true)val canvas Canvas(bitmap)val paint Paint(Paint.ANTI_ALIAS_FLAG)paint.color Color.RED…

常用的电源芯片有哪些?怎么分类

科技的发展也带动了电源的发展&#xff0c;因此需要更多的电源管理芯片。说到电源管理芯片&#xff0c;作为工程师最熟悉的芯片之一。所谓电源管理芯片&#xff0c;就是负责电子设备系统中电能的转换、分配、检测等电能管理的芯片。主要负责识别CPU电源范围&#xff0c;产生相应…

盘古大模型AI生态加速营圆满结营,携手创业者繁荣AI创新生态

“ 共创、共享、共赢 ” 12月15日&#xff0c;华为云加速器——盘古大模型AI生态加速营&#xff08;以下简称“加速营”&#xff09;圆满结营&#xff0c;并举办了面向创投圈层的结营开放日活动。在场的500多位华为云加速器校友、创业者、投资人和媒体朋友&#xff0c;共同…

【RTOS学习】源码分析(信号量和互斥量 事件组 任务通知)

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《RTOS学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 目录 &#x1f353;信号量和互斥量&#x1f345;创建&#x1f345;Take&#x1f345;Give &#x…

听GPT 讲Rust源代码--src/tools(16)

File: rust/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs rust-analyzer是一个基于Rust语言的IntelliSense引擎&#xff0c;用于提供IDE自动补全、代码导航和其他代码编辑功能。在rust-analyzer的源代码中&#xff0c;rust/src/tools/rust-analyzer…

算法基础之约数之和

约数之和 核心思想&#xff1a; #include<iostream>#include<algorithm>#include<vector>#include<unordered_map>using namespace std;typedef long long LL;const int N 110 , mod 1e97;int main(){int n;cin>>n;unordered_map<int,int&…

本地文件内容搜索神器AnyTXT Searcher如何搭建与远程访问

文章目录 前言1. AnyTXT Searcher1.1 下载安装AnyTXT Searcher 2. 下载安装注册cpolar3. AnyTXT Searcher设置和操作3.1 AnyTXT结合cpolar—公网访问搜索神器3.2 公网访问测试 4. 固定连接公网地址 前言 你是否遇到过这种情况&#xff0c;异地办公或者不在公司&#xff0c;想找…

node.js mongoose schemaTypes

目录 官方文档 简介 SchemaType 示例 配置SchemaType规则 通用规则 特定schemaType规则 String Number Date Map monggose会根据shcemaType将文档值转换成指定的类型 官方文档 Mongoose v8.0.3: SchemaTypes 简介 SchemaTypes是在使用Mongoose时&#xff0c;用于…

IDEA中如何创建各种类型的java工程

如果你的工程下面的module没有互相依赖&#xff0c;就相当于是一个小的项目&#xff0c;idea版本不同&#xff0c;细节可能不同 1、普通的Java 工程 在工程上&#xff0c;右键- New - Module&#xff0c;如下&#xff1a; 指明Java工程的名称及使用的JDK版本&#xff1a; 创建…

简单几步完成SVN的安装

介绍以及特点 SVN&#xff1a;Subversion&#xff0c;即版本控制系统。 1.代码版本管理工具 2.查看所有的修改记录 3.恢复到任何历史版本和已经删除的文件 4.使用简单上手快&#xff0c;企业安全必备 下载安装 SVN的安装分为两部分&#xff0c;第一部分是服务端安装&…

开启创意之旅:免费、开源的噪波贴图(noise texture)生成网站——noisecreater.com详细介绍

在当今数字创意领域&#xff0c;噪波贴图&#xff08;Noise Texture&#xff09;是游戏渲染、游戏开发、美术设计以及影视制作等行业不可或缺的艺术素材之一。为了满足广大创作者的需求&#xff0c;noisecreater.com应运而生&#xff0c;成为一款免费、开源的噪波贴图生成工具。…

手机怎么设置每年公历或农历生日提醒?生日提醒设置小妙招

生日是一个人在一年中比较特殊的日子之一&#xff0c;人们通常希望能够在这一天得到亲朋好友的祝福和庆祝。然而&#xff0c;随着人们生活节奏的加快&#xff0c;很多人表示自己很容易忘记他人的生日&#xff0c;导致不能够及时送出祝福和礼物。如果经常忘记亲朋好友的生日&…

神经网络学习小记录76——Tensorflow2设置随机种子Seed来保证训练结果唯一

神经网络学习小记录76——Tensorflow2设置随机种子Seed来保证训练结果唯一 学习前言为什么每次训练结果不同什么是随机种子训练中设置随机种子 学习前言 好多同学每次训练结果不同&#xff0c;最大的指标可能会差到3-4%这样&#xff0c;这是因为随机种子没有设定导致的&#x…

SpringBoot访问外部接口的常见方式

文章目录 SpringBoot访问外部接口模拟服务接口RestTemplatepom.xmlRestTemplateConfigClientTestRestTemplateController.java结果 WebClientpom.xmlClientTestWebClientController.java结果 HttpClientpom.xmlClientTestHttpClientController.java结果 OkHttppom.xmlClientTes…