旋转框检测项目相关python库知识总结(mmrotate、ppyolo_r、yolov5_obb)

旋转框常用于检测带有角度信息的矩形框,即矩形框的宽和高不再与图像坐标轴平行。相较于水平矩形框,旋转矩形框一般包括更少的背景信息。旋转框检测常用于遥感等场景中,本博文简单的介绍了可应用于旋转框数据训练的开源库,数据结构、OBB关键知识(如何实现角度预测、标签预测),最后分享了两个基于mmrotate自定义的旋转框模型(yolox_obb)。

1、相关开源库

目前的旋转框开源库有yolo_obb(yolov5_obb、yolov7_obb、yolov7_obb等)、paddledetection(ppyoloe_r模型等)、mmrotate库(各类obb模型库)

1.1 mmrotate库

MMRotate 是一款基于 PyTorch 的旋转框检测的开源工具箱,是 OpenMMLab 项目的成员之一。主分支代码目前支持 PyTorch 1.6 以上的版本。
MMRotate 提供了三种主流的角度表示法以满足不同论文的配置,并将旋转框检测任务解耦成不同的模块组件,通过组合不同的模块组件,用户可以便捷地构建自定义的旋转框检测算法模型。

mmrotate库下各种模型检测精度如下所。mmrotate库提到其最强模型达到了 78.9(single-scale)/81.3(multi-scale)map50,但在其模型库和config目录下并未找到。
在这里插入图片描述

mmrotate库中大部分模型都是基于faster-rcnn所实现,很难脱离mmdeploy进行部署(主要是rotate roi网络所导致的)。基于其灵活的配置文件,我们可以将其与mmdetection、mmyolo结合起构建基于yolo系列的各种一阶段检测器。博主曾基于mmyolo与mmrotate实现了yolox_obb的训练与测试,但精度总差于yolov5_obb项目

1.2 paddledetection库

paddledetection库是百度公司基于paddle框架推出的目标检测库,其中包含了rotate分支可用于旋转框目标检测。paddledetection将其中的明星模型ppyoloe发表了多个领域的模型,并基于ppyoloe实现了ppyoloe_r模型专用于旋转框目标检测。
在这里插入图片描述

paddledetection中ppyoloe_r等模型精度。模型库中的模型默认使用单尺度训练单尺度测试。如果数据增广一栏标明MS,意味着使用多尺度训练和多尺度测试。如果数据增广一栏标明RR,意味着使用RandomRotate数据增广进行训练。

使用ppyoloe_r训练可以参考 https://hpg123.blog.csdn.net/article/details/128137127 , c++部署可以参考 https://blog.csdn.net/a486259/article/details/128151738

1.3 yolo_obb系列库

yolo_obb是指基于yolo系列改造的obb模型,具体有yolov5-v8, 4个版本的obb模型。目前广泛使用的是yolov5_obb项目(yolov7_obb项目未公布在dota数据集上的精度,开源的yolov8obb项目还在开源中,博主自行实现的yolov8_obb在map50上与yolov5_obb处于同一精度水平,而map5095则要高3-5个百分点)
在这里插入图片描述
yolov5_obb项目的使用可以参考 https://blog.csdn.net/a486259/article/details/129366477 , c++部署可以参考 https://blog.csdn.net/a486259/article/details/130238663

2、 相关数据集

2.1 数据集标注格式

在数据集中,每个对象都由一个定向边界框 (OBB) 进行注释,该边界框可以表示为 (x1, y1, x2, y2, x3, y3, x4, y4) 。(xi,yi)表示 OBB 的第 i 个顶点。除了 OBB 之外,每个实例还标有类别和难度,表示该实例是否难以被检测到 (1 困难,0 表示不困难)。图像的注释保存在具有相同文件名的文本文件中。 每行代表一个实例。以下是图像的注释示例:

x1, y1, x2, y2, x3, y3, x4, y4, category, difficult
x1, y1, x2, y2, x3, y3, x4, y4, category, difficult
...

更多信息参考:https://captain-whu.github.io/DOTA/dataset.html

paddledetection基于coco格式的数据进行训练,其提供了工具支持将dota格式的数据转换为coco格式,具体如下所示。
python configs/rotate/tools/prepare_data.py --input_dirs ${train_dir} --only_change_format --coco_json_file DOTA_train.json

'annotations': [{'id': 2083, 'category_id': 9, 'image_id': 9008,'bbox': [x, y, w, h], # 水平框标注'segmentation': [[x1, y1, x2, y2, x3, y3, x4, y4]], # 旋转框标注...}...
]

2.2 dota数据集介绍

DOTA是一个用于航空图像中目标检测的大规模数据集。它可用于开发和评估目标探测器 在航拍图像中。图像是从不同的传感器和平台收集的。每个图像的大小都在该范围内 从 800 × 800 到 20,000 × 20,000 像素,包含表现出各种比例、方向和形状的对象。 DOTA图像中的实例由航空图像解释专家通过任意(8 d.o.f.)四边形进行注释。 我们将继续更新 DOTA,以扩大规模和范围,以反映不断变化的现实世界条件。现在它有三个 版本:

  • DOTA-v1.0 包含 15 个常见类别、2,806 张图片和 188, 282 个实例。培训比例 DOTA-v1.0 中的 set、validation set 和 testing set 分别为 1/2、1/6 和 1/3。具体类别:飞机、轮船、储罐、棒球钻石、网球场、篮球场、 地面田径场、港口、桥梁、大型车辆、小型车辆、直升机、环形交叉路口、足球场和游泳池 ,英文类别:plane, ship, storage tank, baseball diamond, tennis court, basketball court, ground track field, harbor, bridge, large vehicle, small vehicle, helicopter, roundabout, soccer ball field and swimming pool

  • DOTA-v1.5 使用与 DOTA-v1.0 相同的图像,但实例非常小(小于 10 像素) 也被注释。此外,还增加了一个新类别,“container crane”。它总共包含 403,318 个实例。 图像数量和数据集拆分数量与 DOTA-v1.0 相同。此版本是为 DOAI 挑战赛发布的 2019年与IEEE CVPR 2019一起在航空图像中进行目标检测。具体类别:飞机、轮船、储罐、棒球钻石、网球场、篮球场、 地面田径场, 港口, 桥梁, 大型车辆, 小型车辆, 直升机, 环形交叉路口, 足球场, 游泳 泳池和集装箱起重机 ,英文类别:plane, ship, storage tank, baseball diamond, tennis court, basketball court, ground track field, harbor, bridge, large vehicle, small vehicle, helicopter, roundabout, soccer ball field, swimming pool and container crane

  • DOTA-v2.0 收集了更多谷歌地球、GF-2卫星和航空图像。DOTAv2.0中有18个常见类别、11268个图像和1793658个实例。与DOTA-V.5相比,它进一步增加了“机场”和“直升机停机坪”的新类别。DOTA的11268个图像分为训练、验证、测试开发和测试挑战集。为了避免过拟合的问题,训练和验证集的比例小于测试集。此外,我们有两个测试集,即测试开发和测试挑战。训练包含1830个图像和268627个实例。验证包含593个图像和81048个实例。我们发布了训练和验证集的图像和基本事实。测试开发包含2792个映像和353346个实例。我们公布了图像,但没有公布基本真相。测试挑战包含6053个图像和1090637个实例。。具体类别:飞机、轮船、储罐、棒球钻石、网球场、篮球场、 地面田径场, 港口, 桥梁, 大型车辆, 小型车辆, 直升机, 环形交叉路口, 足球场, 游泳 游泳池、集装箱起重机、机场和直升机停机坪 ,英文类别:plane, ship, storage tank, baseball diamond, tennis court, basketball court, ground track field, harbor, bridge, large vehicle, small vehicle, helicopter, roundabout, soccer ball field, swimming pool, container crane, airport and helipad.
    官网地址:https://captain-whu.github.io/DOTA/index.html
    在这里插入图片描述

原始的dota数据集都是高清大图,基于paddledetection提供的工具可以进行切图操作。具体可参考:https://gitee.com/paddlepaddle/PaddleDetection/tree/develop/configs/rotate ,其支持对有标注和无标注的数据进行多尺度切图

3、OBB的关键知识

3.1 基本概念

OBB是指旋转框目标,HBB是指水平框目标(也就是常规的预测方法)。同架构的OBB模型与HBB相比,OBB多了一个角度输出(通常采用分类方法)。在进行锚框分配时,OBB与HBB并无差别,不将角度考虑到空间维度,仅将其作为附加信息进行预测。而在设计loss时,则需要考虑角度的周期性和对wh空间的影响。 同时,在训练时obb回归的是旋转框的宽和高,hbb回归的是正框的宽高,而正框的宽高扩散更符合卷积模型的感受野扩散过程,故此同模型同数据集下,hbb通常比obb在map50上高1%左右。

在评价指标上有map_obb与map_hbb,map_hbb是原始的map,map_obb是指在计算iou时将使用旋转矩形(基于2个多边形的8个坐标点计算与正框的iou有差异,故计算obb通常需要使用自行编码c++,编译成python的obb插件)

3.2 角度的表示

根据角度范围不同可以划分为不同的表示方法。目前常用的有三种:oc、le90、le135。oc是指opencv表示法,计算矩形与x轴正方向的夹角,角度范围为0~90;le是指长边表示法,计算矩形长边与x轴正方向的夹角。在le90中角度范围为-90到90,在le135中为-45到135。更多细节可以参考:https://zhuanlan.zhihu.com/p/642532202

通常各模型在给出map精度时也会指出其是使用何种角度表示方法,如ppyoloe_r使用oc表示法。

3.3 角度的预测

通常来说在目标检测网络输出分支中加上角度分支即可实现将正框检测模型修改为旋转框模型。关于预测角度则需要确定预测的形式(分类或回归,ppyoloe_r使用分类的方法预测角度,角度值采用弧度制表示,范围为[0,1]。角度回归loss用的是df_loss.转换为角度方法为:angle * 180 / 3.141592653),通常是以分类的进行进行预测(将连续的角度离散为360或180个类别[差1~2度,肉眼基本上不会发现,同时对于iou计算影响很小])

CSL(Circular Smooth Label,ECCV2020) 与KLD(Kullback-Leibler Divergence,NeurIPS2021) 都为大佬yangxue所提出。

Circular Smooth Label
CSL以环形标签表示方法对角度进行编码(使用独热码训练难以收敛,故对标签进行平滑操作),具体下图b所示。

CSL与原始的标签平滑操作(label和为1)是不太一样的,CLS设计了4种窗口函数来进行标签平滑(分别是脉冲函数、矩形函数、三角函数、高斯函数),具体如下图所示。窗口函数还有个参数为窗口半径,窗口半径过小则会变成One-hot label形式,无法学到角度信息,过大则角度预测偏差会加大,论文中的最佳半径为6。

基于高斯窗口函数的方法效果最好,而基于脉冲窗口函数(One-hot label)的效果最差,几乎预测不出角度值。那些角度信息明显的类别(具有一定长宽比),角度分类应该是比较容易,相反则不太容易,比如遥感场景中的油桶。由于边的交换性问题的存在, 90-CSL-baesd方法总体不如180-CSL-baesd方法

更多知识可以参考:https://zhuanlan.zhihu.com/p/111493759
特别注意的是,csl的作者指出边的交换性(exchangeability of edges,EoE)问题,即预测的角度差90度时,模型预测的宽高与真实的宽高在矫正后是相反的,然而在训练是loss却是很小的。针对于EOE问题,我们可以进行2次训练,第一次使角度的loss权重较大,第二次再正常设置loss

yolo_obb系列默认都是使用csl的方法预测角度,mmrotate则可以指定角度预测方法

Kullback-Leibler Divergence
KLD参考GWD先将旋转矩形(x,y,w,h,theat)转换成一个二维的高速分布,具体如下图所示:

其同时对x,y,w,h,theat进行回归,避免了EOE问题。KLD loss中角度loss部分考虑了长宽比,当h/w变大时,角度loss权重系数变的更大,表明了对长方形物体loss的加强。

通过以下可以看出KLD方法基本上要比CSL方法在map50高4个百分点,在map上则要高7个百分点,可见KLD方法所预测出的框更加精准。

更多细节请参考:https://zhuanlan.zhihu.com/p/642532202

4、基于mmrotate自定义模型

基于mmyolo、mmdetection、mmrotate这三个库的组合,我们可以自定义各种旋转框模型。只需要rotate_head与backbone的输出相符合即可,此外我们也可以自定义rotate_head。

4.1 rotated_yolox.py

在models\detectors目录下创建rotated_yolox.py文件,文件内容如下

# Copyright (c) OpenMMLab. All rights reserved.
from ..builder import ROTATED_DETECTORS
from .single_stage import RotatedSingleStageDetector@ROTATED_DETECTORS.register_module()
class RotatedYolox(RotatedSingleStageDetector):"""Implementation of Rotated `RetinaNet.`____ https://arxiv.org/abs/1708.02002"""def __init__(self,backbone,neck,bbox_head,train_cfg=None,test_cfg=None,pretrained=None,init_cfg=None):super(RotatedYolox,self).__init__(backbone, neck, bbox_head, train_cfg, test_cfg,pretrained, init_cfg)

并在models\detectors目录下修改__init__.py文件,新增from .rotated_yolox import RotatedYolox,并在__all__数组内新增,'RotatedYolox'

from .base import RotatedBaseDetector
from .gliding_vertex import GlidingVertex
from .oriented_rcnn import OrientedRCNN
from .r3det import R3Det
from .redet import ReDet
from .roi_transformer import RoITransformer
from .rotate_faster_rcnn import RotatedFasterRCNN
from .rotated_fcos import RotatedFCOS
from .rotated_reppoints import RotatedRepPoints
from .rotated_retinanet import RotatedRetinaNet
from .s2anet import S2ANet
from .single_stage import RotatedSingleStageDetector
from .two_stage import RotatedTwoStageDetector
from .rotated_yolox import RotatedYolox__all__ = ['RotatedRetinaNet', 'RotatedFasterRCNN', 'OrientedRCNN', 'RoITransformer','GlidingVertex', 'ReDet', 'R3Det', 'S2ANet', 'RotatedRepPoints','RotatedBaseDetector', 'RotatedTwoStageDetector','RotatedSingleStageDetector', 'RotatedFCOS','RotatedYolox'
]

4.2 yolox_retina_head.py

新建在config目录下即可

_base_ = ['./_base_/datasets/hrsid.py', './_base_/default_runtime.py'
]evaluation = dict(interval=1, metric='mAP')
# optimizer
optimizer = dict(type='SGD', lr=0.001, momentum=0.9, weight_decay=0.0001)
#optimizer = dict(type='Adam', lr=0.0000)
optimizer_config = dict(grad_clip=dict(max_norm=2, norm_type=1))#,error_if_nonfinite=True
# learning policy
#https://github.com/open-mmlab/mmcv/blob/e417035f5d473b9f85d15ba01267d48d7f30e71e/mmcv/runner/hooks/lr_updater.py#L407
lr_config = dict(policy='CosineRestart',periods=[20,40,60],restart_weights=[0.8,0.5,0.2],min_lr=0.0001)
runner = dict(type='EpochBasedRunner', max_epochs=60)
checkpoint_config = dict(interval=1)fp16 = dict(loss_scale='dynamic')data_root = 'datadata//'
classes = ('cls1', 'cls2') 
#load_from="./checkpoints/rotated_retinanet_obb_r50_fpn_1x_dota_le135-e4131166.pth"angle_version = 'le90'# model settings
model = dict(type='RotatedYolox',backbone=dict(type='CSPDarknet', deepen_factor=1, widen_factor=1),neck=dict(type='YOLOXPAFPN',in_channels=[ 256, 512, 1024],out_channels=256,num_csp_blocks=1),bbox_head=dict(type='RotatedRetinaHead',num_classes=len(classes),in_channels=256,stacked_convs=4,feat_channels=256,assign_by_circumhbbox=None,anchor_generator=dict(type='RotatedAnchorGenerator',octave_base_scale=4,scales_per_octave=3,ratios=[1.0, 0.5, 2.0],strides=[8, 16, 32]),bbox_coder=dict(type='DeltaXYWHAOBBoxCoder',angle_range=angle_version,norm_factor=None,edge_swap=True,proj_xy=True,target_means=(.0, .0, .0, .0, .0),target_stds=(1.0, 1.0, 1.0, 1.0, 1.0)),loss_cls=dict(type='FocalLoss',use_sigmoid=True,gamma=2.0,alpha=0.25,loss_weight=1.0),loss_bbox=dict(type='L1Loss', loss_weight=1.0)),train_cfg=dict(assigner=dict(type='MaxIoUAssigner',pos_iou_thr=0.5,neg_iou_thr=0.4,min_pos_iou=0,ignore_iof_thr=-1,iou_calculator=dict(type='RBboxOverlaps2D')),allowed_border=-1,pos_weight=-1,debug=False),test_cfg=dict(nms_pre=2000,min_bbox_size=0,score_thr=0.05,nms=dict(iou_thr=0.1),max_per_img=2000))img_norm_cfg = dict(mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
img_scale=(800, 800)
train_pipeline = [dict(type='LoadImageFromFile'),dict(type='LoadAnnotations', with_bbox=True),dict(type='YOLOXHSVRandomAug'),dict(type='PolyRandomRotate',rotate_ratio=0.5,angles_range=180,auto_bound=False,#rect_classes=[9, 11],version=angle_version),dict(type='RResize', img_scale=(800, 800)),dict(type='RRandomFlip',flip_ratio=[0.25, 0.25, 0.25],direction=['horizontal', 'vertical', 'diagonal'],version=angle_version),dict(type='Normalize', **img_norm_cfg),dict(type='Pad', size_divisor=32),dict(type='DefaultFormatBundle'),dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])
]
data = dict(samples_per_gpu=8,workers_per_gpu=4,train=dict(pipeline=train_pipeline, version=angle_version),val=dict(version=angle_version),test=dict(version=angle_version))

4.3 yolox_fcos_head.py

新建在config目录下即可

_base_ = ['./_base_/datasets/dotav2.py', './_base_/default_runtime.py'
]
classes = ('plane', 'ship', 'storage-tank', 'baseball-diamond', 'tennis-court', 'basketball-court', 'ground-track-field', 'harbor', 'bridge', 'large-vehicle', 'small-vehicle', 'helicopter', 'roundabout', 'soccer-ball-field', 'swimming-pool', 'container-crane', 'airport', 'helipad')evaluation = dict(interval=1, metric='mAP')
# optimizer
#optimizer = dict(type='SGD', lr=0.005, momentum=0.9, weight_decay=0.0001)
optimizer = dict(type='Adam', lr=0.0005)
optimizer_config = dict(grad_clip=dict(max_norm=35, norm_type=2))
# learning policy
#https://github.com/open-mmlab/mmcv/blob/e417035f5d473b9f85d15ba01267d48d7f30e71e/mmcv/runner/hooks/lr_updater.py#L407
lr_config = dict(policy='CosineRestart',periods=[20,40,60],restart_weights=[0.8,0.5,0.2],min_lr=0.0001)
runner = dict(type='EpochBasedRunner', max_epochs=60)
checkpoint_config = dict(interval=1)data_root = 'datadata//'
classes = ('cls1', 'cls2') 
#load_from="./checkpoints/rotated_fcos_kld_r50_fpn_1x_dota_le90-ecafdb2b.pth"angle_version = 'le90'# model settings
model = dict(type='RotatedYolox',backbone=dict(type='CSPDarknet', deepen_factor=0.33, widen_factor=0.5),neck=dict(type='YOLOXPAFPN',in_channels=[128, 256, 512],out_channels=128,num_csp_blocks=1),bbox_head=dict(type='RotatedFCOSHead',num_classes=len(classes),in_channels=128,stacked_convs=4,feat_channels=256,regress_ranges=((-1, 64), (64, 128), (128, 256)),strides=[8, 16, 32],center_sampling=True,center_sample_radius=1.5,norm_on_bbox=True,centerness_on_reg=True,separate_angle=False,scale_angle=True,bbox_coder=dict(type='DistanceAnglePointCoder', angle_version=angle_version),loss_cls=dict(type='FocalLoss',use_sigmoid=True,gamma=2.0,alpha=0.25,loss_weight=1.0),
#        loss_bbox=dict(
#            type='GDLoss_v1',
#            loss_type='kld',
#            fun='log1p',
#            tau=1,
#            loss_weight=1.0),loss_bbox=dict(type='SmoothL1Loss', beta=0.11, loss_weight=1.0),loss_centerness=dict(type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0)),# training and testing settingstrain_cfg=None,test_cfg=dict(nms_pre=2000,min_bbox_size=0,score_thr=0.05,nms=dict(iou_thr=0.1),max_per_img=2000))img_norm_cfg = dict(mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
img_scale=(800, 800)
train_pipeline = [dict(type='LoadImageFromFile'),dict(type='LoadAnnotations', with_bbox=True),dict(type='Mosaic',img_scale=img_scale,use_cached=True,max_cached_images=40,pad_val=114.0),dict(type='YOLOXHSVRandomAug'),dict(type='YOLOXMixUp',img_scale=img_scale,use_cached=True,ratio_range=(1.0, 1.0),max_cached_images=20,pad_val=(114, 114, 114)),dict(type='PolyRandomRotate',rotate_ratio=0.5,angles_range=180,auto_bound=False,rect_classes=[9, 11],version=angle_version),dict(type='RResize', img_scale=(800, 800)),dict(type='RRandomFlip',flip_ratio=[0.25, 0.25, 0.25],direction=['horizontal', 'vertical', 'diagonal'],version=angle_version),dict(type='Normalize', **img_norm_cfg),dict(type='Pad', size_divisor=32),dict(type='DefaultFormatBundle'),dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])
]train_pipeline = [dict(type='Mosaic', img_scale=img_scale, pad_val=114.0),dict(type='RandomAffine',scaling_ratio_range=(0.1, 2),border=(-img_scale[0] // 2, -img_scale[1] // 2)),dict(type='MixUp',img_scale=img_scale,ratio_range=(0.8, 1.6),pad_val=114.0),dict(type='YOLOXHSVRandomAug'),dict(type='RandomFlip', flip_ratio=0.5),# According to the official implementation, multi-scale# training is not considered here but in the# 'mmdet/models/detectors/yolox.py'.dict(type='Resize', img_scale=img_scale, keep_ratio=True),dict(type='Pad',pad_to_square=True,# If the image is three-channel, the pad value needs# to be set separately for each channel.pad_val=dict(img=(114.0, 114.0, 114.0))),dict(type='FilterAnnotations', min_gt_bbox_wh=(1, 1), keep_empty=False),dict(type='DefaultFormatBundle'),dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])
]train_dataset = dict(type='MultiImageMixDataset',dataset=dict(type="SARDataset",ann_file=data_root + 'annotations/instances_train2017.json',img_prefix=data_root + 'train2017/',pipeline=[dict(type='LoadImageFromFile'),dict(type='LoadAnnotations', with_bbox=True)],filter_empty_gt=False,),pipeline=train_pipeline)
data = dict(samples_per_gpu=32,workers_per_gpu=4,train=dict(pipeline=train_pipeline, version=angle_version),val=dict(version=angle_version),test=dict(version=angle_version))

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

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

相关文章

SpringCloud 微服务全栈体系(十八)

第十一章 分布式搜索引擎 elasticsearch 八、RestClient 查询文档 文档的查询同样适用 RestHighLevelClient 对象,基本步骤包括: 准备 Request 对象准备请求参数发起请求解析响应 1. 快速入门 以 match_all 查询为例 1.1 发起查询请求 代码解读&…

数字技术-IPC专利分类号对应表

数字技术-IPC专利分类号对应表,基于2023年的关键数字技术专利分类体系,通过国际专利分类(IPC)号进行筛选。这些数据涵盖了各种数字技术领域的创新,包括但不限于人工智能、大数据、云计算、物联网、5G通信等。利用关键词…

538. 把二叉搜索树转换为累加树

538. 把二叉搜索树转换为累加树 题目: 给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。 提醒…

浅谈联网汽车安全漏洞

“智能网联汽车存在内生共性问题,即软硬件的漏洞后门,基于此进行的网络攻击可以直接带来勒索、盗窃、大规模车辆恶意操控风险,还有数据泄露等网络安全事件。如果内生的漏洞后门问题不解决,系统自身难保,很难谈系统安全…

QTextEdit多行富文本框控件

​锋哥原创的PyQt6视频教程: 2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~共计21条视频,包括:2024版 PyQt6 Python桌面开发 视频教程(无废话…

推荐你一个基于Koin, Ktor Paging等组件的KMM Compose Multiplatform项目

推荐你一个基于Koin, Ktor & Paging等组件的KMM Compose Multiplatform项目 Kotlin Multiplatform Mobile(KMM)已经从一个雄心勃勃的想法发展成为一个稳定而强大的框架,为开发人员提供了在多个平台上无缝共享代码的能力。通过最近的稳定…

跨境电商系统开发:开启全球贸易新纪元

随着全球电子商务的飞速发展,跨境电子商务已经成为了一种日益重要的贸易形式。跨境电商系统开发,为企业提供了全新的商业机遇,打开了全球贸易的新纪元。 跨境电商系统开发,旨在实现不同国家和地区之间的电子商务交易,促…

【机器学习】迁移学习

迁移学习:给定一个有标记的源域和一个无标记的目标域。这两个领域的数据分布不同。迁移学习的目的就是要借助源域的知识,来学习目标域的知识(标签)。或是指基于源域数据和目标域数据、源任务和目标任务之间的相似性,利用在源领域中学习到的知…

计算机毕业设计|基于SpringBoot+MyBatis框架的电脑商城的设计与实现(商品和购物车)

计算机毕业设计|基于SpringBootMyBatis框架的电脑商城的设计与实现(商品和购物车) 商品热销排行 1 商品-创建数据表 1.使用use命令先选中store数据库。 USE store;2.在store数据库中创建t_product数据表。 CREATE TABLE t_product (id int(20) NOT …

Git开发实用技巧

文章目录 一图胜千言:

SCI一区级 | Matlab实现GWO-CNN-LSTM-selfAttention多变量多步时间序列预测

SCI一区级 | Matlab实现GWO-CNN-LSTM-selfAttention多变量多步时间序列预测 目录 SCI一区级 | Matlab实现GWO-CNN-LSTM-selfAttention多变量多步时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现GWO-CNN-LSTM-selfAttention灰狼算法优化卷积长短…

介绍比特币上的 sCrypt 开发平台

最强大的基础设施和工具套件,可轻松构建和扩展您的 dApp 杀手级应用在哪里? 尽管比特币在小额支付、国际汇款和供应链管理等广泛用例中具有颠覆性潜力,但在推出 14 年后,我们还没有看到一款非常受欢迎并被主流采用的杀手级应用。 …

echart一键生成迁徙图

echart_move 介绍 echart迁徙图,选择起点和目的地生成迁徙图 软件架构 html echarts js 使用说明 将文件放到同一目录下打开index.html即可 默认是小飞机图标,如果想修改图标,将图片放到同一目录,如1.svg 代码修改为对应位…

这一次,Python 真的有望告别 GIL 锁了?

Python 中有一把著名的锁——全局解释器锁(Global Interpreter Lock,简写 GIL),它的作用是防止多个本地线程同时执行 Python 字节码,这会导致 Python 无法实现真正的多线程执行。(注:本文中 Pyt…

DEM分析

一、实验名称: DEM分析 二、实验目的: 通过本实验练习,掌握DEM的建立与应用基本方法。 三、实验内容和要求: 实验内容: 利用ARCGIS软件相关分析工具及实验数据,创建DEM,并计算相应坡度的区…

webshell之编码免杀

Unicode编码 jsp支持unicode编码&#xff0c;如果杀软不支持unicode查杀的话&#xff0c;基本上都能绕过 注意这里的\uuuu00可以换成\uuuu00uuu...可以跟多个u达到绕过的效果 将代码&#xff08;除page以及标签&#xff09;进行unicode编码&#xff0c;并条件到<%%>标签…

sCrypt 在英国伦敦 Exeter 大学讲学

6月5日&#xff0c;sCrypt CEO晓晖和他的两位同事在英国伦敦Exeter大学举行了一场精彩的讲座。刘晓晖向听众们详细介绍了sCrypt智能合约开平台&#xff0c;并演示了如何使用sCrypt来开发基于比特币的智能合约。他用生动形象的语言&#xff0c;深入浅出地解释了这个领域复杂而又…

精通Nginx(18)-FastCGI/SCGI/uWSGI支持

最初用浏览器浏览的网页只能是静态html页面。随着社会发展,动态获取数据、操作数据需要变得日益强烈,CGI应运而生。CGI(Common Gateway Interface)公共网关接口,是外部扩展应用程序与静态Web服务器交互的一个标准接口。它可以使外部程序处理浏览器送来的表单数据并对此作出…

24. 深度学习进阶 - 矩阵运算的维度和激活函数

Hi&#xff0c;你好。我是茶桁。 咱们经过前一轮的学习&#xff0c;已经完成了一个小型的神经网络框架。但是这也只是个开始而已&#xff0c;在之后的课程中&#xff0c;针对深度学习我们需要进阶学习。 我们要学到超参数&#xff0c;优化器&#xff0c;卷积神经网络等等。看…

Node——npm包管理器的使用

Node.js使用npm对包进行管理&#xff0c;其全称为Node Package Manager&#xff0c;开发人员可以使用它安装、更新或者卸载Node.js的模块 1、npm包管理器基础 1.1、npm概述 npm是Node.js的标准软件包管理器&#xff0c;其在2020年3月17日被GitHub收购&#xff0c;而且保证永…