新版mmdetection3d将3D bbox绘制到图像

环境信息

使用 python mmdet3d/utils/collect_env.py收集环境信息

sys.platform: linux
Python: 3.7.12 | packaged by conda-forge | (default, Oct 26 2021, 06:08:21) [GCC 9.4.0]
CUDA available: True
numpy_random_seed: 2147483648
GPU 0,1: NVIDIA GeForce RTX 3090
CUDA_HOME: /usr/local/cuda
NVCC: Cuda compilation tools, release 11.3, V11.3.109
GCC: gcc (Ubuntu 7.5.0-6ubuntu2) 7.5.0
PyTorch: 1.8.1+cu111
PyTorch compiling details: PyTorch built with:
  - GCC 7.3
  - C++ Version: 201402
  - Intel(R) Math Kernel Library Version 2020.0.0 Product Build 20191122 for Intel(R) 64 architecture applications
  - Intel(R) MKL-DNN v1.7.0 (Git Hash 7aed236906b1f7a05c0917e5257a1af05e9ff683)
  - OpenMP 201511 (a.k.a. OpenMP 4.5)
  - NNPACK is enabled
  - CPU capability usage: AVX2
  - CUDA Runtime 11.1
  - NVCC architecture flags: -gencode;arch=compute_37,code=sm_37;-gencode;arch=compute_50,code=sm_50;-gencode;arch=compute_60,code=sm_60;-gencode;arch=compute_70,code=sm_70;-gencode;arch=compute_75,code=sm_75;-gencode;arch=compute_80,code=sm_80;-gencode;arch=compute_86,code=sm_86
  - CuDNN 8.0.5
  - Magma 2.5.2
  - Build settings: BLAS_INFO=mkl, BUILD_TYPE=Release, CUDA_VERSION=11.1, CUDNN_VERSION=8.0.5, CXX_COMPILER=/opt/rh/devtoolset-7/root/usr/bin/c++, CXX_FLAGS= -Wno-deprecated -fvisibility-inlines-hidden -DUSE_PTHREADPOOL -fopenmp -DNDEBUG -DUSE_KINETO -DUSE_FBGEMM -DUSE_QNNPACK -DUSE_PYTORCH_QNNPACK -DUSE_XNNPACK -O2 -fPIC -Wno-narrowing -Wall -Wextra -Werror=return-type -Wno-missing-field-initializers -Wno-type-limits -Wno-array-bounds -Wno-unknown-pragmas -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function -Wno-unused-result -Wno-unused-local-typedefs -Wno-strict-overflow -Wno-strict-aliasing -Wno-error=deprecated-declarations -Wno-stringop-overflow -Wno-psabi -Wno-error=pedantic -Wno-error=redundant-decls -Wno-error=old-style-cast -fdiagnostics-color=always -faligned-new -Wno-unused-but-set-variable -Wno-maybe-uninitialized -fno-math-errno -fno-trapping-math -Werror=format -Wno-stringop-overflow, LAPACK_INFO=mkl, PERF_WITH_AVX=1, PERF_WITH_AVX2=1, PERF_WITH_AVX512=1, TORCH_VERSION=1.8.1, USE_CUDA=ON, USE_CUDNN=ON, USE_EXCEPTION_PTR=1, USE_GFLAGS=OFF, USE_GLOG=OFF, USE_MKL=ON, USE_MKLDNN=ON, USE_MPI=OFF, USE_NCCL=ON, USE_NNPACK=ON, USE_OPENMP=ON, 

TorchVision: 0.9.1+cu111
OpenCV: 4.6.0
MMEngine: 0.9.1
MMDetection: 3.2.0
MMDetection3D: 1.3.0+9d3e162
spconv2.0: True

以前写过mmdetection3d中的可视化,但mmdetection3d更新后代码已经不适用了,正好我把我的工作全转移到新版mmdetection3d上来了,因此重新写了一下推理结果可视化。整体思路还是构建模型、构建数据、推理、绘制,下面分步讲解

1、构建模型

我用jupyter实现,首先需要确保jupyter的工作路径在mmdetection3d的工作路径下,不然会存在找不到mmdet3d的问题

import sys
import os
import torch
import cv2
import numpy as np

# 添加工作路径,不然找不到mmdet3d
os.chdir('/home/wistful/work/open_mmlab_mmdetection3d')
sys.path.append('/home/wistful/work/open_mmlab_mmdetection3d')


# load config
config_file = 'configs/point_cls_voxel/pointpillars_hv_secfpn_8x2-160e_kitti-3d-3class.py'
checkpoint_file = '/home/wistful/work/open_mmlab_mmdetection3d/work_dirs/pointpillars_hv_secfpn_8x2-160e_kitti-3d-3class/epoch_80.pth'

# 构建模型
from mmdet3d.apis import init_model, inference_detector
device = 'cuda:0'
model = init_model(config_file, checkpoint=checkpoint_file, device=device)

至此模型已经构建,下一步是构建数据,送入模型以获取推理结果

2、构建数据

新版mmdet3d的模型输入分为两个部分batch_inputs_dict, batch_data_samplesbatch_inputs_dict包含了模型推理所需的数据(点云、图像),batch_data_samples包含了训练时需要的bbox等信息。因此,需要构建batch_inputs_dict,我写了一个简单的函数,可以调用

build_dataloader.py文件:

from mmdet3d.registry import DATASETS
from tools.misc.browse_dataset import build_data_cfg
from mmengine.registry import init_default_scope


def load_datasets(config_file, aug=False, set='train'):
    """
    Args:
        config_file: 配置文件路径
        aug:是否数据增强(待测试)
        set:要读取的数据集,'train','test','val'

    Returns:
    """
    cfg = build_data_cfg(config_file, aug=aug, cfg_options=None)
    init_default_scope(cfg.get('default_scope', 'mmdet3d'))
    # 选择需要读取的数据集
    if set == 'train':
        dataloader = cfg.train_dataloader.dataset
    elif set == 'val':
        dataloader = cfg.val_dataloader.dataset
    elif set == 'test':
        dataloader = cfg.test_dataloader.dataset

    return DATASETS.build(dataloader)


def build_batch_dict(datasets, batch_size, device, images=False):
    """
    Args:
        device: 指定设备

        datasets: 传入数据集
        batch_size: 批次大小
        images: 加入图像

    Returns:

    """
    # TODO: 编写加入图像的代码
    points = []
    images = []
    batch_data_samples = []
    for i in range(batch_size):
        # 确保在同一个device上
        points.append(datasets[i]['inputs']['points'].to(device))

        data_samples = datasets[i]['data_samples']
        # if data_samples.gt_instances_3d
        if len(data_samples.gt_instances_3d.keys()) != 0:
            data_samples.gt_instances_3d.bboxes_3d = data_samples.gt_instances_3d.bboxes_3d.to(device)
            data_samples.gt_instances_3d.labels_3d = data_samples.gt_instances_3d.labels_3d.to(device)
    batch_inputs_dict = dict()
    batch_inputs_dict['points'] = points

    # batch_data_samples = data_samples
    return batch_inputs_dict, batch_data_samples


def cyclic_load_data_item(datasets, index, device, images=False):
    """
    Args:
        device: 指定设备
        datasets: 传入数据集
        index: 索引
        images: 加入图像

    Returns:
        单条数据,适用于循环遍历整个数据集
    """
    # TODO: 编写加入图像的代码
    points = []
    images = []
    points.append(datasets[index]['inputs']['points'].to(device))

    batch_inputs_dict = dict()
    batch_inputs_dict['points'] = points

    data_samples = datasets[index]['data_samples']
    if len(data_samples.gt_instances_3d.keys()) !=0:
        data_samples.gt_instances_3d.bboxes_3d = data_samples.gt_instances_3d.bboxes_3d.to(device)
        data_samples.gt_instances_3d.labels_3d = data_samples.gt_instances_3d.labels_3d.to(device)
    batch_data_samples = [data_samples]
    return batch_inputs_dict, batch_data_samples

下面利用这个函数,实现构建数据集

# 构建数据集
from custom_API.build_dataloader import load_datasets # 我放在了custom_API路径下,如何导入取决于读者如何存放
 
set = 'test'

# set字段表示构建的数据集
datasets = load_datasets(dataset_config, aug=False, set=set) # aug字段表示不使用数据增强

至此,datasets为一个列表,长度就是数据集的总样本数。eg:datasets[0]里面就包含了第1个样本的全部信息,下面可以看一下输出

在这里插入图片描述

3、推理与绘制

我们已经得到了整个数据集,那么我们就可以使用数据集中的任意一条数据进行推理,根据这个思路,我们也能很方便的推理完整个数据集。绘制部分的代码我使用的是旧版mmdetection3d中的代码,下面是代码:

# draw_box.py
import os

from custom_API.draw_utils import draw_lidar_bbox3d_on_img, draw_depth_bbox3d_on_img, draw_camera_bbox3d_on_img
import mmcv
from os import path as osp
import numpy as np

def show_multi_modality_result(img,
                               gt_bboxes,
                               pred_bboxes,
                               batch_data_samples,
                               out_dir,
                               filename,
                               type='train',
                               box_mode='lidar',
                               img_metas=None,
                               show=False,
                               gt_bbox_color=(61, 102, 255),
                               pred_bbox_color=(241, 101, 72)):
    """Convert multi-modality detection results into 2D results.
    将3D边框投影到2D图像平面并且可视化
    Project the predicted 3D bbox to 2D image plane and visualize them.

    Args:
        img (np.ndarray): The numpy array of image in cv2 fashion.
        gt_bboxes (:obj:`BaseInstance3DBoxes`): Ground truth boxes.
        pred_bboxes (:obj:`BaseInstance3DBoxes`): Predicted boxes.
        proj_mat (numpy.array, shape=[4, 4]): The projection matrix # 投影矩阵
            according to the camera intrinsic parameters.
        out_dir (str): Path of output directory.
        filename (str): Filename of the current frame.
        box_mode (str, optional): Coordinate system the boxes are in.
            Should be one of 'depth', 'lidar' and 'camera'.
            Defaults to 'lidar'.
        img_metas (dict, optional): Used in projecting depth bbox.
            Defaults to None.
        show (bool, optional): Visualize the results online. Defaults to False.
        颜色为B G R,不是RGB!!!
        gt_bbox_color (str or tuple(int), optional): Color of bbox lines.
           The tuple of color should be in BGR order. Default: (255, 102, 61).
        pred_bbox_color (str or tuple(int), optional): Color of bbox lines.
           The tuple of color should be in BGR order. Default: (72, 101, 241).
    """
    # 根据传入3D框所处的坐标系调用对应的投影方法,获取投影框
    if box_mode == 'depth':
        draw_bbox = draw_depth_bbox3d_on_img
    elif box_mode == 'lidar':
        draw_bbox = draw_lidar_bbox3d_on_img
    elif box_mode == 'camera':
        draw_bbox = draw_camera_bbox3d_on_img
    else:
        raise NotImplementedError(f'unsupported box mode {box_mode}')

    # 在out_dir下创建每个文件名字的文件夹
    # result_path = osp.join(out_dir, filename)
    # mmcv.mkdir_or_exist(result_path)
    out_dir = out_dir + type + '/'
    # 判断目录是否存在
    if not os.path.exists(out_dir):
        os.makedirs(out_dir)
    else:
        pass
        # os.makedirs(out_dir)
    # mmcv.mkdir_or_exist(result_path)

    # if score_thr > 0:
    #     inds = pred_scores > score_thr
    #     pred_bboxes = pred_bboxes[inds]
    # 获取投影矩阵
    proj_mat = batch_data_samples[0].lidar2img
    proj_mat = proj_mat[0]
    proj_mat = np.array(proj_mat)
    if show:
        show_img = img.copy()
        if gt_bboxes is not None:
            show_img = draw_bbox(
                gt_bboxes, show_img, proj_mat, img_metas, color=gt_bbox_color)
        if pred_bboxes is not None:
            show_img = draw_bbox(
                pred_bboxes,
                show_img,
                proj_mat,
                img_metas,
                color=pred_bbox_color)
        mmcv.imshow(show_img, win_name='project_bbox3d_img', wait_time=0)

    if img is not None:
        # print('写入原图像')
        mmcv.imwrite(img, osp.join(out_dir, f'{filename}.png'))

    if gt_bboxes is not None:
        # 写入地面真相
        gt_img = draw_bbox(
            gt_bboxes, img, proj_mat, img_metas, color=gt_bbox_color)
        mmcv.imwrite(gt_img, osp.join(out_dir, f'{filename}_gt.png'))

    if pred_bboxes is not None:
        pred_img = draw_bbox(
            pred_bboxes, img, proj_mat, img_metas, color=pred_bbox_color)
        mmcv.imwrite(pred_img, osp.join(out_dir, f'{filename}_pred.png'))

    if pred_bboxes is not None and gt_bboxes is not None:
        # print('draw_gt_bbox')
        gt_img = draw_bbox(
            gt_bboxes, img, proj_mat, img_metas, color=gt_bbox_color)
        gt_and_pred_img = draw_bbox(
            pred_bboxes, gt_img, proj_mat, img_metas, color=pred_bbox_color)
        mmcv.imwrite(gt_and_pred_img, osp.join(out_dir, f'{filename}_pred_gt.png'))

# draw_utils.py
# Copyright (c) OpenMMLab. All rights reserved.
import copy

import cv2
import numpy as np
import torch
from matplotlib import pyplot as plt


def project_pts_on_img(points,
                       raw_img,
                       lidar2img_rt,
                       max_distance=70,
                       thickness=-1):
    """Project the 3D points cloud on 2D image.

    Args:
        points (numpy.array): 3D points cloud (x, y, z) to visualize.
        raw_img (numpy.array): The numpy array of image.
        lidar2img_rt (numpy.array, shape=[4, 4]): The projection matrix
            according to the camera intrinsic parameters.
        max_distance (float, optional): the max distance of the points cloud.
            Default: 70.
        thickness (int, optional): The thickness of 2D points. Default: -1.
    """
    img = raw_img.copy()
    num_points = points.shape[0]
    pts_4d = np.concatenate([points[:, :3], np.ones((num_points, 1))], axis=-1)
    pts_2d = pts_4d @ lidar2img_rt.T

    # cam_points is Tensor of Nx4 whose last column is 1
    # transform camera coordinate to image coordinate
    pts_2d[:, 2] = np.clip(pts_2d[:, 2], a_min=1e-5, a_max=99999)
    pts_2d[:, 0] /= pts_2d[:, 2]
    pts_2d[:, 1] /= pts_2d[:, 2]

    fov_inds = ((pts_2d[:, 0] < img.shape[1])
                & (pts_2d[:, 0] >= 0)
                & (pts_2d[:, 1] < img.shape[0])
                & (pts_2d[:, 1] >= 0))

    imgfov_pts_2d = pts_2d[fov_inds, :3]  # u, v, d

    cmap = plt.cm.get_cmap('hsv', 256)
    cmap = np.array([cmap(i) for i in range(256)])[:, :3] * 255

    for i in range(imgfov_pts_2d.shape[0]):
        depth = imgfov_pts_2d[i, 2]
        color = cmap[np.clip(int(max_distance * 10 / depth), 0, 255), :]
        cv2.circle(
            img,
            center=(int(np.round(imgfov_pts_2d[i, 0])),
                    int(np.round(imgfov_pts_2d[i, 1]))),
            radius=1,
            color=tuple(color),
            thickness=thickness,
        )
    cv2.imshow('project_pts_img', img.astype(np.uint8))

    cv2.waitKey(0)


def plot_rect3d_on_img(img,
                       num_rects,
                       rect_corners,
                       color=(0, 255, 0),
                       thickness=1):
    """Plot the boundary lines of 3D rectangular on 2D images.

    Args:
        img (numpy.array): The numpy array of image.
        num_rects (int): Number of 3D rectangulars.
        rect_corners (numpy.array): Coordinates of the corners of 3D
            rectangulars. Should be in the shape of [num_rect, 8, 2].
        color (tuple[int], optional): The color to draw bboxes.
            Default: (0, 255, 0).
        thickness (int, optional): The thickness of bboxes. Default: 1.
    """
    line_indices = ((0, 1), (0, 3), (0, 4), (1, 2), (1, 5), (3, 2), (3, 7),
                    (4, 5), (4, 7), (2, 6), (5, 6), (6, 7))
    # thickness = 0.5
    # print('rect_corners type:', rect_corners.dtype)
    # print('img type',type(img))
    for i in range(num_rects):
        corners = rect_corners[i].astype(np.int64)
        # print("opencv corners type:", corners.dtype)

        for start, end in line_indices:
            # cv2.line(img, (corners[start, 0], corners[start, 1]),
            #          (corners[end, 0], corners[end, 1]), color, thickness,
            #          cv2.LINE_AA)
            # print("change:", type(int(corners[start, 0])))
            cv2.line(img,
                     tuple(corners[start]),
                     tuple(corners[end]),
                     color,
                     thickness,
                     cv2.LINE_AA)
            # cv2.line(img,
            #          (int(corners[start, 0]), int(corners[start, 1])),
            #          (int(corners[end, 0]), int(corners[end, 1])),
            #          color,
            #          thickness,
            #          cv2.LINE_AA)

    # return img.astype(np.uint8)
    return img


def draw_lidar_bbox3d_on_img(bboxes3d,
                             raw_img,
                             lidar2img_rt,
                             img_metas,
                             color=(0, 255, 0),
                             thickness=1):
    """Project the 3D bbox on 2D plane and draw on input image.

    Args:
        bboxes3d (:obj:`LiDARInstance3DBoxes`):
            3d bbox in lidar coordinate system to visualize.
        raw_img (numpy.array): The numpy array of image.
        lidar2img_rt (numpy.array, shape=[4, 4]): The projection matrix
            according to the camera intrinsic parameters.
        img_metas (dict): Useless here.
        color (tuple[int], optional): The color to draw bboxes.
            Default: (0, 255, 0).
        thickness (int, optional): The thickness of bboxes. Default: 1.
    """
    img = raw_img.copy()
    corners_3d = bboxes3d.corners.cpu().numpy()
    num_bbox = corners_3d.shape[0]
    pts_4d = np.concatenate(
        [corners_3d.reshape(-1, 3),
         np.ones((num_bbox * 8, 1))], axis=-1)
    lidar2img_rt = copy.deepcopy(lidar2img_rt).reshape(4, 4)
    if isinstance(lidar2img_rt, torch.Tensor):
        lidar2img_rt = lidar2img_rt.cpu().numpy()
    pts_2d = pts_4d @ lidar2img_rt.T

    pts_2d[:, 2] = np.clip(pts_2d[:, 2], a_min=1e-5, a_max=1e5)
    pts_2d[:, 0] /= pts_2d[:, 2]
    pts_2d[:, 1] /= pts_2d[:, 2]
    imgfov_pts_2d = pts_2d[..., :2].reshape(num_bbox, 8, 2)

    return plot_rect3d_on_img(img, num_bbox, imgfov_pts_2d, color, thickness)


# TODO: remove third parameter in all functions here in favour of img_metas
def draw_depth_bbox3d_on_img(bboxes3d,
                             raw_img,
                             calibs,
                             img_metas,
                             color=(0, 255, 0),
                             thickness=1):
    """Project the 3D bbox on 2D plane and draw on input image.

    Args:
        bboxes3d (:obj:`DepthInstance3DBoxes`, shape=[M, 7]):
            3d bbox in depth coordinate system to visualize.
        raw_img (numpy.array): The numpy array of image.
        calibs (dict): Camera calibration information, Rt and K.
        img_metas (dict): Used in coordinates transformation.
        color (tuple[int], optional): The color to draw bboxes.
            Default: (0, 255, 0).
        thickness (int, optional): The thickness of bboxes. Default: 1.
    """
    from mmdet3d.structures import points_cam2img
    from mmdet3d.models import apply_3d_transformation

    img = raw_img.copy()
    img_metas = copy.deepcopy(img_metas)
    corners_3d = bboxes3d.corners
    num_bbox = corners_3d.shape[0]
    points_3d = corners_3d.reshape(-1, 3)

    # first reverse the data transformations
    xyz_depth = apply_3d_transformation(
        points_3d, 'DEPTH', img_metas, reverse=True)

    # project to 2d to get image coords (uv)
    uv_origin = points_cam2img(xyz_depth,
                               xyz_depth.new_tensor(img_metas['depth2img']))
    uv_origin = (uv_origin - 1).round()
    imgfov_pts_2d = uv_origin[..., :2].reshape(num_bbox, 8, 2).numpy()

    return plot_rect3d_on_img(img, num_bbox, imgfov_pts_2d, color, thickness)


def draw_camera_bbox3d_on_img(bboxes3d,
                              raw_img,
                              cam2img,
                              img_metas,
                              color=(0, 255, 0),
                              thickness=1):
    """Project the 3D bbox on 2D plane and draw on input image.

    Args:
        bboxes3d (:obj:`CameraInstance3DBoxes`, shape=[M, 7]):
            3d bbox in camera coordinate system to visualize.
        raw_img (numpy.array): The numpy array of image.
        cam2img (dict): Camera intrinsic matrix,
            denoted as `K` in depth bbox coordinate system.
        img_metas (dict): Useless here.
        color (tuple[int], optional): The color to draw bboxes.
            Default: (0, 255, 0).
        thickness (int, optional): The thickness of bboxes. Default: 1.
    """
    from mmdet3d.structures import points_cam2img

    img = raw_img.copy()
    cam2img = copy.deepcopy(cam2img)
    corners_3d = bboxes3d.corners
    num_bbox = corners_3d.shape[0]
    points_3d = corners_3d.reshape(-1, 3)
    if not isinstance(cam2img, torch.Tensor):
        cam2img = torch.from_numpy(np.array(cam2img))

    assert (cam2img.shape == torch.Size([3, 3])
            or cam2img.shape == torch.Size([4, 4]))
    cam2img = cam2img.float().cpu()

    # project to 2d to get image coords (uv)
    uv_origin = points_cam2img(points_3d, cam2img)
    uv_origin = (uv_origin - 1).round()
    imgfov_pts_2d = uv_origin[..., :2].reshape(num_bbox, 8, 2).numpy()

    return plot_rect3d_on_img(img, num_bbox, imgfov_pts_2d, color, thickness)

下面是推理和绘制的完整代码,必要的注释已经给出。

from custom_API.draw_box import show_multi_modality_result #如何导入取决于读者如何存放
print(f'datasets length:{len(datasets)}')
data_root = 'data/kitti/' # 数据集根路径
save_root = '/home/wistful/work/open_mmlab_mmdetection3d/visual_dir/predict_imgs/' # 保存可视化结果的根路径

data_num = 100  # 最大不能超过数据集长度
# 判断一开始是读取的哪个数据集
if set == 'train' or set == 'val':
    new_set = 'training'
else:
    new_set = 'testing'
# 推理整个数据集的前data_num条数据
for i in tqdm(range(data_num), desc='process situation'):
    # cyclic_load_data_item代码位于第2步
    batch_inputs_dict, batch_data_samples = cyclic_load_data_item(datasets, index=i, device=device)  # 读取一条数据,并构建批次
    points = batch_inputs_dict['points'][0]  # 获取点云,因为是单条数据,所以直接取0

    # 获取检测结果
    result, data = inference_detector(model, points.cpu())
    bboxes_3d = result.pred_instances_3d.bboxes_3d
    labels_3d = result.pred_instances_3d.labels_3d
    scores_3d = result.pred_instances_3d.scores_3d

    # 设置阈值
    thr = 0.4
    score = (scores_3d > thr)
    bboxes_3d = bboxes_3d[score] # 根据阈值筛选

    # 读取原始图像
    img_file_path = data_root + new_set + '/image_2/' + batch_data_samples[0].img_path[0]
    image = cv2.imread(img_file_path)

    img_name = batch_data_samples[0].img_path[0].split('.')[0] # 取一下文件名
    # 保存多模态结果(调用的旧版mmdet代码接口)
    show_multi_modality_result(img=image,
                               box_mode='lidar',
                               gt_bboxes=None,
                               pred_bboxes=bboxes_3d,
                               batch_data_samples=batch_data_samples,
                               out_dir=save_root,
                               filename=img_name,
                               type=set,
                               show=False)

    # result = model(batch_inputs_dict, batch_data_samples) # model的输入与具体模型有关

运行上述代码后,会在设置的save_root下生成可视化图片
在这里插入图片描述

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

记录-2023/11/18

1. 序列器中可以定义update方法 2. 分页之后前端获取数据的方式要进行改变 JavaScript的switch语法2 situation "a"switch (situation) {case "a":console.log("a")breakcase "b":console.log("b")breakcase "c&quo…

小美的树上染色

美团2024届秋招笔试第一场编程真题 先提一个小知识&#xff1a;题目中凡是提到树结构都要使用图的存储方式&#xff0c;只有二叉树例外。 分析&#xff1a;在树结构中&#xff0c;孩子和父节点是相邻节点&#xff0c;而父节点可能有多个孩子节点。在染色的过程中&#xff0c;…

【linux】补充:高效处理文本的命令学习(tr、uniq、sort、cut)

目录 一、tr——转换、压缩、删除 1、tr -s “分隔符” &#xff08;指定压缩连续的内容&#xff09; 2、tr -d 想要删除的东西 ​编辑 3、tr -t 内容1 内容2 将内容1全部转换为内容2&#xff08;字符数需要一一对应&#xff09; 二、cut——快速剪裁命令 三、uniq——去…

MongoDB之索引和聚合

文章目录 一、索引1、说明2、原理3、相关操作3.1、创建索引3.2、查看集合索引3.3、查看集合索引大小3.4、删除集合所有索引&#xff08;不包含_id索引&#xff09;3.5、删除集合指定索引 4、复合索引 二、聚合1、说明2、使用 总结 一、索引 1、说明 索引通常能够极大的提高查…

Python3.7+PyQt5 pyuic5将.ui文件转换为.py文件、Python读取配置文件、生成日志

1.实际开发项目时&#xff0c;是使用Qt Designer来设计UI界面&#xff0c;得到一个.ui的文件&#xff0c;然后利用PyQt5安装时自带的工具pyuic5将.ui文件转换为.py文件&#xff1a; pyuic5 -o mywindow.py mywindow.ui #先是py文件名&#xff0c;再是ui文件名样式图 QT5 UI&am…

端口号大揭秘:网络世界的“门牌号”有多牛?

大家好&#xff0c;今天我们来聊一聊网络中的端口号。如果你以为端口号只是冷冰冰的数字&#xff0c;那你就大错特错了。端口号&#xff0c;这些看似枯燥的数字背后&#xff0c;隐藏着一个个生动的故事。 1. 80/tcp - HTTP&#xff1a;数字版的美食街 首先&#xff0c;让我们迈…

6.9平衡二叉树(LC110-E)

绝对值函数&#xff1a;abs() 算法&#xff1a; 高度和深度的区别&#xff1a; 节点的高度&#xff1a;节点到叶子节点的距离&#xff08;从下往上&#xff09; 节点的深度&#xff1a;节点到根节点的距离&#xff08;从上往下&#xff09; 逻辑&#xff1a;一个平衡二叉树…

对象与this

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 最近想再聊聊Java的对象…

JVM 调优指南

文章目录 为什么要学 JVM一、JVM 整体布局二、Class 文件规范三、类加载模块四、执行引擎五、GC 垃圾回收1 、JVM内存布局2 、 JVM 有哪些主要的垃圾回收器&#xff1f;3 、分代垃圾回收工作机制 六、对 JVM 进行调优的基础思路七、 GC 情况分析实例 JVM调优指南 -- 楼兰 ​ JV…

系列七、GC垃圾回收【四大垃圾算法-标记压缩算法】

一、原理 在整理压缩阶段&#xff0c;不再对标记的对象回收&#xff0c;而是通过所有存活对象都向一端移动。可以看到&#xff0c;标记的存活对象将会被整理&#xff0c;按照内存地址依次排列。如此一来&#xff0c;当我们需要给新对象分配内存时&#xff0c;JVM只需要持有一个…

永久关机windows系统自动更新

1、打开cmd执行 reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" /v FlightSettingsMaxPauseDays /t reg_dword /d 3000 /f2、设置&#xff0c;打开windows更新高级选项 修改暂停日期&#xff0c;可长达十年。 3、你小子

解锁数据安全之门:探秘迅软DSE的文件权限控制功能

企业管理者在进行数据安全管控时通常只关注到文件的加密方式&#xff0c;却忽略了以下问题&#xff1a;对于企业内部文档&#xff0c;根据其所承载的涉密程度不同&#xff0c;重要程度也不相同&#xff0c;需要由不同涉密等级的的人员进行处理&#xff0c;这就需要对涉密文档和…

战神传奇【我本沉默精修版】win服务端+双端+充值后台+架设教程

搭建资源下载:战神传奇【我本沉默精修版】win服务端双端充值后台架设教程-海盗空间

详解Java设计模式之职责链模式

原文&#xff1a;详解Java设计模式之职责链模式_java_脚本之家 责任链模式是一种行为设计模式&#xff0c;使多个对象都有机会处理请求&#xff0c;从而避免请求的发送者和接收者之间的耦合关系&#xff0c;文中通过代码示例给大家介绍的非常详细,需要的朋友可以参考下 − 目…

TG Pro v2.87(mac温度风扇速度控制工具)

TG Pro 是适用于 macOS 的温度和风扇速度控制工具&#xff0c;可让您监控 Mac 组件&#xff08;例如 CPU 和 GPU&#xff09;的温度和风扇速度。如果您担心 Mac 过热或想要手动调整风扇速度以降低噪音水平&#xff0c;这将特别有用。 除了温度和风扇监控&#xff0c;TG Pro 还…

基于截图页面生成前端项目

前两天&#xff0c;在群里看见一个视频&#xff0c;视频中&#xff0c;作者截图twitter首页&#xff0c;然后使用截图直接生成与截图布局非常相近的前端项目&#xff0c;效果还是比较惊艳的。 今天陪老婆回老家&#xff0c;路上clone这个项目的代码到本地&#xff0c;学习了一下…

回归预测 | Matlab实现HPO-ELM猎食者算法优化极限学习机的数据回归预测

回归预测 | Matlab实现HPO-ELM猎食者算法优化极限学习机的数据回归预测 目录 回归预测 | Matlab实现HPO-ELM猎食者算法优化极限学习机的数据回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 Matlab实现HPO-ELM猎食者算法优化极限学习机的数据回归预测&#xff08;…

Bert学习笔记(简单入门版)

目 录 一、基础架构 二、输入部分 三、预训练&#xff1a;MLMNSP 3.1 MLM&#xff1a;掩码语言模型 3.1.1 mask模型缺点 3.1.2 mask的概率问题 3.1.3 mask代码实践 3.2 NSP 四、如何微调Bert 五、如何提升BERT下游任务表现 5.1 一般做法 5.2 如何在相同领域数据中进…

037、目标检测-算法速览

之——常用算法速览 目录 之——常用算法速览 杂谈 正文 1.区域卷积神经网络 - R-CNN 2.单发多框检测SSD&#xff0c;single shot detection 3.yolo 杂谈 快速过一下目标检测的各类算法。 正文 1.区域卷积神经网络 - R-CNN region_based CNN&#xff0c;奠基性的工作。…