探索基于300W-LP的3D人脸关键点检测

news2024/11/26 15:37:20

目录

  • 前言
  • 一、3D 关键点可视化
  • 二、使用步骤
    • 1.300W-LP转为YOLO数据格式
    • 2.修改数据入口
    • 3.开始训练
  • 总结


前言

300WLP数据集提供来丰富的人脸线索,包括2D或3D的关键点信息,Head Angle和3DMM的参数等.它可以用于2/3D的人脸关键点检测,以及头部姿态检测等任务.这里,我们尝试去实现端到段的3D人脸关键点检测.


一、3D 关键点可视化

在这里插入图片描述
如左图所示,其3D特征点其实是在相机平面上的二维投影,并非真正的含有深度信息的.

二、使用步骤

1.300W-LP转为YOLO数据格式

代码如下(示例):

import os, cv2
import hdf5storage
import numpy as np
import sys


import scipy.io as sio
 


def process_300WLP(root_folder, folder_name, image_name, label_name, target_size):
    #modify by WQT, referring from PIPNet

    image_path = os.path.join(root_folder, folder_name, image_name)
    label_path = os.path.join(root_folder, 'landmarks', folder_name, label_name)

    with open(label_path, 'r') as ff:
        C = sio.loadmat(label_path)
        anno = C['pts_3d'] 

        # anno = ff.readlines()[3:-1]
        # anno = [x.strip().split() for x in anno]
        # # anno = [[int(float(x[0])), int(float(x[1]))] for x in anno]
        # anno = [[float(x[0]), float(x[1])] for x in anno]
        anno_x = [x[0] for x in anno]
        anno_y = [x[1] for x in anno]

        # anno_x = anno[0, :]
        # anno_y = anno[-1, :]
        bbox_xmin = min(anno_x)
        bbox_ymin = min(anno_y)
        bbox_xmax = max(anno_x)
        bbox_ymax = max(anno_y)

        bbox_width = bbox_xmax - bbox_xmin + 1
        bbox_height = bbox_ymax - bbox_ymin + 1
        
        image = cv2.imread(image_path)
        image_height, image_width, _ = image.shape
        bbox_xcenter = bbox_xmin + bbox_width/2
        bbox_ycenter = bbox_ymin + bbox_height/2

        padding = 2 # to enlarge the face box
        isCrowdAndXYWH = [0, bbox_xcenter/image_width, bbox_ycenter/image_height, (bbox_width+padding)/image_width, (bbox_height+padding)/image_height]
        anno = [[x/image_width, y/image_height, 2] for x,y in anno]

        return image, isCrowdAndXYWH, anno

def gen_meanface(root_folder, data_name):
    with open(os.path.join(root_folder, data_name, 'train2yolo.txt'), 'r') as f:
        annos = f.readlines()
    annos = [x.strip().split()[1:] for x in annos]
    annos = [[float(x) for x in anno] for anno in annos]
    annos = np.array(annos)
    meanface = np.mean(annos, axis=0)
    meanface = meanface.tolist()
    meanface = [str(x) for x in meanface]
    
    with open(os.path.join(root_folder, data_name, 'meanface.txt'), 'w') as f:
        f.write(' '.join(meanface))

def convert_wflw(root_folder, data_name):
    with open(os.path.join('../data/WFLW/test.txt'), 'r') as f:
        annos = f.readlines()
    annos = [x.strip().split() for x in annos]
    annos_new = []
    for anno in annos:
        annos_new.append([])
        # name
        annos_new[-1].append(anno[0])
        anno = anno[1:]
        # jaw
        for i in range(17):
            annos_new[-1].append(anno[i*2*2])
            annos_new[-1].append(anno[i*2*2+1])
        # left eyebrow
        annos_new[-1].append(anno[33*2])
        annos_new[-1].append(anno[33*2+1])
        annos_new[-1].append(anno[34*2])
        annos_new[-1].append(str((float(anno[34*2+1])+float(anno[41*2+1]))/2))
        annos_new[-1].append(anno[35*2])
        annos_new[-1].append(str((float(anno[35*2+1])+float(anno[40*2+1]))/2))
        annos_new[-1].append(anno[36*2])
        annos_new[-1].append(str((float(anno[36*2+1])+float(anno[39*2+1]))/2))
        annos_new[-1].append(anno[37*2])
        annos_new[-1].append(str((float(anno[37*2+1])+float(anno[38*2+1]))/2))
        # right eyebrow
        annos_new[-1].append(anno[42*2])
        annos_new[-1].append(str((float(anno[42*2+1])+float(anno[50*2+1]))/2))
        annos_new[-1].append(anno[43*2])
        annos_new[-1].append(str((float(anno[43*2+1])+float(anno[49*2+1]))/2))
        annos_new[-1].append(anno[44*2])
        annos_new[-1].append(str((float(anno[44*2+1])+float(anno[48*2+1]))/2))
        annos_new[-1].append(anno[45*2])
        annos_new[-1].append(str((float(anno[45*2+1])+float(anno[47*2+1]))/2))
        annos_new[-1].append(anno[46*2])
        annos_new[-1].append(anno[46*2+1])
        # nose
        for i in range(51, 60):
            annos_new[-1].append(anno[i*2])
            annos_new[-1].append(anno[i*2+1])
        # left eye
        annos_new[-1].append(anno[60*2])
        annos_new[-1].append(anno[60*2+1])
        annos_new[-1].append(str(0.666*float(anno[61*2])+0.333*float(anno[62*2])))
        annos_new[-1].append(str(0.666*float(anno[61*2+1])+0.333*float(anno[62*2+1])))
        annos_new[-1].append(str(0.666*float(anno[63*2])+0.333*float(anno[62*2])))
        annos_new[-1].append(str(0.666*float(anno[63*2+1])+0.333*float(anno[62*2+1])))
        annos_new[-1].append(anno[64*2])
        annos_new[-1].append(anno[64*2+1])
        annos_new[-1].append(str(0.666*float(anno[65*2])+0.333*float(anno[66*2])))
        annos_new[-1].append(str(0.666*float(anno[65*2+1])+0.333*float(anno[66*2+1])))
        annos_new[-1].append(str(0.666*float(anno[67*2])+0.333*float(anno[66*2])))
        annos_new[-1].append(str(0.666*float(anno[67*2+1])+0.333*float(anno[66*2+1])))
        # right eye
        annos_new[-1].append(anno[68*2])
        annos_new[-1].append(anno[68*2+1])
        annos_new[-1].append(str(0.666*float(anno[69*2])+0.333*float(anno[70*2])))
        annos_new[-1].append(str(0.666*float(anno[69*2+1])+0.333*float(anno[70*2+1])))
        annos_new[-1].append(str(0.666*float(anno[71*2])+0.333*float(anno[70*2])))
        annos_new[-1].append(str(0.666*float(anno[71*2+1])+0.333*float(anno[70*2+1])))
        annos_new[-1].append(anno[72*2])
        annos_new[-1].append(anno[72*2+1])
        annos_new[-1].append(str(0.666*float(anno[73*2])+0.333*float(anno[74*2])))
        annos_new[-1].append(str(0.666*float(anno[73*2+1])+0.333*float(anno[74*2+1])))
        annos_new[-1].append(str(0.666*float(anno[75*2])+0.333*float(anno[74*2])))
        annos_new[-1].append(str(0.666*float(anno[75*2+1])+0.333*float(anno[74*2+1])))
        # mouth
        for i in range(76, 96):
            annos_new[-1].append(anno[i*2])
            annos_new[-1].append(anno[i*2+1])

    with open(os.path.join(root_folder, data_name, 'test.txt'), 'w') as f:
        for anno in annos_new:
            f.write(' '.join(anno)+'\n')


def gen_data(root_folder, data_name, target_size):
    if not os.path.exists(os.path.join(root_folder, data_name, 'images_train2yolo')):
        os.mkdir(os.path.join(root_folder, data_name, 'images_train2yolo'))
    if not os.path.exists(os.path.join(root_folder, data_name, 'images_test2yolo')):
        os.mkdir(os.path.join(root_folder, data_name, 'images_test2yolo'))   
    #这是为了把cropped的人脸存入新文件夹,由于我们不需要此步,即可省掉也行

    ################################################################################################################
    if data_name == '300W_LP':

        # folders_train = ['AFW', 'HELEN',  'IBUG',  'LFPW']
        folders_train = ['HELEN',   'LFPW']
        annos_train = {}
        for folder_train in folders_train:
            all_files = sorted(os.listdir(os.path.join(root_folder, data_name, folder_train)))
            image_files = [x for x in all_files if '.mat' not in x]
            # label_files = [x for x in all_files if '.mat' in x]
            label_files = [x.split('.')[0]+'_pts.mat' for x in all_files if '.mat' in x]
            assert len(image_files) == len(label_files)
            for image_name, label_name in zip(image_files, label_files):
                
                image_crop, isCrowdAndXYWH, anno = process_300WLP(os.path.join(root_folder, '300W_LP'), folder_train, image_name, label_name, target_size)               
                image_crop_name = image_name
                cv2.imwrite(os.path.join(root_folder, data_name, 'images', 'train', image_crop_name), image_crop)
                annos_train[image_crop_name] =   isCrowdAndXYWH, anno

        with open(os.path.join(root_folder, data_name, 'train2yolo.txt'), 'w') as f:
            for image_crop_name, anno in annos_train.items():
                f.write('./images/train/' + image_crop_name)   #./images/val2017/000000345356.jpg
                # f.write(image_crop_name+' ')
                # for x,y in anno:
                #     f.write(str(x)+' '+str(y)+' ')
                f.write('\n')

                base_txt = os.path.basename(image_crop_name.split('.')[0]) + ".txt"
                save_txt_path = os.path.join(root_folder, data_name,'labels', 'train', base_txt)
                with open(save_txt_path, 'w') as f_txt:
                    for xywh in anno[0]:
                        f_txt.write(str(xywh)+' ')
                    for x, y, z in anno[1]:
                        f_txt.write(str(x)+' '+str(y)+' '+str(z)+' ')
                    f_txt.write('\n') 

        folders_test = ['AFW',  'IBUG']
        annos_test = {}
        for folder_test in folders_test:
            all_files = sorted(os.listdir(os.path.join(root_folder, data_name, folder_test)))
            image_files = [x for x in all_files if '.mat' not in x]
            # label_files = [x for x in all_files if '.mat' in x]
            label_files = [x.split('.')[0]+'_pts.mat' for x in all_files if '.mat' in x]
            assert len(image_files) == len(label_files)
            for image_name, label_name in zip(image_files, label_files):
                
                image_crop, isCrowdAndXYWH, anno = process_300WLP(os.path.join(root_folder, '300W_LP'), folder_test, image_name, label_name, target_size)               
                image_crop_name = image_name
                cv2.imwrite(os.path.join(root_folder, data_name, 'images', 'test', image_crop_name), image_crop)
                annos_test[image_crop_name] =   isCrowdAndXYWH, anno

        with open(os.path.join(root_folder, data_name, 'test2yolo.txt'), 'w') as f:
            for image_crop_name, anno in annos_test.items():
                f.write('./images/test/' + image_crop_name)   #./images/val2017/000000345356.jpg
                # f.write(image_crop_name+' ')
                # for x,y in anno:
                #     f.write(str(x)+' '+str(y)+' ')
                f.write('\n')

                base_txt = os.path.basename(image_crop_name.split('.')[0]) + ".txt"
                save_txt_path = os.path.join(root_folder, data_name,'labels', 'test', base_txt)
                with open(save_txt_path, 'w') as f_txt:
                    for xywh in anno[0]:
                        f_txt.write(str(xywh)+' ')
                    for x, y, z in anno[1]:
                        f_txt.write(str(x)+' '+str(y)+' '+str(z)+' ')
                    f_txt.write('\n') 

        gen_meanface(root_folder, data_name)

    elif data_name == 'LaPa':
        pass
        # TODO
    else:
        print('Wrong data!')

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print('please input the data name.')
        print('1. 300W_LP')
        print('0. data_300W')
        print('2. COFW')
        print('3. WFLW')
        print('4. AFLW')
        print('5. LaPa')
        exit(0)
    else:
        data_name = sys.argv[1]
        gen_data('../', data_name, 256)

2.修改数据入口

修改ultrlytics/datasets/coco8-pose.yaml中的path.
参考如下(示例):

# Ultralytics YOLO 🚀, AGPL-3.0 license
# COCO8-pose dataset (first 8 images from COCO train2017) by Ultralytics
# Example usage: yolo train data=coco8-pose.yaml
# parent
# ├── ultralytics
# └── datasets
#     └── coco8-pose  ← downloads here (1 MB)

path: 
  /home/wqt/Datasets/300W-LP/300W_LP
  # ../datasets/coco8-pose  # dataset root dir
train: 
  train2yolo.txt
  # data/video_68out/026_noglasses_mix_tired1/train2yolo.txt
  # data/video_68out/WIN_20230417_15_51_51_Pro/train2yolo.txt
  # images/train  # train images (relative to 'path') 4 images
val: 
  test2yolo.txt
  # images/val  # val images (relative to 'path') 4 images
test:  # test images (optional)

# Keypoints
kpt_shape: [68, 3]  # number of keypoints, number of dims (2 for x,y or 3 for x,y,visible)
flip_idx: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 27, 28, 29, 30, 35, 34, 33, 32, 31, 45, 44, 43, 42, 47, 46, 39, 38, 37, 36, 41, 40, 54, 53, 52, 51, 50, 49, 48, 59, 58, 57, 56, 55, 64, 63, 62, 61, 60, 67, 66, 65]
# Classes
names:
  # 0: person  #ori
  0: face      #wqt

# Download script/URL (optional)
download: https://ultralytics.com/assets/coco8-pose.zip

3.开始训练

超参数设置

yolo/engine/trainer: task=pose, mode=train, model=/home/wqt/NewProjects/ultralyticsWholeBody/runs/pose/train10/weights/best.pt, data=coco8-pose.yaml, epochs=100, patience=50, batch=16, imgsz=640, save=True, save_period=20, cache=False, device=, workers=8, project=None, name=/home/wqt/NewProjects/ultralyticsFaceMark/runs/pose/train, exist_ok=False, pretrained=False, optimizer=SGD, verbose=True, seed=0, deterministic=True, single_cls=False, rect=False, cos_lr=False, close_mosaic=0, resume=False, amp=True, fraction=1.0, profile=False, overlap_mask=True, mask_ratio=4, dropout=0.0, val=True, split=val, save_json=False, save_hybrid=False, conf=None, iou=0.7, max_det=300, half=False, dnn=False, plots=True, source=None, show=False, save_txt=False, save_conf=False, save_crop=False, show_labels=True, show_conf=True, vid_stride=1, line_width=None, visualize=False, augment=False, agnostic_nms=False, classes=None, retina_masks=False, boxes=True, format=torchscript, keras=False, optimize=False, int8=False, dynamic=False, simplify=False, opset=None, workspace=4, nms=False, lr0=0.01, lrf=0.01, momentum=0.937, weight_decay=0.0005, warmup_epochs=3.0, warmup_momentum=0.8, warmup_bias_lr=0.1, box=7.5, cls=0.5, dfl=1.5, pose=12.0, kobj=1.0, label_smoothing=0.0, nbs=64, hsv_h=0.015, hsv_s=0.7, hsv_v=0.4, degrees=0.0, translate=0.1, scale=0.5, shear=0.0, perspective=0.0, flipud=0.0, fliplr=0.5, mosaic=1.0, mixup=0.0, copy_paste=0.0, cfg=None, v5loader=False, tracker=botsort.yaml, save_dir=/home/wqt/NewProjects/ultralyticsFaceMark/runs/pose/train2
Overriding model.yaml kpt_shape=[133, 3] with kpt_shape=[68, 3]

网络结构,参考yolo8

                   from  n    params  module                                       arguments                     
  0                  -1  1       928  ultralytics.nn.modules.conv.Conv             [3, 32, 3, 2]                 
  1                  -1  1     18560  ultralytics.nn.modules.conv.Conv             [32, 64, 3, 2]                
  2                  -1  1     29056  ultralytics.nn.modules.block.C2f             [64, 64, 1, True]             
  3                  -1  1     73984  ultralytics.nn.modules.conv.Conv             [64, 128, 3, 2]               
  4                  -1  2    197632  ultralytics.nn.modules.block.C2f             [128, 128, 2, True]           
  5                  -1  1    295424  ultralytics.nn.modules.conv.Conv             [128, 256, 3, 2]              
  6                  -1  2    788480  ultralytics.nn.modules.block.C2f             [256, 256, 2, True]           
  7                  -1  1   1180672  ultralytics.nn.modules.conv.Conv             [256, 512, 3, 2]              
  8                  -1  1   1838080  ultralytics.nn.modules.block.C2f             [512, 512, 1, True]           
  9                  -1  1    656896  ultralytics.nn.modules.block.SPPF            [512, 512, 5]                 
 10                  -1  1         0  torch.nn.modules.upsampling.Upsample         [None, 2, 'nearest']          
 11             [-1, 6]  1         0  ultralytics.nn.modules.conv.Concat           [1]                           
 12                  -1  1    591360  ultralytics.nn.modules.block.C2f             [768, 256, 1]                 
 13                  -1  1         0  torch.nn.modules.upsampling.Upsample         [None, 2, 'nearest']          
 14             [-1, 4]  1         0  ultralytics.nn.modules.conv.Concat           [1]                           
 15                  -1  1    148224  ultralytics.nn.modules.block.C2f             [384, 128, 1]                 
 16                  -1  1    147712  ultralytics.nn.modules.conv.Conv             [128, 128, 3, 2]              
 17            [-1, 12]  1         0  ultralytics.nn.modules.conv.Concat           [1]                           
 18                  -1  1    493056  ultralytics.nn.modules.block.C2f             [384, 256, 1]                 
 19                  -1  1    590336  ultralytics.nn.modules.conv.Conv             [256, 256, 3, 2]              
 20             [-1, 9]  1         0  ultralytics.nn.modules.conv.Concat           [1]                           
 21                  -1  1   1969152  ultralytics.nn.modules.block.C2f             [768, 512, 1]                 
 22        [15, 18, 21]  1   5013031  ultralytics.nn.modules.head.Pose             [1, [68, 3], [128, 256, 512]] 
YOLOv8s-pose summary: 250 layers, 14032583 parameters, 14032567 gradients

训练集与测试集

Transferred 361/397 items from pretrained weights
AMP: running Automatic Mixed Precision (AMP) checks with YOLOv8n...
AMP: checks passed ✅
optimizer: SGD(lr=0.01) with parameter groups 63 weight(decay=0.0), 73 weight(decay=0.0005), 72 bias
train: Scanning /home/wqt/Datasets/300W-LP/300W_LP/labels/train... 54232 images, 0 backgrounds, 0 corrupt: 100%|██████████| 54232/54232 [00:45<00:00, 1190.60it/s]
train: New cache created: /home/wqt/Datasets/300W-LP/300W_LP/labels/train.cache
val: Scanning /home/wqt/Datasets/300W-LP/300W_LP/labels/test... 6993 images, 0 backgrounds, 0 corrupt: 100%|██████████| 6993/6993 [00:06<00:00, 1127.92it/s]
val: New cache created: /home/wqt/Datasets/300W-LP/300W_LP/labels/test.cache
Plotting labels to /home/wqt/NewProjects/ultralyticsFaceMark/runs/pose/train2/labels.jpg... 
Image sizes 640 train, 640 val
Using 8 dataloader workers
Logging results to /home/wqt/NewProjects/ultralyticsFaceMark/runs/pose/train2
Starting training for 100 epochs...

      Epoch    GPU_mem   box_loss  pose_loss  kobj_loss   cls_loss   dfl_loss  Instances       Size
      1/100      4.58G     0.9736          7     0.6731     0.9241      1.464         34        640:  29%|██▉       | 992/3390 [04:26<10:48,  3.70it/s]

训练过程:
在这里插入图片描述


总结

期待好的结果!

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

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

相关文章

【岗位】IT行业岗位知识图谱--大数据工程师、机器学习、嵌入式、架构师

目录 1. 大数据工程师技能图谱2. 机器学习技能图谱3. 架构师技能图谱4. 嵌入式开发必备技能5. 嵌入式体系结构 1. 大数据工程师技能图谱 2. 机器学习技能图谱 3. 架构师技能图谱 4. 嵌入式开发必备技能 5. 嵌入式体系结构 **点赞、关注、评论、收藏哦**

7.7.8clip/简单量化

一、 clip函数&#xff1a;限制一个array的上下界 给定一个范围[min, max]&#xff0c;数组中值不在这个范围内的&#xff0c;会被限定为这个范围的边界。如给定范围[0, 1]&#xff0c;数组中元素值小于0的&#xff0c;值会变为0&#xff0c;数组中元素值大于1的&#xff0c;要…

【云存储】主流分布式文件系统介绍

目录 1、引言 2、云存储与分布式文件系统 2.1、云存储 2.2、分布式文件系统 3、Google的三大云计算与云存储论文 3.1、The Google File System&#xff08;谷歌文件系统&#xff09; 3.2、MapReduce&#xff1a;Simplified Data Processing on Large Clusters&#xff0…

云原生之深入解析Kubernetes CNI插件的选型和应用场景

一、常见网络插件 在学习容器网络的时候&#xff0c;肯定都听说过 Docker 的 bridge 网络、Vethpair、VxLAN 等术语&#xff0c;从 Docker 到 Kubernetes 后&#xff0c;学习 Flannel、Calico 等主流网络插件&#xff0c;分别代表了 Overlay 和 Underlay 的两种网络传输模式&a…

【VirtualBox】安装 VirtualBox 提示 needsthe Microsoft Visual C++ 2019

概述 一个好的文章能够帮助开发者完成更便捷、更快速的开发。书山有路勤为径&#xff0c;学海无涯苦作舟。我是秋知叶i、期望每一个阅读了我的文章的开发者都能够有所成长。 一、开发环境 开发环境&#xff1a;windows10虚拟机&#xff1a;VirtualBox 7.0.8 二、报错 ubun…

多条件见多值查询的 Excel 公式和 python 函数

问题 Python草堂 群的一位群友问&#xff1a;excel 数据表&#xff0c;用 vlookup 函数怎样实现多条件查询多值&#xff0c;多值排到一行上。如下图所示&#xff1a; 左边是数据清单&#xff0c;希望根据两个条件&#xff1a;产品、日期&#xff0c;查询数量&#xff0c;列到…

Element-UI el-table属性row-class-name用法

文章目录 前言官方示例自定义条件样式设置背景颜色样式stripe属性 设置背景颜色样式设置字体颜色总结 前言 可以通过指定 Table 组件的 row-class-name 属性来为 Table 中的某一行添加 class&#xff0c;表明该行处于某种状态。 官方示例 代码如下&#xff1a; <el-table…

体验版小程序为何无法访问云端服务器后端接口(请求失败...(已完美解决附加图片))?

文章目录 前言解决方案一解决方案二第一步第二步 前言 体验版小程序访问不到后端&#xff0c;接口请求失败&#xff0c;这个及其头疼的今天这个坑被我踩到了&#xff0c;呜呜呜~ 今天再发体验版小程序时&#xff0c;在微信开发者工具上面是可以正常访问后端的&#xff0c;但是线…

【sql注入-堆叠注入】多语句执行、结合其他注入

目录 堆叠注入 一、语法介绍 二、漏洞示例 三、常见形式 网络安全O 堆叠注入 一、语法介绍&#xff1a; 版本&#xff1a; 可以影响几乎所有的关系型数据库 原理&#xff1a; 将多条语句堆叠在一起进行查询&#xff0c;且可以执行多条SQL语句 语句之间以分号(;)隔开&#…

人气爆棚!广西、湖南、山西等地领导莅临数据宝考察交流

摘要&#xff1a;近期&#xff0c;数据宝发展如火如荼&#xff0c;企业展厅“忙不停”&#xff0c;见证众多思想碰撞、交流提升&#xff0c;迎来了各省领导莅临参观指导。 01 数字广西集团、青秀区政府领导一行莅临数据宝上海分公司实地走访 近日&#xff0c;数字广西集团党…

深入理解Linux网络——内核与用户进程协作之同步阻塞方案(BIO)

文章目录 一、相关实际问题二、socket的直接创建三、内核和用户进程协作之阻塞方式1&#xff09;等待接收消息2&#xff09;软中断模块3&#xff09;同步队列阻塞总结 在上一部分中讲述了网络包是如何从网卡送到协议栈的&#xff08;详见深入理解Linux网络——内核是如何接收到…

postman测试接口出现404

postman测试接口出现404 1.用postman调试接口的过程中&#xff0c;出现404的情况&#xff0c;但是接口明明已调到了&#xff0c;而且数据也已经存入数据库了&#xff0c;这让我感到很疑惑。看网上的解决办法检查了我的路径&#xff0c;提交方式、参数类型等都是正确的&#xf…

Java反射(Reflection)总结

目录 Java反射概述 Class类 Class对象获取的三种方式&#xff1a; Class类的常用方法 动态加载机制&#xff1a; 通过反射调用构造方法 Constructor类 通过反射获取继承关系 通过反射访问字段&#xff08;成员变量&#xff09; 获取字段值&#xff1a; 设置字段值 通过反…

MySQL数据库(四)

前言 本文讲述索引和事务&#xff0c;以及JDBC。 是关于MySQL的最后一弹啦~~ 重点小知识&#xff1a;MySQL数据库的存储结构是B树&#xff01;&#xff01; 目录 前言 一、索引 &#xff08;一&#xff09;查看索引 &#xff08;二&#xff09;创建索引 &#xff08;三&am…

【JVM】14. 堆外内存

文章目录 堆外内存的意义堆外内存(Off-heap memory)是指在计算机内存管理之外进行分配和使用的内存空间。与堆内内存(Heap memory)不同,堆外内存不受Java虚拟机(JVM)的垃圾回收机制控制,需要手动进行内存的分配和释放。 堆外内存通常由操作系统提供支持,可以通过直接…

3.利用matlab求平均值和中位数(matlab程序)

代码及运行结果 %% 算术平均值 clear all; A[1 2 3 4;4 4 4 4] m1mean(A) %对列元素求算术平均值 m2mean(A,2) %对行元素求算术平均值 %% 忽略非数计算算术平均值 clear all; A[1 4 nan 5;6 nan 7 nan] m1mean(A) %有nan就是nan…

深度学习-图像分类篇一:基础理论

开头言 学东西前总是爱问&#xff0c;这个学了有什么用&#xff0c;会用就行了么。能够回答你这个问题的人&#xff0c;都是学过的&#xff08;只有学过才有资格告诉你有没有用&#xff09;&#xff0c;然而知识往往就是这样&#xff0c;学的人越多越没有用&#xff0c;我可以…

使用 Google 的 zx 库编写切换微信小程序环境的脚本

背景 微信小程序目前为止还没有提供API或者具体的配置方式&#xff0c;给我们设置环境变量&#xff0c;所以还得自己想办法。 创建一个 shell 脚本——一个由诸如 Bash 或 zsh 之类的 shell 执行的脚本——可以是自动化重复任务的好方法。Node.js 似乎是编写 shell 脚本的理想…

Apache Calcite 简介

这张图上列的,是直接使用 Apache Calcite 或者至少相关联的项目。大家肯定能在里面找到很多自己熟悉的项目。 那 Apache Calcite 究竟是干嘛的,又为什么能这么流行呢? 首先,摆一个应该没多少人会反对的共识:SQL 是编程领域最流行的语言。 有 MySQL、Oracle 之类使用 SQL…

Linux---函数库和Makefile

Linux---函数库和Makefile 函数库动态库静态库例 Linux项目自动化构建工具-make/Makefile背景实例代码原理项目清理 函数库 方法实现就是在库当中&#xff0c;库其实就是把源文件经过一定的翻译&#xff0c;然后打包&#xff0c;只给你提供一个文件计科&#xff0c;不用给你提…