【3D目标检测】Det3d—SE-SSD模型训练(前篇):KITTI数据集训练

news2024/11/16 5:47:26

SE-SSD模型训练

  • 1 基于Det3d搭建SE-SSD环境
  • 2 自定义数据准备
    • 2.1 自定义数据集标注
    • 2.2 训练数据生成
    • 2.3 数据集分割
  • 3 训练KITTI数据集
    • 3.1 数据准备
    • 3.2 配置修改
    • 3.3 模型训练

1 基于Det3d搭建SE-SSD环境

Det3D环境搭建参考:【3D目标检测】环境搭建(OpenPCDet、MMdetection3d、Det3d)

SE-SSD源码链接:https://github.com/Vegeta2020/SE-SSD
首先激活Det3d环境(上述链接已经搭建好的环境):

conda activate det3d

新建3_det3d_projects文件夹(自定义名称),用于储存基于Det3D架构的模型源码项目,将SE-SSD源码存储在里面
目录结构如下:

SE-SSD环境部署指令

cd ~/3_det3d_projects
git clone https://github.com/Vegeta2020/SE-SSD.git
cd ./SE-SSD/det3d/core/iou3d
python setup.py install
cd ./SE-SSD
pip install ipykernel nbconvert numba==0.48 -i https://pypi.tuna.tsinghua.edu.cn/simple
python setup.py build develop

git clone https://github.com/jackd/ifp-sample.git
pip install -e ifp-sample

成功安装如下:
在这里插入图片描述
在这里插入图片描述
以下未说明均在SE-SSD目录下

2 自定义数据准备

2.1 自定义数据集标注

参考链接:【3D目标检测】OpenPCDet自定义数据集训练

2.2 训练数据生成

官方参考链接:https://github.com/V2AI/Det3D/blob/master/GETTING_STARTED.md
数据组织结果如下:

# For KITTI Dataset
└── SE-SSD/data/kitti
       ├── training    <-- 7481 train data
           ├── image_2 <-- for visualization
           ├── calib
           ├── label_2
           ├── velodyne
           └── velodyne_reduced <-- empty directory
       └── testing     <-- 7580 test data
           ├── image_2 <-- for visualization
           ├── calib
           ├── velodyne
           └── velodyne_reduced <-- empty directory
# KITTI
python tools/create_data.py kitti_data_prep --root_path=KITTI_DATASET_ROOT

2.3 数据集分割

"""
2024.03.21
author:alian
数据预处理操作
1.数据集分割
"""
import os
import random
import shutil
import numpy as np


def get_train_val_txt_kitti_det3d(src_path):
    """
    3D算法库:Det3D
    数据格式:KITTI
    # For KITTI Dataset
    └── KITTI_DATASET_ROOT
        ├── training    <-- 7481 train data
        |   ├── image_2 <-- for visualization
        |   ├── calib
        |   ├── label_2
        |   ├── velodyne
        |   └── velodyne_reduced <-- empty directory
        └── testing     <-- 7580 test data
            ├── image_2 <-- for visualization
            ├── calib
            ├── velodyne
            └── velodyne_reduced <-- empty directory
    	
        
    src_path: KITTI_DATASET_ROOT kitti文件夹

    """
    # 1.自动生成数据集划分文件夹ImageSets
    set_path = "%s/ImageSets/"%src_path
    if os.path.exists(set_path):  # 如果文件存在
        shutil.rmtree(set_path)  # 清空原始数据
        os.makedirs(set_path)  # 重新创建
    else:
        os.makedirs(set_path)  # 自动新建文件夹
    
    # 2.训练样本分割  生成train.txt val.txt trainval.txt
    train_list = os.listdir(os.path.join(src_path,'training','velodyne'))
    random.shuffle(train_list)  # 打乱顺序,随机采样
    # 设置训练和验证的比例
    train_p = 0.8

    # 开始写入分割文件
    f_train = open(os.path.join(set_path, "train.txt"), 'w')
    f_val = open(os.path.join(set_path, "val.txt"), 'w')
    f_trainval = open(os.path.join(set_path, "trainval.txt"), 'w')
    
    for i,src in enumerate(train_list):
        if i<int(len(train_list)*train_p): # 训练集的数量
            f_train.write(src[:-4] + '\n')
            f_trainval.write(src[:-4] + '\n')
        else:
            f_val.write(src[:-4] + '\n')
            f_trainval.write(src[:-4] + '\n')

    # 3.测试样本分割  生成test.txt
    test_list = os.listdir(os.path.join(src_path,'testing','velodyne'))
    f_test = open(os.path.join(set_path, "test.txt"), 'w')
    for i,src in enumerate(test_list):
        f_test.write(src[:-4] + '\n')


if __name__=='__main__':
    """
    	src_path: 数据目录
    """
    src_path = '/media/ll/L/llr/a2023_my_3d/Det3D/data/custom'
    get_train_val_txt_kitti_det3d(src_path)

输入:数据集路径
输出:在输入的数据集路径下生成

└── ImageSets
            ├── train.txt
            ├── val.txt
            ├── test.txt
            └── trainval.txt

3 训练KITTI数据集

先训练公开数据集,验证代码可行性

3.1 数据准备

tools/creat_data.py

import copy
from pathlib import Path
import pickle

import fire

from det3d.datasets.kitti import kitti_common as kitti_ds
from det3d.datasets.utils.create_gt_database import create_groundtruth_database
from det3d.torchie import Config


def kitti_data_prep(root_path):
    
    kitti_ds.create_kitti_info_file(root_path)

    kitti_ds.create_reduced_point_cloud(root_path)

    create_groundtruth_database("KITTI", root_path, Path(root_path) / "kitti_infos_train.pkl")


if __name__ == "__main__":
    # 数据集目录
    kitti_data_prep("/media/ll/L/llr/a2023_my_3d/3_det3d_projects/SE-SSD/data/kitti")

运行指令

Python tools/creat_data.py

在这里插入图片描述
其中kitti_infos_train.pkl的数据信息如下:
储存了所有数据的信息(以文件为单位)
在这里插入图片描述
包括:图像、点云、标定、标签信息
在这里插入图片描述
其中图像和点云信息如下:
在这里插入图片描述
其中标签信息如下:
在这里插入图片描述
标注信息解析:

  1. 第1列(字符串):代表物体类别(type)
    总共有9类,分别是:Car、Van、Truck、Pedestrian、Person_sitting、Cyclist、Tram、Misc、DontCare。
    其中DontCare标签表示该区域没有被标注,比如由于目标物体距离激光雷达太远。为了防止在评估过程中(主要是计算precision),将本来是目标物体但是因为某些原因而没有标注的区域统计为假阳性(false positives),评估脚本会自动忽略DontCare区域的预测结果。

  2. 第2列(浮点数):代表物体是否被截断(truncated)
    数值在0(非截断)到1(截断)之间浮动,数字表示指离开图像边界对象的程度。

  3. 第3列(整数):代表物体是否被遮挡(occluded)
    整数0、1、2、3分别表示被遮挡的程度。

  4. 第4列(弧度数):物体的观察角度(alpha)
    取值范围为:-pi ~ pi(单位:rad),它表示在相机坐标系下,以相机原点为中心,相机原点到物体中心的连线为半径,将物体绕相机y轴旋转至相机z轴,此时物体方向与相机x轴的夹角(如下图所示,y轴垂直与屏幕)

  5. 第5~8列(浮点数):物体的2D边界框大小(bbox)
    四个数分别是xmin、ymin、xmax、ymax(单位:pixel),表示2维边界框的左上角和右下角的坐标。

  6. 第9~11列(浮点数):3D物体的尺寸(dimensions)
    分别是高、宽、长(单位:米)

  7. 第12-14列(浮点数):3D物体的位置(location)
    分别是x、y、z(单位:米),特别注意的是,这里的xyz是在相机坐标系下3D物体的中心点位置。

  8. 第15列(弧度数):3D物体的空间方向(rotation_y)
    取值范围为:-pi ~pi(单位:rad),它表示,在照相机坐标系下,物体的全局方向角(物体前进方向与相机坐标系x轴的夹角),如下图所示。

  9. 第16列(浮点数):检测的置信度(score)
    在这里插入图片描述

其中dbinfos_train.pkl的数据信息如下:
根据类别来划分样本实例
在这里插入图片描述
在这里插入图片描述

重要说明:
当准备数据集时,./Det3d/det3d
当训练模型时,./Det3d/0det3d

原因解释:
数据准备时,使用Det3d的det3d
模型训练时则用回SE-SSD的det3d

└── 3_det3d_projects
       ├── SE-SSD
              ├── det3d
              └── ......
       └── ......
└── Det3D
       ├── 0det3d(数据集准备好后,改变名字,否则后续使用SE-SSD会找不到自己的det3d)
       └── ......

3.2 配置修改

修改examples/second/configs/config.py配置

主要修改三个部分

  1. 数据集目录
  2. 权重保存目录
  3. 预训练权重目录
import itertools
import logging
from pathlib import Path

from det3d.builder import build_box_coder
from det3d.utils.config_tool import get_downsample_factor
import glob

# norm_cfg = dict(type='SyncBN', eps=1e-3, momentum=0.01)
norm_cfg = None

tasks = [dict(num_class=1, class_names=["Car"],),]

class_names = list(itertools.chain(*[t["class_names"] for t in tasks]))

# training and testing settings
box_coder = dict(type="ground_box3d_coder", n_dim=7, linear_dim=False, encode_angle_vector=False,)

# exp_sesssd_release_v0_0: based on v1_0, remove sada
# exp_sesssd_release_v1_0: default settings of sesssd


# torch.set_printoptions(precision=4, sci_mode=False)
my_paras = dict(
    batch_size=4,
    data_mode="train",        # "train" or "trainval": the set to train the model;
    enable_ssl=True,         # Ensure "False" in CIA-SSD training
    eval_training_set=False,  # True: eval on "data_mode" set; False: eval on validation set.[Ensure "False" in training; Switch in Testing]

    # unused
    enable_difficulty_level=False,
    remove_difficulty_points=False,  # act with neccessary condition: enable_difficulty_level=True.
    gt_random_drop=-1,
    data_aug_random_drop=-1,
    far_points_first=False,
    data_aug_with_context=-1,        # enlarged size for w and l in data aug.
    gt_aug_with_context=-1,
    gt_aug_similar_type=False,
    min_points_in_gt=-1,
    loss_iou=None,
)

# model settings
model = dict(
    type="VoxelNet",
    pretrained=None,
    reader=dict(type="VoxelFeatureExtractorV3", num_input_features=4, norm_cfg=norm_cfg,),
    backbone=dict(type="SpMiddleFHD", num_input_features=4, ds_factor=8, norm_cfg=norm_cfg,),
    neck=dict(
        type="SSFA",
        layer_nums=[5,],
        ds_layer_strides=[1,],
        ds_num_filters=[128,],
        us_layer_strides=[1,],
        us_num_filters=[128,],
        num_input_features=128,
        norm_cfg=norm_cfg,
        logger=logging.getLogger("RPN"),
    ),
    bbox_head=dict(
        type="MultiGroupHead",
        mode="3d",
        in_channels=sum([128,]),
        norm_cfg=norm_cfg,
        tasks=tasks,
        weights=[1,],
        box_coder=build_box_coder(box_coder),
        encode_background_as_zeros=True,
        loss_norm=dict(type="NormByNumPositives", pos_cls_weight=1.0, neg_cls_weight=1.0,),
        loss_cls=dict(type="SigmoidFocalLoss", alpha=0.25, gamma=2.0, loss_weight=1.0,),
        use_sigmoid_score=True,
        loss_bbox=dict(type="WeightedSmoothL1Loss", sigma=3.0, code_weights=[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], codewise=True, loss_weight=2.0, ),
        encode_rad_error_by_sin=True,
        loss_aux=dict(type="WeightedSoftmaxClassificationLoss", name="direction_classifier", loss_weight=0.2,),
        direction_offset=0.0,
        #loss_iou=my_paras['loss_iou'],
    ),
)

target_assigner = dict(
    type="iou",
    anchor_generators=[
        dict(
            type="anchor_generator_range",
            sizes=[1.6, 3.9, 1.56],  # w, l, h
            anchor_ranges=[0, -40.0, -1.0, 70.4, 40.0, -1.0],
            rotations=[0, 1.57],
            matched_threshold=0.6,
            unmatched_threshold=0.45,
            class_name="Car",
        ),
    ],
    sample_positive_fraction=-1,
    sample_size=512,
    region_similarity_calculator=dict(type="nearest_iou_similarity",),
    pos_area_threshold=-1,
    tasks=tasks,
)

assigner = dict(
    box_coder=box_coder,
    target_assigner=target_assigner,
    out_size_factor=8,
    debug=False,
    enable_similar_type=True,
)


train_cfg = dict(assigner=assigner)

test_cfg = dict(
    nms=dict(
        use_rotate_nms=True,
        use_multi_class_nms=False,
        nms_pre_max_size=1000,
        nms_post_max_size=100,
        nms_iou_threshold=0.01,
    ),
    score_threshold=0.3,
    post_center_limit_range=[0, -40.0, -5.0, 70.4, 40.0, 5.0],
    max_per_img=100,
)

# dataset settings----------------------------------------------------------------------------------
data_root_prefix = "/media/ll/L/llr/a2023_my_3d/3_det3d_projects/SE-SSD/data/kitti"  # 数据集目录
dataset_type = "KittiDataset"

db_sampler = dict(
    type="GT-AUG",
    enable=True,
    db_info_path=glob.glob('%s/dbinfos_train.pkl'%data_root_prefix)[0],
    sample_groups=[dict(Car=15,),],
    db_prep_steps=[
        dict(filter_by_min_num_points=dict(Car=5,)),
        dict(filter_by_difficulty=[-1],),    # todo: need to check carefully
    ],
    global_random_rotation_range_per_object=[0, 0],
    rate=1.0,
    gt_random_drop=my_paras['gt_random_drop'],
    gt_aug_with_context=my_paras['gt_aug_with_context'],
    gt_aug_similar_type=my_paras['gt_aug_similar_type'],
)
train_preprocessor = dict(
    mode="train",
    shuffle_points=True,
    gt_loc_noise=[1.0, 1.0, 0.5],
    gt_rot_noise=[-0.785, 0.785],
    global_rot_noise=[-0.785, 0.785],
    global_scale_noise=[0.95, 1.05],
    global_rot_per_obj_range=[0, 0],
    global_trans_noise=[0.0, 0.0, 0.0],
    remove_points_after_sample=True,
    gt_drop_percentage=0.0,
    gt_drop_max_keep_points=15,
    remove_environment=False,
    remove_unknown_examples=my_paras.get("remove_difficulty_points", False),
    db_sampler=db_sampler,
    class_names=class_names,   # 'Car'
    symmetry_intensity=False,
    enable_similar_type=True,
    min_points_in_gt=my_paras["min_points_in_gt"],
    data_aug_with_context=my_paras["data_aug_with_context"],
    data_aug_random_drop=my_paras["data_aug_random_drop"],
)

val_preprocessor = dict(
    mode="val",
    shuffle_points=False,
    remove_environment=False,
    remove_unknown_examples=False,
)

voxel_generator = dict(
    range=[0, -40.0, -3.0, 70.4, 40.0, 1.0],
    voxel_size=[0.05, 0.05, 0.1],
    max_points_in_voxel=5,
    max_voxel_num=20000,
    far_points_first=my_paras['far_points_first'],
)

train_pipeline = [
    dict(type="LoadPointCloudFromFile"),
    dict(type="LoadPointCloudAnnotations", with_bbox=True, enable_difficulty_level=my_paras.get("enable_difficulty_level", False)),
    dict(type="Preprocess", cfg=train_preprocessor),
    dict(type="Voxelization", cfg=voxel_generator),
    dict(type="AssignTarget", cfg=train_cfg["assigner"]),
    dict(type="Reformat"),
    # dict(type='PointCloudCollect', keys=['points', 'voxels', 'annotations', 'calib']),
]
test_pipeline = [
    dict(type="LoadPointCloudFromFile"),
    dict(type="LoadPointCloudAnnotations", with_bbox=True),
    dict(type="Preprocess", cfg=val_preprocessor),
    dict(type="Voxelization", cfg=voxel_generator),
    dict(type="AssignTarget", cfg=train_cfg["assigner"]),
    dict(type="Reformat"),
]
training_pipeline = test_pipeline if my_paras['eval_training_set'] else train_pipeline


data_root = data_root_prefix  #  数据集目录
train_anno = glob.glob('%s/*_infos_train.pkl'%data_root_prefix)[0]
val_anno = glob.glob('%s/*val.pkl'%data_root_prefix)[0]
test_anno = glob.glob('%s/*test.pkl'%data_root_prefix)[0]
trainval_anno = glob.glob('%s/*trainval.pkl'%data_root_prefix)[0]

data = dict(
    samples_per_gpu=my_paras['batch_size'],  # batch_size: 4
    workers_per_gpu=2,  # default: 2
    train=dict(
        type=dataset_type,
        root_path=data_root,
        info_path=train_anno,
        class_names=class_names,
        pipeline=training_pipeline,
    ),
    val=dict(
        type=dataset_type,
        root_path=data_root,
        info_path=val_anno,
        class_names=class_names,
        pipeline=test_pipeline,
    ),
    test=dict(
        type=dataset_type,
        root_path=data_root,
        info_path=test_anno,
        class_names=class_names,
        pipeline=test_pipeline,
    ),
    trainval=dict(
        type=dataset_type,
        root_path=data_root,
        info_path=trainval_anno,
        class_names=class_names,
        pipeline=test_pipeline,
    ),
    train_unlabel_val=dict(
        type=dataset_type,
        root_path=data_root,
        info_path=val_anno,
        class_names=class_names,
        pipeline=train_pipeline,
        labeled=False,
    ),
    train_unlabel_test=dict(
        type=dataset_type,
        root_path=data_root,
        info_path=test_anno,
        class_names=class_names,
        pipeline=train_pipeline,
        labeled=False,
    ),
)

# for cia optimizer
optimizer = dict(type="adam", amsgrad=0.0, wd=0.01, fixed_wd=True, moving_average=False,)
optimizer_config = dict(grad_clip=dict(max_norm=35, norm_type=2))
lr_config = dict(type="one_cycle", lr_max=0.003, moms=[0.95, 0.85], div_factor=10.0, pct_start=0.4,)  # learning policy in training hooks



checkpoint_config = dict(interval=1)
log_config = dict(interval=10,hooks=[dict(type="TextLoggerHook"),],) # dict(type='TensorboardLoggerHook')

# runtime settings-----------------------------------------------------------------------------------------
TAG = 'exp_se_ssd_v1_1'  #  权重文件保存目录
work_dir = "/media/ll/L/llr/a2023_my_3d/3_det3d_projects/SE-SSD/examples/second/" + TAG
total_epochs = 60
device_ids = range(8)
dist_params = dict(backend="nccl", init_method="env://")
log_level = "INFO"
# 预训练权重文件
load_from = "/media/ll/L/llr/a2023_my_3d/3_det3d_projects/SE-SSD/examples/second/pre_trained_model/cia-ssd-model.pth"
resume_from = None
workflow = [("train", 60), ("val", 1)] if my_paras['enable_ssl'] else [("train", 60), ("val", 1)]
save_file = False if TAG == "debug" or TAG == "exp_debug" or Path(work_dir, "Det3D").is_dir() else True

3.3 模型训练

下载预训练权重文件
SE-SSE预训练权重:https://drive.google.com/file/d/1M2nP_bGpOy0Eo90xWFoTIUkjhdw30Pjs/view?usp=sharing
CIA-SSD预训练权重:https://drive.google.com/file/d/1SElYNQCsr4gctqLxmB6Fc4t7Ed8SgBgs/view?usp=sharing

修改tools/train.py配置文件的路径
大概在29行

def parse_args():
    parser = argparse.ArgumentParser(description="Train a detector")
    #  修改这里!!!!!
    parser.add_argument("--config", default='/media/ll/L/llr/a2023_my_3d/3_det3d_projects/SE-SSD/examples/second/configs/config.py', help="train config file path")
    parser.add_argument("--work_dir", help="the dir to save logs and models")
    parser.add_argument("--resume_from", help="the checkpoint file to resume from")
    parser.add_argument("--validate", action="store_true", help="whether to evaluate the checkpoint during training",)
    parser.add_argument("--gpus", type=int, default=1, help="number of gpus to use " "(only applicable to non-distributed training)",)
    parser.add_argument("--seed", type=int, default=None, help="random seed")
    parser.add_argument("--launcher",choices=["none", "pytorch", "slurm", "mpi"],default="none",help="job launcher",)
    parser.add_argument("--local_rank", type=int, default=0)
    parser.add_argument("--autoscale-lr",action="store_true",help="automatically scale lr with the number of gpus",)
    parser.add_argument("--save_file", type=bool, default=True, help="whether save code files as backup", )
    args = parser.parse_args()
    if "LOCAL_RANK" not in os.environ:
        os.environ["LOCAL_RANK"] = str(args.local_rank)

    return args

训练指令:

python tools/train.py

在这里插入图片描述
在这里插入图片描述
以上就实现了SE-SSD在KITTI数据上的训练!

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

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

相关文章

【Entity Framework】Code First 数据批注

【Entity Framework】Code First 数据批注 文章目录 【Entity Framework】Code First 数据批注一、概述二、模型二、键Key三、组合键四、外键-ForeigKey第一种&#xff1a;指定导航属性&#xff0c;会自动生成外键&#xff0c;命名规则为&#xff1a;“对象名称_主键名“第二种…

YOLOv9改进策略:注意力机制 | 二阶通道注意力机制(Second-order Channel Attention,SOCA),实现单图超分效果

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文改进内容&#xff1a;CVPR_2019 SOCA注意力&#xff0c;一种基于二阶通道注意力机制&#xff0c;能够单幅图像超分辨率&#xff0c;从原理角度分析能够在小目标检测领域实现大幅涨点效果&#xff01;&#xff01;&#xff01; &am…

文件编辑命令—vim

1.vim vim 是vi的升级版本.vi 文件名(vi方向键用不了) vim 的官方网站 (welcome home : vim online) 自己也说 vim 是一个程序开发工具而不是文字处理软件。 2.安装vim sudo apt install vim 如果出错了:apt update:刷新软件源; 出现"无法获得锁 之类的"sudo rm 文件…

Vit Transformer

一 VitTransformer 介绍 vit : An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale 论文是基于Attention Is All You Need&#xff0c;由于图像数据和词数据数据格式不一样&#xff0c;经典的transformer不能处理图像数据&#xff0c;在视觉领域的应…

【jenkins+cmake+svn管理c++项目】Windows环境安装以及工具配置

一、目标和环境 目标&#xff1a;搭建一个jenkins环境&#xff0c;实现jenkins调用cmake和svn和VS编译c项目&#xff0c;并将生成的库上传svn。 环境&#xff1a;win10虚拟机&#xff08;练习流程用&#xff0c;正式用的话还是放到服务器&#xff09;&#xff0c;VS2017. 二、…

肿瘤靶向肽 iRGD peptide环肽 1392278-76-0 c(CRGDKGPDC)

RGD环肽 c(CRGDKGPDC)&#xff0c;iRGD peptide 1392278-76-0 结 构 式&#xff1a; H2N-CRGDKGPDC-OH(Disulfide Bridge:C1-C9) H2N-Cys-Arg-Gly-Asp-Lys-Gly-Pro-Asp-Cys-COOH(Disulfide Bridge:Cys1-Cys9) 氨基酸个数&#xff1a; 9 C35H57N13O14S2 平均分子量:…

智能优化算法 | Matlab实现牛顿-拉夫逊优化算法Newton-Raphson-based optimize(内含完整源码)

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 智能优化算法 | Matlab实现牛顿-拉夫逊优化算法Newton-Raphson-based optimize(内含完整源码) 源码设计 % ------------------------------------------------------------------------------------------------…

GIS与Python机器学习:开创地质灾害风险评价新纪元

地质灾害是指全球地壳自然地质演化过程中&#xff0c;由于地球内动力、外动力或者人为地质动力作用下导致的自然地质和人类的自然灾害突发事件。由于降水、地震等自然作用下&#xff0c;地质灾害在世界范围内频繁发生。我国除滑坡灾害外&#xff0c;还包括崩塌、泥石流、地面沉…

55、Qt/事件机制相关学习20240326

一、代码实现设置闹钟&#xff0c;到时间后语音提醒用户。示意图如下&#xff1a; 代码&#xff1a; #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget), speecher(new QTextToSpeech(t…

【Redis】Redis 介绍Redis 为什么这么快?Redis数据结构Redis 和Memcache区别 ?为何Redis单线程效率也高?

目录 Redis 介绍 Redis 为什么这么快&#xff1f; Redis数据结构 Redis 和Memcache区别 &#xff1f; 为何Redis单线程效率也高&#xff1f; Redis 介绍 Redis 是一个开源&#xff08;BSD 许可&#xff09;、基于内存、支持多种数据结构的存储系统&#xff0c;可以作为数据…

【Linux】从零开始认识进程 — 中下篇

送给大家一句话&#xff1a; 人一切的痛苦&#xff0c;本质上都是对自己无能的愤怒。而自律&#xff0c;恰恰是解决人生痛苦的根本途径。—— 王小波 从零认识进程 1 进程优先级1.1 什么是优先级1.2 为什么要有优先级1.3 Linux优先级的特点 && 查看方式1.4 其他概念 2…

1.6.1 变换

我们要想改变物体的位置&#xff0c;现有解决办法是&#xff0c;每一帧改变物体的顶点并且重配置缓冲区从而使物体移动&#xff0c;但是这样太繁琐&#xff0c;更好的解决方式是使用矩阵&#xff08;Matrix&#xff09;来更好的变换&#xff08;Transform&#xff09;一个物体。…

Python更改Word文档的页面大小

页面大小确定文档中每个页面的尺寸和布局。在某些情况下&#xff0c;您可能需要自定义页面大小以满足特定要求。在这种情况下&#xff0c;Python可以帮助您。通过利用Python&#xff0c;您可以自动化更改Word文档中页面大小的过程&#xff0c;节省时间和精力。本文将介绍如何使…

每日一题 --- 删除链表的倒数第 N 个结点[力扣][Go]

删除链表的倒数第 N 个结点 题目&#xff1a;19. 删除链表的倒数第 N 个结点 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#x…

Python中lambda函数使用方法

在Python中&#xff0c;lambda 关键字用于创建匿名函数&#xff08;无名函数&#xff09;&#xff0c;这些函数的特点是简洁、一次性使用&#xff0c;并且通常用于只需要一行表达式的简单场景。下面是lambda函数的基本结构和使用方法&#xff1a; 基本语法&#xff1a; lambd…

代码随想录算法训练营DAY7| C++哈希表Part.2|LeetCode:454.四数相加II、383.赎金信、15. 三数之和、18.四数之和

文章目录 454.四数相加II思路C代码 383.赎金信C 代码 15. 三数之和排序哈希法思路C代码 排序双指针法思路去重C代码 18.四数之和前言剪枝C代码 454.四数相加II 力扣题目链接 文章链接&#xff1a;454.四数相加II 视频链接&#xff1a;学透哈希表&#xff0c;map使用有技巧&…

STL的基本概念

一、STL的诞生 长久以来&#xff0c;软件界一直希望建立一种可重复利用的东西 C的面向对象和泛型编程思想&#xff0c;目的就是复用性的提升 面向对象的三大特性(简单理解) 封装&#xff1a;把属性和行为抽象出来作为一个整体来实现事和物 继承&#xff1a;子类继承父类&a…

linux下docker容器的使用

1、根据已有镜像images创建容器 1.1、查看镜像 如果是接手的别人的项目&#xff0c;需要从以往的images镜像中创建新容器&#xff0c;使用命令查看当前机器上的docker镜像&#xff1a; docker images1.2、创建容器 使用docker run 根据images镜像名创建容器&#xff0c;命令…

电阻的妙用:限流、分压、滤波,助力电路设计!

电阻可以降低电压&#xff0c;这是通过电阻的分压来实现的。事实上&#xff0c;利用电阻来降低电压只是电阻的多种功能之一。电路中的电阻与其他元件&#xff08;电容、电感&#xff09;结合用于限流、滤波等。&#xff08;本文素材来源&#xff1a;https://www.icdhs.com/news…

SV-7045V网络草坪音箱 室外网络广播POE供电石头音箱

SV-7045V网络草坪音箱 室外网络广播POE供电石头音箱 描述 IP网络广播草坪音箱 SV-7045V是深圳锐科达电子有限公司的一款防水网络草坪音箱&#xff0c;具有10/100M以太网接口&#xff0c;可将网络音源通过自带的功放和喇叭输出播放&#xff0c;可达到功率20W。用在公园&#…