【精选】改进的YOLOv5:红外遥感图像微型目标的高效识别系统

1.研究背景与意义

随着科技的不断发展,红外遥感技术在军事、安防、环境监测等领域中得到了广泛应用。红外遥感图像具有独特的优势,可以在夜间或恶劣天气条件下获取目标信息,因此在小目标检测方面具有重要的应用价值。然而,由于红外图像的低对比度、噪声干扰等问题,小目标检测仍然是一个具有挑战性的问题。

目前,深度学习已经在计算机视觉领域取得了显著的成果,特别是目标检测领域。YOLO(You Only Look Once)是一种基于深度学习的实时目标检测算法,其通过将目标检测问题转化为回归问题,将目标的位置和类别同时预测出来。YOLO算法具有快速、准确的特点,因此在目标检测领域受到了广泛关注。

然而,传统的YOLO算法在红外遥感图像中小目标检测方面存在一些问题。首先,红外图像中的小目标往往具有低对比度,导致目标的边缘信息不明显,难以准确检测。其次,红外图像中存在大量的噪声干扰,这些噪声会干扰目标的检测和识别。此外,红外图像中的小目标往往具有多尺度和多方向的特点,传统的YOLO算法难以处理这种复杂情况。

因此,基于小目标检测头的改进YOLOv5红外遥感图像小目标检测系统具有重要的研究意义。通过引入小目标检测头,可以专门针对红外图像中的小目标进行优化,提高检测的准确性和鲁棒性。此外,改进的YOLOv5算法可以充分利用红外图像中的特征信息,提高小目标的检测效果。这对于提高红外遥感图像的目标检测能力,进一步推动红外遥感技术的发展具有重要的实际应用价值。

在实际应用中,基于小目标检测头的改进YOLOv5红外遥感图像小目标检测系统可以应用于军事侦察、边防巡逻、环境监测等领域。例如,在军事侦察中,可以利用该系统对红外图像中的敌方小目标进行实时监测和识别,提高作战的情报获取能力。在边防巡逻中,该系统可以帮助边防人员及时发现潜在的安全威胁。在环境监测中,该系统可以用于检测和监测自然灾害、森林火灾等情况,提供及时的预警和救援。

综上所述,基于小目标检测头的改进YOLOv5红外遥感图像小目标检测系统具有重要的研究意义和实际应用价值。通过优化目标检测算法,提高红外图像中小目标的检测准确性和鲁棒性,可以进一步推动红外遥感技术的发展,为军事、安防、环境监测等领域提供更加可靠和高效的解决方案。

2.图片演示

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

3.视频演示

基于小目标检测头的改进YOLOv5红外遥感图像小目标检测系统_哔哩哔哩_bilibili

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

图片的收集

首先,我们需要收集所需的图片。这可以通过不同的方式来实现,例如使用现有的红外遥感图像小目标数据集infrared_COCO_format。
在这里插入图片描述

使用labelImg进行标注

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

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

转换为YOLO格式

由于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目录下。
这样的结构使得数据的管理和模型的训练、验证和测试变得非常方便。

5.核心代码讲解

5.1 detect.py

class YOLOv5Detector:def __init__(self, weights='yolov5s.pt', source='data/images', imgsz=640, conf_thres=0.25, iou_thres=0.45,max_det=1000, device='', view_img=False, save_txt=False, save_conf=False, save_crop=False,nosave=False, classes=None, agnostic_nms=False, augment=False, visualize=False, update=False,project='runs/detect', name='exp', exist_ok=False, line_thickness=3, hide_labels=False,hide_conf=False, half=False):self.weights = weightsself.source = sourceself.imgsz = imgszself.conf_thres = conf_thresself.iou_thres = iou_thresself.max_det = max_detself.device = deviceself.view_img = view_imgself.save_txt = save_txtself.save_conf = save_confself.save_crop = save_cropself.nosave = nosaveself.classes = classesself.agnostic_nms = agnostic_nmsself.augment = augmentself.visualize = visualizeself.update = updateself.project = projectself.name = nameself.exist_ok = exist_okself.line_thickness = line_thicknessself.hide_labels = hide_labelsself.hide_conf = hide_confself.half = half@torch.no_grad()def run(self):save_img = not self.nosave and not self.source.endswith('.txt')  # save inference imageswebcam = self.source.isnumeric() or self.source.endswith('.txt') or self.source.lower().startswith(('rtsp://', 'rtmp://', 'http://', 'https://'))# Directoriessave_dir = increment_path(Path(self.project) / self.name, exist_ok=self.exist_ok)  # increment run(save_dir / 'labels' if self.save_txt else save_dir).mkdir(parents=True, exist_ok=True)  # make dir# Initializeset_logging()device = select_device(self.device)half = self.half & device.type != 'cpu'  # half precision only supported on CUDA# Load modelmodel = attempt_load(self.weights, map_location=device)  # load FP32 modelstride = int(model.stride.max())  # model strideimgsz = check_img_size(self.imgsz, s=stride)  # check image sizenames = model.module.names if hasattr(model, 'module') else model.names  # get class namesif half:model.half()  # to FP16# Second-stage classifierclassify = Falseif classify:modelc = load_classifier(name='resnet50', n=2)  # initializemodelc.load_state_dict(torch.load('resnet50.pt', map_location=device)['model']).to(device).eval()# Dataloaderif webcam:

这个程序文件是一个用于在图像、视频、目录和流上运行YOLOv5模型进行推理的脚本。它接受命令行参数来指定模型、输入源、推理尺寸等。

主要的函数是run(),它接受一系列参数来配置推理过程。在函数内部,它首先加载模型并设置一些参数,然后根据输入源的类型创建一个数据加载器。接下来,它循环遍历数据加载器中的每个图像或视频帧,并对其进行推理。推理结果包括检测到的物体的边界框和类别。最后,它可以选择将结果保存到文件或显示在屏幕上。

parse_opt()函数用于解析命令行参数,并返回一个包含这些参数的命名空间对象。

main()函数是脚本的入口点,它调用parse_opt()函数解析命令行参数,并调用run()函数进行推理。

整个程序文件的目的是提供一个方便的方式来运行YOLOv5模型进行目标检测。用户可以通过命令行参数来自定义推理过程的各个方面,例如模型、输入源、推理尺寸等。

5.2 export.py
class ModelExporter:def __init__(self, weights='./yolov5s.pt', img_size=(640, 640), batch_size=1, device='cpu',include=('torchscript', 'onnx', 'coreml'), half=False, inplace=False, train=False,optimize=False, dynamic=False, simplify=False, opset_version=12):self.weights = weightsself.img_size = img_sizeself.batch_size = batch_sizeself.device = deviceself.include = includeself.half = halfself.inplace = inplaceself.train = trainself.optimize = optimizeself.dynamic = dynamicself.simplify = simplifyself.opset_version = opset_versiondef export_torchscript(self, model, img, file, optimize):# TorchScript model exportprefix = colorstr('TorchScript:')try:print(f'\n{prefix} starting export with torch {torch.__version__}...')f = file.with_suffix('.torchscript.pt')ts = torch.jit.trace(model, img, strict=False)(optimize_for_mobile(ts) if optimize else ts).save(f)print(f'{prefix} export success, saved as {f} ({file_size(f):.1f} MB)')return tsexcept Exception as e:print(f'{prefix} export failure: {e}')def export_onnx(self, model, img, file, opset_version, train, dynamic, simplify):# ONNX model exportprefix = colorstr('ONNX:')try:check_requirements(('onnx', 'onnx-simplifier'))import onnxprint(f'\n{prefix} starting export with onnx {onnx.__version__}...')f = file.with_suffix('.onnx')torch.onnx.export(model, img, f, verbose=False, opset_version=opset_version,training=torch.onnx.TrainingMode.TRAINING if train else torch.onnx.TrainingMode.EVAL,do_constant_folding=not train,input_names=['images'],output_names=['output'],dynamic_axes={'images': {0: 'batch', 2: 'height', 3: 'width'},  # shape(1,3,640,640)'output': {0: 'batch', 1: 'anchors'}  # shape(1,25200,85)} if dynamic else None)# Checksmodel_onnx = onnx.load(f)  # load onnx modelonnx.checker.check_model(model_onnx)  # check onnx model# print(onnx.helper.printable_graph(model_onnx.graph))  # print# Simplifyif simplify:try:import onnxsimprint(f'{prefix} simplifying with onnx-simplifier {onnxsim.__version__}...')model_onnx, check = onnxsim.simplify(model_onnx,dynamic_input_shape=dynamic,input_shapes={'images': list(img.shape)} if dynamic else None)assert check, 'assert check failed'onnx.save(model_onnx, f)except Exception as e:print(f'{prefix} simplifier failure: {e}')print(f'{prefix} export success, saved as {f} ({file_size(f):.1f} MB)')except Exception as e:print(f'{prefix} export failure: {e}')def export_coreml(self, model, img, file):# CoreML model exportprefix = colorstr('CoreML:')try:import coremltools as ctprint(f'\n{prefix} starting export with coremltools {ct.__version__}...')f = file.with_suffix('.mlmodel')model.train()  # CoreML exports should be placed in model.train() modets = torch.jit.trace(model, img, strict=False)  # TorchScript modelmodel = ct.convert(ts, inputs=[ct.ImageType('image', shape=img.shape, scale=1 / 255.0, bias=[0, 0, 0])])model.save(f)print(f'{prefix} export success, saved as {f} ({file_size(f):.1f} MB)')except Exception as e:print(f'{prefix} export failure: {e}')def run(self):t = time.time()include = [x.lower() for x in self.include]img_size = self.img_size * 2 if len(self.img_size) == 1 else 1  # expandfile = Path(self.weights)# Load PyTorch modeldevice = select_device(self.device)assert not (device.type == 'cpu' and self.half), '--half only compatible with GPU export, i.e. use --device 0'model = attempt_load(self.weights, map_location=device)  # load FP32 modelnames = model.names# Inputgs = int(max(model.stride))  # grid size (max stride)img_size = [check_img_size(x, gs) for x in img_size]  # verify img_size are gs-multiplesimg = torch.zeros(self.batch_size, 3, *img_size).to(device)  # image size(1,3,320,192) iDetection# Update modelif self.half:img, model = img.half(), model.half()  # to FP16model.train() if self.train else model.eval()  # training mode = no Detect() layer grid constructionfor k, m in model.named_modules():if isinstance(m, Conv):  # assign export-friendly activationsif isinstance(m.act, nn.Hardswish):m.act = Hardswish()elif isinstance(m.act, nn.SiLU):m.act = SiLU()elif isinstance(m, Detect):m.inplace = self.inplacem.onnx_dynamic = self.dynamic# m.forward = m.forward_export  # assign forward (optional)for _ in range(2):y = model(img)  # dry runsprint(f"\n{colorstr('PyTorch:')} starting from {self.weights} ({file_size(self.weights):.1f} MB)")# Exportsif 'torchscript' in include:self.export_torchscript(model, img, file, self.optimize)if 'onnx' in include:self.export_onnx(model, img, file, self.opset_version, self.train, self.dynamic, self.simplify)if 'coreml' in include:self.export_coreml(model, img, file)# Finishprint(f'\nExport complete ({time.time() - t:.2f}s). Visualize with https://github.com/lutzroeder/netron.')

这个程序文件是用来将YOLOv5模型导出为TorchScript、ONNX和CoreML格式的。程序提供了命令行参数来指定模型权重路径、图像尺寸、批处理大小、设备类型等。程序的主要功能是加载PyTorch模型,然后根据用户指定的格式进行导出。导出的格式包括TorchScript、ONNX和CoreML。导出过程中还可以选择优化模型、使用半精度浮点数、设置YOLOv5的Detect()层为inplace模式、设置模型为训练模式等。导出完成后,程序会打印出导出的文件路径和大小,并提示可以使用Netron工具进行可视化。

5.3 hubconf.py

class YOLOv5:def __init__(self, name='yolov5s', pretrained=True, channels=3, classes=80, autoshape=True, verbose=True, device=None):self.name = nameself.pretrained = pretrainedself.channels = channelsself.classes = classesself.autoshape = autoshapeself.verbose = verboseself.device = deviceself.model = self._create()def _create(self):from pathlib import Pathfrom models.yolo import Model, attempt_loadfrom utils.general import check_requirements, set_loggingfrom utils.google_utils import attempt_downloadfrom utils.torch_utils import select_devicefile = Path(__file__).absolute()check_requirements(requirements=file.parent / 'requirements.txt', exclude=('tensorboard', 'thop', 'opencv-python'))set_logging(verbose=self.verbose)save_dir = Path('') if str(self.name).endswith('.pt') else file.parentpath = (save_dir / self.name).with_suffix('.pt')  # checkpoint pathtry:device = select_device(('0' if torch.cuda.is_available() else 'cpu') if self.device is None else self.device)if self.pretrained and self.channels == 3 and self.classes == 80:model = attempt_load(path, map_location=device)  # download/load FP32 modelelse:cfg = list((Path(__file__).parent / 'models').rglob(f'{self.name}.yaml'))[0]  # model.yaml pathmodel = Model(cfg, self.channels, self.classes)  # create modelif self.pretrained:ckpt = torch.load(attempt_download(path), map_location=device)  # loadmsd = model.state_dict()  # model state_dictcsd = ckpt['model'].float().state_dict()  # checkpoint state_dict as FP32csd = {k: v for k, v in csd.items() if msd[k].shape == v.shape}  # filtermodel.load_state_dict(csd, strict=False)  # loadif len(ckpt['model'].names) == self.classes:model.names = ckpt['model'].names  # set class names attributeif self.autoshape:model = model.autoshape()  # for file/URI/PIL/cv2/np inputs and NMSreturn model.to(device)except Exception as e:help_url = 'https://github.com/ultralytics/yolov5/issues/36's = 'Cache may be out of date, try `force_reload=True`. See %s for help.' % help_urlraise Exception(s) from edef inference(self, imgs):return self.model(imgs)if __name__ == '__main__':model = YOLOv5(name='yolov5s', pretrained=True, channels=3, classes=80, autoshape=True, verbose=True)imgs = ['data/images/zidane.jpg',  # filename'https://github.com/ultralytics/yolov5/releases/download/v1.0/zidane.jpg',  # URIcv2.imread('data/images/bus.jpg')[:, :, ::-1],  # OpenCVImage.open('data/images/bus.jpg'),  # PILnp.zeros((320, 640, 3))]  # numpyresults = model.inference(imgs)results.print()results.save()

这个程序文件是一个用于加载和使用YOLOv5模型的Python脚本。它定义了一个名为hubconf.py的模块,可以通过PyTorch Hub加载和使用YOLOv5模型。

该模块提供了以下功能:

  • _create函数:根据指定的模型名称创建一个YOLOv5模型。
  • custom函数:加载自定义或本地模型。
  • yolov5syolov5myolov5lyolov5xyolov5s6yolov5m6yolov5l6yolov5x6函数:加载预训练的YOLOv5模型,根据模型的大小和复杂度选择不同的函数。
  • __main__部分:在这里可以验证模型的推理功能,加载图像并进行批量推理。

总体而言,这个程序文件提供了一个方便的接口,可以轻松地加载和使用YOLOv5模型进行目标检测任务。

5.4 img2videos.py
class ImageToVideoConverter:def __init__(self, input_folder='./image', output_file='./output.mp4', frame_size=(960, 540), fps=30):self.input_folder = input_folderself.output_file = output_fileself.frame_size = frame_sizeself.fps = fpsdef convert(self):image_extensions = ["*.png", "*.PNG", "*.JPG", "*.JPEG", "*.jpg", "*.jpeg", "*.bmp"]image_files = []for ext in image_extensions:image_files.extend(glob.glob(os.path.join(self.input_folder, ext)))image_files.sort()fourcc = cv2.VideoWriter_fourcc(*'mp4v')out = cv2.VideoWriter(self.output_file, fourcc, self.fps, self.frame_size)for image_file in image_files:img = cv2.imread(image_file)img_resized = cv2.resize(img, self.frame_size)out.write(img_resized)out.release()cv2.destroyAllWindows()converter = ImageToVideoConverter(input_folder='./images', output_file='./output.mp4')
converter.convert()

这个程序文件名为img2videos.py,它的功能是将一个文件夹中的图片转换成视频。具体来说,它会读取指定文件夹中的所有图片文件,并按照文件名的顺序将这些图片合成为一个视频文件。用户可以通过指定输入文件夹路径、输出文件路径、帧大小和帧率等参数来自定义转换过程。程序使用了OpenCV库来处理图片和视频。

5.5 subdivision.py

封装为类后的代码如下:

class ImageProcessor:def __init__(self, model, img, augment, save_dir, path, visualize):self.model = modelself.img = imgself.augment = augmentself.save_dir = save_dirself.path = pathself.visualize = visualizedef process_image(self):mulpicplus = "3"  # 1 for normal,2 for 4pic plus,3 for 9pic plus and so onassert (int(mulpicplus) >= 1)if mulpicplus == "1":pred = self.model(self.img,augment=self.augment,visualize=increment_path(self.save_dir / Path(self.path).stem, mkdir=True) if self.visualize else False)[0]else:xsz = self.img.shape[2]ysz = self.img.shape[3]mulpicplus = int(mulpicplus)x_smalloccur = int(xsz / mulpicplus * 1.2)y_smalloccur = int(ysz / mulpicplus * 1.2)for i in range(mulpicplus):x_startpoint = int(i * (xsz / mulpicplus))for j in range(mulpicplus):y_startpoint = int(j * (ysz / mulpicplus))x_real = min(x_startpoint + x_smalloccur, xsz)y_real = min(y_startpoint + y_smalloccur, ysz)if (x_real - x_startpoint) % 64 != 0:x_real = x_real - (x_real - x_startpoint) % 64if (y_real - y_startpoint) % 64 != 0:y_real = y_real - (y_real - y_startpoint) % 64dicsrc = self.img[:, :, x_startpoint:x_real,y_startpoint:y_real]pred_temp = self.model(dicsrc,augment=self.augment,visualize=increment_path(self.save_dir / Path(self.path).stem, mkdir=True) if self.visualize else False)[0]pred_temp[..., 0] = pred_temp[..., 0] + y_startpointpred_temp[..., 1] = pred_temp[..., 1] + x_startpointif i == 0 and j == 0:pred = pred_tempelse:pred = torch.cat([pred, pred_temp], dim=1)# Apply NMSpred = non_max_suppression(pred, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)return pred

使用时,可以实例化该类,并调用process_image方法来处理图像。

这个程序文件名为subdivision.py,主要功能是对图像进行细分处理。程序中定义了一个变量mulpicplus,用于确定细分的方式。如果mulpicplus为1,则进行普通的细分处理;如果mulpicplus大于1,则进行更多的细分处理。

在普通细分处理中,程序调用了一个名为model的函数,对图像进行处理,并返回一个结果pred。

在更多细分处理中,程序根据mulpicplus的值,将图像分成多个小块,并分别进行处理。程序通过计算图像的尺寸和细分的数量,确定每个小块的起始点和结束点。然后,程序将每个小块传入model函数进行处理,并将处理结果拼接在一起。

最后,程序对处理结果进行非极大值抑制(NMS),通过设置一些阈值和参数,筛选出最有可能的目标物体,并返回最终的结果pred。

5.6 train.py
class YOLOv5Trainer:def __init__(self, hyp, opt, device):self.hyp = hypself.opt = optself.device = devicedef train(self):save_dir, epochs, batch_size, weights, single_cls, evolve, data, cfg, resume, noval, nosave, workers, = \self.opt.save_dir, self.opt.epochs, self.opt.batch_size, self.opt.weights, self.opt.single_cls, \self.opt.evolve, self.opt.data, self.opt.cfg, self.opt.resume, self.opt.noval, self.opt.nosave, \self.opt.workers# Directoriessave_dir = Path(save_dir)wdir = save_dir / 'weights'wdir.mkdir(parents=True, exist_ok=True)  # make dirlast = wdir / 'last.pt'best = wdir / 'best.pt'results_file = save_dir / 'results.txt'# Hyperparametersif isinstance(self.hyp, str):with open(self.hyp) as f:self.hyp = yaml.safe_load(f)  # load hyps dictLOGGER.info(colorstr('hyperparameters: ') + ', '.join(f'{k}={v}' for k, v in self.hyp.items()))# Save run settingswith open(save_dir / 'hyp.yaml', 'w') as f:yaml.safe_dump(self.hyp, f, sort_keys=False)with open(save_dir / 'opt.yaml', 'w') as f:yaml.safe_dump(vars(self.opt), f, sort_keys=False)# Configureplots = not evolve  # create plotscuda = self.device.type != 'cpu'init_seeds(1 + RANK)with open(data) as f:data_dict = yaml.safe_load(f)  # data dict# Loggersloggers = {'wandb': None, 'tb': None}  # loggers dictif RANK in [-1, 0]:# TensorBoardif not evolve:prefix = colorstr('tensorboard: ')LOGGER.info(f"{prefix}Start with 'tensorboard --logdir {self.opt.project}', view at http://localhost:6006/")loggers['tb'] = SummaryWriter(str(save_dir))# W&Bself.opt.hyp = self.hyp  # add hyperparametersrun_id = torch.load(weights).get('wandb_id') if weights.endswith('.pt') and os.path.isfile(weights) else Nonerun_id = run_id if self.opt.resume else None  # start fresh run if transfer learningwandb_logger = WandbLogger(self.opt, save_dir.stem, run_id, data_dict)loggers['wandb'] = wandb_logger.wandbif loggers['wandb']:data_dict = wandb_logger.data_dictweights, epochs, self.hyp = self.opt.weights, self.opt.epochs, self.opt.hyp  # may update weights, epochs if resumingnc = 1 if single_cls else int(data_dict['nc'])  # number of classesnames = ['item'] if single_cls and len(data_dict['names']) != 1 else data_dict['names']  # class namesassert len(names) == nc, '%g names found for nc=%g dataset in %s' % (len(names), nc, data)  # checkis_coco = data.endswith('coco.yaml') and nc == 80  # COCO dataset# Modelpretrained = weights.endswith('.pt')if pretrained:with torch_distributed_zero_first(RANK):weights = attempt_download(weights)  # download if not found locallyckpt = torch.load(weights, map_location=self.device)  # load checkpointmodel = Model(cfg or ckpt['model'].yaml, ch=3, nc=nc, anchors=self.hyp.get('anchors')).to(self.device)  # createexclude = ['anchor'] if (cfg or self.hyp.get('anchors')) and not resume else []  # exclude keysstate_dict = ckpt['model'].float().state_dict()  # to FP32state_dict = intersect_dicts(state_dict, model.state_dict(), exclude=exclude)  # intersectmodel.load_state_dict(state_dict, strict=False)  # loadLOGGER.info('Transferred %g/%g items from %s' % (len(state_dict), len(model.state_dict()), weights))  # reportelse:model = Model(cfg, ch=3, nc=nc, anchors=self.hyp.get('anchors')).to(self.device)  # createwith torch_distributed_zero_first(RANK):check_dataset(data_dict)  # checktrain_path = data_dict['train']val_path = data_dict['val']# Freezefreeze = []  # parameter names to freeze (full or partial)for k, v in model.named_parameters():v.requires_grad = True  # train all layersif any(x in k for x in freeze):print('freezing %s' % k)v.requires_grad = False# Optimizernbs = 64  # nominal batch sizeaccumulate = max(round(nbs / batch_size), 1)  # accumulate loss before optimizingself.hyp['weight_decay'] *= batch_size * accumulate / nbs  # scale weight_decayLOGGER.info(f"Scaled weight_decay = {self.hyp['weight_decay']}")pg0, pg1, pg2 = [], [], []  # optimizer parameter groupsfor k, v in model.named_modules():if hasattr(v, 'bias') and isinstance(v.bias, nn.Parameter):pg2.append(v.bias)  # biasesif isinstance(v, nn.BatchNorm2d):pg0.append(v.weight)  # no decayelif hasattr(v, 'weight') and isinstance(v.weight, nn.Parameter):pg1.append(v.weight)  # apply decayif self.opt.adam:optimizer = optim.Adam(pg0, lr=self.hyp['lr0'], betas=(self.hyp['momentum'], 0.999))  # adjust beta1 to momentumelse:optimizer = optim.SGD(pg0, lr=self.hyp['lr0'], momentum=self.hyp['momentum'], nesterov=True)optimizer.add_param_group({'params': pg1,

这个程序文件是用来训练一个YOLOv5模型的,使用的是自定义的数据集。程序文件的使用方法是通过命令行参数来指定数据集配置文件、模型权重文件和图像尺寸等参数。程序会根据指定的参数加载模型和数据集,并进行训练。训练过程中会保存模型权重和训练结果,并可以通过TensorBoard和W&B进行可视化和记录。训练过程中还会使用一些优化技巧,如学习率调整、权重衰减和EMA等。训练完成后,可以使用训练结果进行目标检测等任务。

6.系统整体结构

整体功能和构架概述:
该项目是一个基于YOLOv5的红外遥感图像小目标检测系统。它包含了多个程序文件,用于实现不同的功能,包括模型训练、推理、导出、数据处理等。主要的程序文件包括detect.py、export.py、hubconf.py、img2videos.py、subdivision.py、train.py等。

下表整理了每个文件的功能:

文件路径功能概述
detect.py运行YOLOv5模型进行推理的脚本
export.py将YOLOv5模型导出为TorchScript、ONNX和CoreML格式的脚本
hubconf.py加载和使用YOLOv5模型的Python模块
img2videos.py将图片文件夹转换为视频的脚本
subdivision.py对图像进行细分处理的脚本
train.py训练YOLOv5模型的脚本
ui.py用户界面脚本
val.py验证YOLOv5模型的脚本
yaml.py解析和处理YAML文件的脚本
models\common.pyYOLOv5模型的通用函数和类
models\experimental.pyYOLOv5模型的实验性函数和类
models\tf.pyYOLOv5模型的TensorFlow相关函数和类
models\yolo.pyYOLOv5模型的主要实现
models_init_.py模型初始化脚本
utils\activations.py激活函数的实现
utils\augmentations.py数据增强的实现
utils\autoanchor.py自动锚框生成的实现
utils\autobatch.py自动批处理的实现
utils\callbacks.py回调函数的实现
utils\datasets.py数据集加载和处理的实现
utils\downloads.py下载文件的实现
utils\general.py通用函数和类的实现
utils\google_utils.pyGoogle云存储相关函数的实现
utils\loss.py损失函数的实现
utils\metrics.py评估指标的实现
utils\plots.py绘图函数的实现
utils\torch_utils.pyPyTorch相关函数和类的实现
utils_init_.py工具函数初始化脚本
utils\aws\resume.pyAWS相关函数的实现
utils\aws_init_.pyAWS初始化脚本
utils\flask_rest_api\example_request.pyFlask REST API示例请求的实现
utils\flask_rest_api\restapi.pyFlask REST API的实现
utils\loggers_init_.py日志记录器初始化脚本
utils\loggers\wandb\log_dataset.py使用WandB记录数据集的实现
utils\loggers\wandb\sweep.py使用WandB进行超参数搜索的实现
utils\loggers\wandb\wandb_utils.py使用WandB进行日志记录的实现
utils\loggers\wandb_init_.pyWandB日志记录器初始化脚本
utils\wandb_logging\log_dataset.py使用WandB记录数据集的实现
utils\wandb_logging\sweep.py使用WandB进行超参数搜索的实现
utils\wandb_logging\wandb_utils.py使用WandB进行日志记录的实现
utils\wandb_logging_init_.pyWandB日志记录器初始化脚本

以上是对每个文件的功能进行了简要概述。每个文件都有不同的功能,用于实现整个基于小目标检测头的改进YOLOv5红外遥感图像小目标检测系统的各个方面。

7.数据集的标注和增强

数据集的标注

YOLOv5网络虽然使用pytorch作为网络的基础框架,但YOLO系列算法在建立之初并没有使用任何现有框架,而是独创了以纯C语言为基础的轻量级darknet框架,这也使YOLO系列算法的标签具有独立性,并没有使用被大家熟知的VOC或COCo格式标签。因此新建立的数据集,在标注目标框的时候,通常只能使用最常见的标注工具Labelimgl50来标注,得到VOC或者COCO格式的标签然后在通过python或其他语言编写的格式转换文件来转换成YOLO独特的标签,这也使众多YOLO爱好者感受到了建立标注框的困难。直到来自俄罗斯的AlexeyAB制作了一款基于c语言的YOLO专属标注软件YOLO_markl51l,才将获得YOLO格式标签的难度降低了一部分。然而深度学习算法的性能很大一部分取决于数据集的数量,所以即使YOLO_mark可以直接制作YOLO格式标签,但庞大的工作量依然让众多深度学习研究者苦不堪言。鉴于工作量的庞大,本次研究专门建立的红外弱小目标数据集并没有特别多的图像数据量,且目标类别也只留下了无人机一类。红外弱小目标数据集共有1530张图片,排除掉其中零零散散的无目标负样本图像,剩余有价值目标接近1500张,同时目标的尺寸非常弱小,因此此环节为整个实验过程中最为困难的一环。
YOLO_mark 的标注界面如图4.2所示,标注过程中只需用矩形框将目标物体框在框内即可,尽可能准确不留背景的锁住目标物体就可以得到一个有效的标签。至此,标签格式如图所示
在这里插入图片描述

数据增强

作为深度学习网络,大规模数据集的应用是网络成功实现的前提,而上文创立的数据集单从图像数量的角度来说,并不利于网络模型的训练。数据增广技术就是针对这一问题,通过对数据图像进行一系列随机的变化,来产出一些与原始数据集目标特征相似,背景信息相似,色域信息相似,可以被网络认定为同类型目标样本,但又不完全相同的训练样本来达到扩充数据集样本数量的目的。同时,经过数据增广填充后的数据集样本,还能起到减少网络模型对于目标样本其中某些特征或属性过度依赖的作用。
最早期的数据增广方式为简单的对原始训练样本进行翻转或裁剪[52],来得到一些新的训练样本。翻转的具体操作只需要将原始训练样本进行水平或者上下的翻转,虽然操作简单,训练样本的肉眼可识别特征也没有变化,但对于检测网络来说,目标所在的位置和背景信息的位置都发生了改变,所以可以得到新的训练样本数据,是一种简单有效的数据增广方式。而对于原始训练数据的裁剪,操作更复杂一些,需要从原始图像中随机裁取出一块面积为10%至100%的区域,然后再将其放大到原始图像的大小,得到新的数据图像。这种方式得到的数据增广样本,极可能将原始样本中的目标物体所在位置分离掉,从而使网络能够学习到目标物体的局部特征,降低对某些属性的过度依赖。虽然比起翻转方式复杂一些,但也属于一种简捷有效的数据增广方法。由于图像拥有对比度,饱和度,亮度和色调等参数,又产生了一个基于颜色的数据增广方式[3],只需要将上述参数随机调整为原参数的50%至150%,就可以又得到一组新的样本数据,这样产生的样本数据并没有改变目标物体的位置及类别信息,也是一种行之有效的方式。
上述的三种方法都是最为基础的数据增广方式,而当样本中含有多类别时,简单的处理方式,可能会在训练样本中加入过多的无效样本,反而使网络鲁棒性下降.由此又提出了cutmixl[S4]的数据增广方法。顾名思义,cutmix就是将图片先裁剪再融合,具体操作就是在某张特征图上随机生成一个裁剪区域,然后将另一张图片同一位置的裁剪部分补充到特征图的空白区域,最终得到的分类结果,按一定比例分配。cutmix 数据增广方式有如下几个优点:(1) cutmix数据增广方式没有补О操作,因而并不会存在无效的非像素信息出现在训练过程中,能够有效提高训练效率; (2) cutmix要求网络学习的重点集中到目标的局部信息,进一步增强网络的强定位能力。(3)合成的训练样本图像中的目标物体并不会出现不自然的情况,能够有效提高网络模型的分类能力。
但cutmix数据增广方式对于单类别的数据集并没有有效提升,因此本文使用的数据增广方式为cutmix 的增强版本,Mosaic数据增广。Mosaic数据增广[55]利用了来自原始训练样本中的四张图片,将四张图片进行拼接后,就会得到一张新的训练样本数据,同时还能获得这四张图片中的目标框位置信息。Mosaic数据增广后的图像如图所示:
在这里插入图片描述
由上图可知,Mosaic数据增广的具体操作是,首先从原始训练样本中随机抽取四张图片,然后对四张图片进行如旋转,翻转,裁剪,色域变换等随机基础方法,得到的四张图片按照左上,左下,右下,右上的顺序进行排放,排放后的四张图片按照矩阵的方式截取固定区域大小进行拼接,拼接后的图像有极为明显的边缘线,这些边缘线的取值可以随机选取或者人为设定,超出边缘的部分会被直接舍去掉,同时保留原始图像中的目标框信息,没有信息的部分会进行补О操作,将图片尺寸与原始样本尺寸对齐。
Mosaic数据增广方法在将数据集样本数量丰富的同时,也极大地提高了样本的多样性,降低了算法网络对于学习待测图像多样性的难度,是新颖又有效的数据增广方式。

模型训练
 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%|██████████| 213/213 [00:52<00:00,  4.04it/s]all       3395      17314      0.996      0.957      0.0957      0.0845

8.针对小目标检测的YOLOv5网络改进

增加小尺度检测头

增加了一个检测框,这个感觉意义不大,YOLO本身也有自适应框。
主要是参考上面网页中的方式,为小目标检测专门的增加了几个特征提取层:
在第17层后,继续对特征图进行上采样等处理,使得特征图继续扩大,同时在第20层时,将获取到的大小为160X160的特征图与骨干网络中第2层特征图进行concat融合,以此获取更大的特征图进行小目标检测。

# parameters
nc: 1  # number of classes
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple# anchors
anchors:- [5,6, 8,14, 15,11]  #4- [10,13, 16,30, 33,23]  # P3/8- [30,61, 62,45, 59,119]  # P4/16- [116,90, 156,198, 373,326]  # P5/32# YOLOv5 backbone
backbone:# [from, number, module, args][[-1, 1, Focus, [64, 3]],  # 0-P1/2[-1, 1, Conv, [128, 3, 2]],  # 1-P2/4[-1, 3, BottleneckCSP, [128]],   #160*160[-1, 1, Conv, [256, 3, 2]],  # 3-P3/8[-1, 9, BottleneckCSP, [256]],  #80*80[-1, 1, Conv, [512, 3, 2]],  # 5-P4/16[-1, 9, BottleneckCSP, [512]], #40*40[-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32[-1, 1, SPP, [1024, [5, 9, 13]]],[-1, 3, BottleneckCSP, [1024, False]],  # 9   20*20]# YOLOv5 head
head:[[-1, 1, Conv, [512, 1, 1]],  #20*20[-1, 1, nn.Upsample, [None, 2, 'nearest']], #40*40[[-1, 6], 1, Concat, [1]],  # cat backbone P4  40*40[-1, 3, BottleneckCSP, [512, False]],  # 13     40*40[-1, 1, Conv, [512, 1, 1]], #40*40[-1, 1, nn.Upsample, [None, 2, 'nearest']],[[-1, 4], 1, Concat, [1]],  # cat backbone P3   80*80[-1, 3, BottleneckCSP, [512, False]],  # 17 (P3/8-small)  80*80[-1, 1, Conv, [256, 1, 1]], #18  80*80[-1, 1, nn.Upsample, [None, 2, 'nearest']], #19  160*160[[-1, 2], 1, Concat, [1]], #20 cat backbone p2  160*160[-1, 3, BottleneckCSP, [256, False]], #21 160*160[-1, 1, Conv, [256, 3, 2]],  #22   80*80[[-1, 18], 1, Concat, [1]], #23 80*80[-1, 3, BottleneckCSP, [256, False]], #24 80*80[-1, 1, Conv, [256, 3, 2]], #25  40*40[[-1, 14], 1, Concat, [1]],  # 26  cat head P4  40*40[-1, 3, BottleneckCSP, [512, False]],  # 27 (P4/16-medium) 40*40[-1, 1, Conv, [512, 3, 2]],  #28  20*20[[-1, 10], 1, Concat, [1]],  #29 cat head P5  #20*20[-1, 3, BottleneckCSP, [1024, False]],  # 30 (P5/32-large)  20*20[[21, 24, 27, 30], 1, Detect, [nc, anchors]],  # Detect(p2, P3, P4, P5)]

深度学习算法中并不需要人工选择目标所在区域,因此为了解决如何自主寻找候选区域的问题,选择预设一组或多组不同尺度不同位置的锚点框,这样只需要留下与锚点框交并比大于预设阈值的预测框就可以得到目标信息,YOLOv5s的anchor 设置如图所示:
在这里插入图片描述

虽然YOLOv5s的准确率和召回率并不低,但由于YOLOv5s网络 anchors的设置具有泛用性,适用于大部分数据集的目标尺度,并没有完全将特征提取能力聚焦到小尺度上,所以接下来对网络的改进将针对anchors,使网络尽可能的锁定到实际目标所在的高层语义信息。在上文中提到,YOLOv5网络的检测头接在PANet后,因此需要在Head输出层PAN结构部分增加一层高分辨率网络,鉴于PANet的双塔结构,还需要在FPN层补充一次下采样过程,使网络模型能更准确细致的保留且学习到弱小目标的语义特征信息。增加高分辨率小尺度检测头后,网络的锚点信息如图所示:
在这里插入图片描述
针对红外弱小目标的小尺度检测头添加完成,训练参数与上一次实验的参数对齐,在Ubuntu18.04操作系统下进行,软件平台为Pycharm,训练与验证框架为Pytorch1.6.0。使用的CUDA版本为10.1,Python 版本为3.6,CPU为i9 9900k,GPU为两张NVIDIARTX 2080ti。Batchsize设为8,输入图像大小为1920*1080,初始学习率采用0.01训练100epoch,直至训练loss 如图时训练结束。

在这里插入图片描述

增加图像切割层

AAAI提出的思路就是在目标分辨率太大的情况下,将目标图像分解为数个图像送入YOLOV5网络中做检测,再回收所有图像,计算坐标的相对值,集体来一次NMS。
小目标检测效果不好主要原因为小目标尺寸问题。
以网络的输入608608为例,yolov5中下采样使用了5次,因此最后的特征图大小是1919,3838,7676。三个特征图中,最大的7676负责检测小目标,而对应到608608上,每格特征图的感受野是608/76=8*8大小。即如果原始图像中目标的宽或高小于8像素,网络很难学习到目标的特征信息。
另外很多图像分辨率很大,如果简单的进行下采样,下采样的倍数太大,容易丢失数据信息。但是倍数太小,网络前向传播需要在内存中保存大量的特征图,极大耗尽GPU资源,很容易发生显存爆炸,无法正常的训练及推理。
这种情况可以使用分割的方式,将大图先分割成小图,再对每个小图检测,可以看出中间区域很多的汽车都被检测出来:不过这样方式有优点也有缺点:优点:准确性分割后的小图,再输入目标检测网络中,对于最小目标像素的下限会大大降低。比如分割成608608大小,送入输入图像大小608608的网络中,按照上面的计算方式,原始图片上,长宽大于8个像素的小目标都可以学习到特征。
缺点:增加计算量比如原本19201080的图像,如果使用直接大图检测的方式,一次即可检测完。但采用分割的方式,切分成4张912608大小的图像,再进行N次检测,会大大增加检测时间。
在这里插入图片描述

9.系统整合

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

在这里插入图片描述

参考博客《基于小目标检测头的改进YOLOv5红外遥感图像小目标检测系统》

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

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

相关文章

专注短视频账号矩阵系统源头开发---saas工具

专注短视频账号矩阵系统源头开发---saas营销化工具&#xff0c;目前我们作为一家纯技术开发团队目前已经专注打磨开发这套系统企业版/线下版两个版本的saas营销拓客工具已经3年了&#xff0c;本套系统逻辑主要是从ai智能批量剪辑、账号矩阵全托管发布、私信触单收录、文案ai智能…

微服务实战系列之签名Sign

前言 昨日恰逢“小雪”节气&#xff0c;今日寒风如约而至。清晨的马路上&#xff0c;除了洋洋洒洒的落叶&#xff0c;就是熙熙攘攘的上班族。眼看着&#xff0c;暖冬愈明显了&#xff0c;叶子来不及泛黄就告别了树。变化总是在不经意中发生&#xff0c;容不得半刻糊涂。 上集博…

kubernetes 部署 spinnaker

spinnaker简介 Spinnaker 是一个开源、多云持续交付平台&#xff0c;它将强大而灵活的管道管理系统与主要云提供商的集成相结合。Spinnaker 提供应用程序管理和部署&#xff0c;帮助您快速、自信地发布软件变更。 Spinnaker 提供了两组核心的功能&#xff1a; 应用管理与应用程…

从根到叶:随机森林模型的深入探索

一、说明 在本综合指南中&#xff0c;我们将超越基础知识。当您盯着随机森林模型的文档时&#xff0c;您将不再对“节点杂质”、“加权分数”或“成本复杂性修剪”等术语感到不知所措。相反&#xff0c;我们将剖析每个参数&#xff0c;阐明其作用和影响。通过理论和 Python 实践…

Navicat 技术指引 | 适用于 GaussDB 的备份与还原功能

Navicat Premium&#xff08;16.2.8 Windows版或以上&#xff09; 已支持对 GaussDB 主备版的管理和开发功能。它不仅具备轻松、便捷的可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结构同步、协同合作、数据迁移等&#xff09;&#xff0c;这…

如何评估供应商协同平台的功能和性能

在制造业中&#xff0c;供应商协同平台是一种重要的工具&#xff0c;可以帮助企业与供应商建立更紧密的合作关系&#xff0c;提高采购效率&#xff0c;降低成本。而SRM系统是一种集成的供应链管理系统&#xff0c;可以协调和管理企业与供应商之间的业务关系&#xff0c;包括供应…

Sealos 云操作系统私有化部署教程

Sealos 私有云已经正式发布了&#xff0c;它为企业用云提供了一种革命性的新方案。Sealos 的核心优势在于&#xff0c;它允许企业在自己的机房中一键构建一个功能与 Sealos 公有云完全相同的私有云。这意味着企业可以在自己的控制和安全范围内&#xff0c;享受到公有云所提供的…

高通OTA升级方案介绍

高通OTA升级方案介绍 1. 高通LE OTA1.1 背景1.2 Recovery系统 2. SDX12 OTA方案3 OTA包的加密 3UK Penetration Test对于OTA升级也有严格的安全要求&#xff0c;下面是几条用例要求&#xff1a; Firmware: A sufficiently strong signing key MUST be in use. Signing keys MUS…

visionOS空间计算实战开发教程Day 6 拖拽和点击

在之前的学习中我们在空间中添加了3D模型&#xff0c;但在初始摆放后就无法再对其进行移动或做出修改。本节我们在​​Day 5​​显示和隐藏的基础上让我们模型可以实现拖拽效果&#xff0c;同时对纯色的立方体实现点击随机换色的功能。 首先是入口文件&#xff0c;无需做出改变…

Linux反弹SHell与检测思路

免责声明 文章仅做经验分享用途,利用本文章所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任,一旦造成后果请自行承担!!! 反弹shell payload在线生成 https://www.chinabaiker.com/Hack-Tools/ Online - Reverse Shell G…

Talk | UCSB博士生宋珍巧:基于人工智能的功能性蛋白质设计

本期为TechBeat人工智能社区第549期线上Talk。 北京时间11月22日(周三)20:00&#xff0c;UC Santa Barbara博士生—宋珍巧的Talk已准时在TechBeat人工智能社区开播&#xff01; 她与大家分享的主题是: “基于人工智能的功能性蛋白质设计”&#xff0c;介绍了如何利用机器学习算…

itext - PDF模板套打

项目需求&#xff1a;获取列表数据之后直接将数据生成一个pdf。因此需要使用到 itext 对pdf进行直接操作。 环境配置 需要为pdf添加文字域&#xff0c;因此需要安装Adobe Acrobat 准备一个空的PDF文件&#xff0c;如果有现成的模板更好 依赖配置&#xff0c;我们使用itext的7版…

python数据结构与算法-14_树与二叉树

树和二叉树 前面我们讲了两种使用分治和递归解决排序问题的归并排序和快速排序&#xff0c;堆排序先就此打住&#xff0c;因为涉及到树的概念&#xff0c;所以我们先来讲讲树。 讲完了树之后后面我们开始介绍一种有用的数据结构堆(heap)&#xff0c; 以及借助堆来实现的堆排序…

python命令行 引导用户填写ssh登录信息

字多不看&#xff0c;直接体验&#xff1a; 待补充 演示代码 # -*- coding:UTF-8 -*- """ author: dyy contact: douyaoyuan126.com time: 2023/11/23 9:20 file: 引导用户填写ssh接口信息.py desc: xxxxxx """# region 引入必要的依赖 impor…

【图像分类】基于深度学习的垃圾分类系统的设计与实现(ResNet网络,附代码和数据集)

写在前面: 首先感谢兄弟们的关注和订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。(专栏订阅用户订阅专栏后免费提供数据集和源码一份,超级VIP用户不在服务范围之内,不想订阅专栏的兄弟们可以私信…

el-table表格排序(需要后端判别),el-table导出功能(向后端发送请求)

&#xff08;1&#xff09;表格排序 &#xff08;2&#xff09;简单的table导出功能&#xff08;需要后台支撑&#xff09;必须要有iframe &#xff08;3&#xff09;页面所有代码&#xff1a; <template><div class"mainContainer"><el-form:model&…

使用Pytorch从零开始构建DCGAN

在本文中&#xff0c;我们将深入研究生成建模的世界&#xff0c;并使用流行的 PyTorch 框架探索 DCGAN&#xff08;生成对抗网络 (GAN) 的一种变体&#xff09;的实现。具体来说&#xff0c;我们将使用 CelebA 数据集&#xff08;名人面部图像的集合&#xff09;来生成逼真的合…

网络安全等级保护收费标准?

不同省份价格会略有不同&#xff0c;二级等保一般不低于5万元;三级等保不低于9万元&#xff0c;个别省份也可能7万也能办理&#xff0c;根据企业实际情况和省市选定的代理机构确定。 等级保护二级? 第二级等保是指信息系统受到破坏后&#xff0c;会对公民、法人和其他组织的合…

《YOLOv8创新改进》专栏指导书册 手把手创新教程

&#x1f680;&#x1f680;&#x1f680;YOLOv8改进专栏&#xff1a;http://t.csdnimg.cn/hGhVK 学姐带你学习YOLOv8&#xff0c;从入门到创新&#xff0c;轻轻松松搞定科研&#xff1b; 本专栏为订阅者提供答疑服务&#xff0c;每一篇提供源代码和详细的每一个步骤改进地方。…

Navicat 技术指引 | 适用于 GaussDB 的模型功能

Navicat Premium&#xff08;16.2.8 Windows版或以上&#xff09; 已支持对 GaussDB 主备版的管理和开发功能。它不仅具备轻松、便捷的可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结构同步、协同合作、数据迁移等&#xff09;&#xff0c;这…