当前位置: 首页 > article >正文

【第二十五周】:DeepPose:通过深度神经网络实现人体姿态估计

DeepPose

  • 摘要
  • Abstract
  • 文章信息
  • 引言
  • DeepPose
    • 归一化
    • 网络结构
    • 初始网络(粗略估计所有关节点位置)
    • 精细化级联网络(分别修正每个关节点的位置)
  • 疑问与解决
  • 代码实践
  • 总结

摘要

这篇博客介绍了DeepPose,这是首个基于深度神经网络(DNN)的人体姿态估计框架,其核心思想是通过端到端回归直接预测人体关节坐标,摒弃了传统方法依赖手工特征和图形模型的局限性。针对传统算法在遮挡、复杂背景和小关节定位中的不足,DeepPose提出级联回归的方法:初始阶段利用全局低分辨率图像预测粗略关节点位置,后续级联阶段通过高分辨率局部图像块逐步修正误差,实现从粗到细的优化。为消除尺度差异,DeepPose对输入图像使用了归一化,且对级联网络进行独立训练,每个阶段参数分离以适配不同的输入尺度。该方法在LSP、FLIC等数据集上较传统方法定位误差降低20%-30%,尤其在遮挡场景下鲁棒性显著提升。但级联结构计算成本较高,且依赖初始预测的准确性。未来改进方向可结合热力图回归与级联优化,或引入轻量化网络提升实时性。

Abstract

This blog introduces DeepPose, the first deep neural network (DNN)-based framework for human pose estimation. Its core innovation lies in directly predicting joint coordinates through end-to-end regression, eliminating the reliance on handcrafted features and graphical models inherent in traditional methods. To address the limitations of conventional algorithms in handling occlusions, complex backgrounds, and small joint localization, DeepPose proposes a cascaded regression approach: the initial stage predicts rough joint positions using global low-resolution images, while subsequent cascaded stages iteratively refine errors via high-resolution local image patches, achieving coarse-to-fine optimization. To mitigate scale variance, DeepPose employs input normalization and independently trains cascaded networks with separated parameters to adapt to different input scales. Evaluations on datasets like LSP and FLIC demonstrate a 20%-30% reduction in localization errors compared to traditional methods, with marked robustness improvements in occlusion scenarios. However, the cascaded structure incurs higher computational costs and heavily depends on the accuracy of initial predictions. Future improvements may integrate heatmap regression with cascaded refinement or adopt lightweight networks for real-time performance. This work pioneers a regression-based paradigm for pose estimation, bridging the gap between global context awareness and local precision.


文章信息

Title:DeepPose: Human Pose Estimation via Deep Neural Networks
Author: Alexander Toshev, Christian Szegedy
Source:https://arxiv.org/abs/1312.4659


引言

人体姿态估计问题,被定义为人体关节定位问题。其难点在于人体关节的灵活性、某些关节小而模糊及遮挡问题。如下图,许多关节不可见,而我们可以通过看到的人物姿势和其余可见关节预测不可见的关节,并预测人体姿态。这也说明了全局推理的必要性。
在这里插入图片描述
早期的研究基本是基于部件模型(如Pictorial Structures)仅能建模身体局部关系,无法全局推理整体姿态 。例如,遮挡的关节位置需通过其他可见部位推测,但传统模型缺乏这种整体关联能力。为保持推理效率,一些模型采用树状结构拓扑,仅建模相邻关节的约束关系,忽视远距离关节的相互作用(如头与脚的关联)。另外,传统方法多将姿态估计视为分类问题,生成离散的姿态类别,难以实现连续空间中的高精度定位。
2012年AlexNet在ImageNet上的成功验证了深度神经网络(DNN)在图像分类任务中的潜力 。此后,DNN逐步扩展至目标检测(如R-CNN)和定位任务,但姿态估计尚未被充分探索 。
作者利用深度神经网络来进行人体姿态评估,将姿态估计视为一个联合回归问题。通过全卷积网络(如AlexNet)提取整图特征,可隐式学习关节间的空间依赖关系。另外,作者提出级联的方法来对关节点位置进行多次修正以提高精准率。

DeepPose

归一化

人体在图像中的尺度差异(如近景全身像与远景小尺寸人像)会导致关节点绝对坐标的数值范围差异巨大。通过边界框归一化,将关节点坐标转换为相对于人体边界框中心的比例值,可统一不同尺度下的坐标分布,使模型无需适应绝对像素值的变化,专注于学习姿态的空间关系。直接回归关节点绝对坐标需要模型同时学习空间位置和尺度变换,而归一化将问题简化为相对位置回归,归一化后的坐标仅需预测相对偏移量,模型更易收敛。另外,归一化后的数据分布更均匀,梯度下降过程中参数的更新方向更稳定,可有避免止训练时梯度爆炸问题。
用边框b对于图像进行归一化:
在这里插入图片描述
其中, y i {\mathbf{y}}_{i} yi 表示第 i i i 个关节在图像中的绝对坐标,具体为 ( x i , y i ) (x_i,y_i) (xi,yi);
b b b 是边框信息,定义为 b = ( b c , b w , b h ) b=(b_c,b_w,b_h) b=(bc,bw,bh), b c b_c bc 是边界框的中心坐标 ( b c x , b c y ) (b_{cx},b_{cy}) (bcx,bcy), b w b_w bw b h b_h bh 是边框的宽和高。

按照上面的公式可以将关节点的坐标转化为相对坐标,相对坐标在[-0.5,0.5]范围内,实现中也可加上0.5,归一化到[0,1]。

网络结构

作者将姿态估计视为回归问题,并用深度神经网络来预测关节点位置。
在这里插入图片描述
上图展示了DeepPose的总体结构:左边是初始阶段,粗略预测全局所有的关节点位置,其中蓝色是卷积层,绿色是全连接层,池化层和归一层没有需要学习的参数,图中没有展示。图中右边是精细化级联网络,其结构与初始阶段的网络完全一致,但每一级的网络参数是独立的,精细化级联网络对上一级预测的关节点位置进行修正,得到更准确的位置。
在初始阶段(Initial Stage),模型通过归一化人体边界框坐标构建尺度不变的输入,利用卷积网络直接回归所有关节点的坐标;在后续级联阶段(Cascade),模型基于初始预测结果对局部图像区域进行精细化裁剪,通过多层级联DNN逐步修正关节点位移量,最终输出精确的关节点位置。
下面分别介绍初始网络和精细化计量网络的具体细节:

初始网络(粗略估计所有关节点位置)

用 C 表示卷积层,用LRN表示局部响应标准化层,用P 表示池化层,用 F 表示全连接层。只有C 层和F 层包含可学习的参数,而其余的是无参数的。
在这里插入图片描述

对于 C 层,尺寸定义为宽度×高度×深度,其中前两个维度具有空间意义,而深度定义了滤波器的数量。如果我们将每层的大小写在括号中,那么网络可以简洁地描述为 C ( 55 × 55 × 96 ) − L R N − P − C ( 27 × 27 × 256 ) − L R N − P − C ( 13 × 13 × 384 ) − C ( 13 × 13 × 384 ) − C ( 13 × 13 × 256 ) − P − F ( 4096 ) − F ( 4096 ) C\left( {{55} \times {55} \times {96}}\right) - {LRN} - P - C\left( {{27} \times {27} \times {256}}\right) -{LRN} - P - C\left( {{13} \times {13} \times {384}}\right) - C\left( {{13} \times {13} \times {384}}\right) -C\left( {{13} \times {13} \times {256}}\right) - P - F\left( {4096}\right) - F\left( {4096}\right) C(55×55×96)LRNPC(27×27×256)LRNPC(13×13×384)C(13×13×384)C(13×13×256)PF(4096)F(4096)
前两个C层的滤波器大小为 11 × 11 11\times 11 11×11 5 × 5 5\times 5 5×5,其余三个层的大小为 3 × 3 3\times 3 3×3
池化操作在三层之后应用,尽管分辨率降低,但有助于提高性能。
网络的输入是 220 × 220 220\times 220 220×220的图像,通过步幅为4的方式输入网络,记人体关键点个数为 k k k,则初始网络的输出为 2 k 2k 2k 维向量。
网络的结构可以替换成其他网络,文章用的是AlexNet,还可替换成resent等其他网络。

损失函数
不想AlexNet那样使用分类损失,而是在最后一层网络层上训练线性回归,通过最小化预测值与真实姿态向量之间的 L 2 L_2 L2 距离来预测姿态向量。
先将训练集 D D D 进行归一化:
在这里插入图片描述
最优网络参数的 L 2 L_2 L2 损失函数为:
在这里插入图片描述
为了清晰起见,公式写出对各个关节的优化。需要注意的是,即使某些图像中并非所有关节都被标注(存在遮挡或缺失时),上述目标函数仍然可以使用,只是求和中的相应项将被省略。

精细化级联网络(分别修正每个关节点的位置)

上一小节的初始网络是以整个图像作为输入,要预测图像中所有的关节点(单人)。但此网络在观察细节方面的能力有限——它学习的是在粗尺度上捕捉姿态属性的滤波器,这些滤波器不足以精确定位人体关节。为了实现更高的精度,作者提出级级联的姿态回归器。
在这里插入图片描述
在第一阶段,级联从估计初始姿态开始,如上一节所述。在后续阶段,额外的深度神经网络(DNN)回归器被训练来预测关节位置从前一阶段到真实位置的位移。因此,每个后续阶段可以被视为对当前预测姿态的细化。

每个后续阶段都以上一阶段预测出或修正后的关节位置为中心从原始高分辨率图像中裁剪出子图像,并在此子图像上应用该关节的姿态位移回归器。通过这种方式,后续的姿态回归器可以看到更高分辨率的图像,从而学习到更精细尺度的特征,最终实现更高的精度。

级联的所有阶段的网络结构都完全相同,但学习的参数不同。
对于总共 S S S个级联阶段(包括初始阶段)中的第 s ∈ { 1 , … , S } s \in \{ 1,\ldots ,S\} s{1,,S}阶段,用 θ s {\theta }_{s} θs表示学习到的网络参数。姿态位移回归器读取 ψ ( x ; θ s ) \psi \left( {x;{\theta }_{s}}\right) ψ(x;θs)。为了细化给定的关节位置 y i {\mathbf{y}}_{i} yi ,考虑一个关节边界框 b i {b}_{i} bi,该边界框捕获围绕 y i : b i ( y ; σ ) = ( y i , σ diam ⁡ ( y ) , σ diam ⁡ ( y ) ) {\mathbf{y}}_{i} : {b}_{i}\left( {\mathbf{y};\sigma }\right) = \left( {{\mathbf{y}}_{i},\sigma \operatorname{diam}\left( \mathbf{y}\right) ,\sigma \operatorname{diam}\left( \mathbf{y}\right) }\right) yi:bi(y;σ)=(yi,σdiam(y),σdiam(y))的子图像,其中心为第 i i i个关节,尺寸为姿态直径按 σ \sigma σ缩放。姿态的直径 diam ⁡ ( y ) \operatorname{diam}\left( \mathbf{y}\right) diam(y)定义为人体躯干上相对关节之间的距离,例如左肩和右髋,具体取决于具体的姿态定义和数据集。

那么,在阶段 s = 1 s = 1 s=1中,从边界框 b 0 {b}^{0} b0开始,该边界框要么包围整个图像,要么是通过人体检测器获得的,则初始姿态为:
在这里插入图片描述
在每个后续阶段 s ≥ 2 s \geq 2 s2中,对于所有关节 i ∈ { 1 , … , k } i \in \{ 1,\ldots ,k\} i{1,,k},首先通过在前一阶段(s - 1)定义的子图像 b i ( s − 1 ) {b}_{i}^{\left( s - 1\right) } bi(s1)上应用回归器,回归到一个细化位移 y i s − y i ( s − 1 ) {\mathbf{y}}_{i}^{s} -{\mathbf{y}}_{i}^{\left( s - 1\right) } yisyi(s1)。然后,估计新的关节框 b i s {b}_{i}^{s} bis
在这里插入图片描述
s ≥ 2 s \geq 2 s2 阶段中,训练方式与初始阶段基本相同,只是每个关节点使用不同的边界框来进行归一化。

疑问与解决

Q:初始阶段是对所有关节点进行粗略的预测,输出是 2 k 2k 2k维向量,而后续的级联精细化阶段只需要 2 2 2维向量表示对关节点的修正信息,那为什么初始阶段和后续级联阶段的网络结构完全一致?
A:初始阶段和后续级联阶段所需的输出的维度不一样,级联阶段网络仍输出 2 k 2k 2k维向量,但仅使用当前处理的关节点的修正量(Δx, Δy),其他维度被忽略。这种设计通过动态选择输出通道实现功能适配。例如,处理右肘关节点,级联阶段仅提取输出向量中对应右肘的Δx和Δy,其余维度不参与计算。训练时,每个级联阶段仅对当前处理的关键点的两个输出维度(Δx, Δy)计算损失,其他维度在损失函数中被赋予权重0,从而避免无关维度的干扰

代码实践

在实现中,骨干网络是利用图像分类网络,如AlexNet、ResNet等,下面是以ResNet为骨干网络进行实现的DeepPose:

  • 骨干网络:ResNet,最后一层全连接层改动,使其输出 2 k 2k 2k维向量
def create_deep_pose_model(num_keypoints: int) -> nn.Module:# 加载预训练的ResNet-50模型,使用ImageNet数据集上的预训练权重res50 = resnet50(weights=ResNet50_Weights.IMAGENET1K_V2)# 获取原始ResNet-50模型中全连接层的输入特征数in_features = res50.fc.in_features# 替换原有的全连接层为一个新的线性层,输出大小为num_keypoints*2,# 因为每个关键点需要两个坐标值(x,y)res50.fc = nn.Linear(in_features=in_features, out_features=num_keypoints * 2)return res50  # 返回修改后的模型
  • 训练
import os  import torch  
import torch.amp  
from torch.utils.data import DataLoader  # 数据加载器
from torch.utils.tensorboard import SummaryWriter  # TensorBoard写入器,用于记录训练过程import transforms  # 自定义的数据变换模块
from model import create_deep_pose_model  # 自定义函数,用于创建DeepPose模型
from datasets import WFLWDataset  # 自定义数据集类
from train_utils.train_eval_utils import train_one_epoch, evaluate  # 训练和评估的实用函数# 定义获取命令行参数的解析器函数
def get_args_parser(add_help=True):import argparse  # 命令行选项、参数和子命令解析器parser = argparse.ArgumentParser(description="PyTorch DeepPose Training", add_help=add_help)  # 创建解析器实例parser.add_argument("--dataset_dir", type=str, default="/home/wz/datasets/WFLW", help="WFLW dataset directory")  # 数据集目录parser.add_argument("--device", type=str, default="cuda:0", help="training device, e.g. cpu, cuda:0")  # 训练设备parser.add_argument("--save_weights_dir", type=str, default="./weights", help="save dir for model weights")  # 模型权重保存目录parser.add_argument("--save_freq", type=int, default=10, help="save frequency for weights and generated imgs")  # 权重保存频率parser.add_argument("--eval_freq", type=int, default=5, help="evaluate frequency")  # 评估频率parser.add_argument('--img_hw', default=[256, 256], nargs='+', type=int, help='training image size[h, w]')  # 训练图像尺寸parser.add_argument("--epochs", type=int, default=210, help="number of epochs of training")  # 训练周期数parser.add_argument("--batch_size", type=int, default=32, help="size of the batches")  # 批次大小parser.add_argument("--num_workers", type=int, default=8, help="number of workers, default: 8")  # 数据加载线程数parser.add_argument("--num_keypoints", type=int, default=98, help="number of keypoints")  # 关键点数量parser.add_argument("--lr", type=float, default=5e-4, help="Adam: learning rate")  # 学习率parser.add_argument('--lr_steps', default=[170, 200], nargs='+', type=int, help='decrease lr every step-size epochs')  # 学习率衰减步骤parser.add_argument("--warmup_epoch", type=int, default=10, help="number of warmup epoch for training")  # 预热轮数parser.add_argument('--resume', default='', type=str, help='resume from checkpoint')  # 从检查点恢复训练parser.add_argument('--test_only', action="store_true", help='Only test the model')  # 仅测试模式return parser# 主函数
def main(args):torch.manual_seed(1234)  # 固定随机种子以确保结果可复现dataset_dir = args.dataset_dir  # 数据集目录save_weights_dir = args.save_weights_dir  # 权重保存目录save_freq = args.save_freq  # 权重保存频率eval_freq = args.eval_freq  # 评估频率num_keypoints = args.num_keypoints  # 关键点数量num_workers = args.num_workers  # 数据加载线程数epochs = args.epochs  # 训练周期数bs = args.batch_size  # 批次大小start_epoch = 0  # 初始训练轮次img_hw = args.img_hw  # 图像尺寸os.makedirs(save_weights_dir, exist_ok=True)  # 创建保存权重的目录if "cuda" in args.device and not torch.cuda.is_available():  # 如果指定使用GPU但不可用,则回退到CPUdevice = torch.device("cpu")else:device = torch.device(args.device)print(f"using device: {device} for training.")  # 打印使用的设备信息# tensorboard writer,用于记录训练过程中的信息tb_writer = SummaryWriter()# 创建DeepPose模型实例,并将其移动到指定设备model = create_deep_pose_model(num_keypoints)model.to(device)# 配置数据集和数据加载器data_transform = {"train": transforms.Compose([  # 训练数据变换transforms.AffineTransform(scale_factor=(0.65, 1.35), rotate=45, shift_factor=0.15, fixed_size=img_hw),transforms.RandomHorizontalFlip(0.5),transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])]),"val": transforms.Compose([  # 验证数据变换transforms.AffineTransform(scale_prob=0., rotate_prob=0., shift_prob=0., fixed_size=img_hw),transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])}train_dataset = WFLWDataset(root=dataset_dir, train=True, transforms=data_transform["train"])  # 创建训练数据集val_dataset = WFLWDataset(root=dataset_dir, train=False, transforms=data_transform["val"])  # 创建验证数据集train_loader = DataLoader(train_dataset, batch_size=bs, shuffle=True, pin_memory=True, num_workers=num_workers, collate_fn=WFLWDataset.collate_fn, persistent_workers=True)  # 创建训练数据加载器val_loader = DataLoader(val_dataset, batch_size=bs, shuffle=False, pin_memory=True, num_workers=num_workers, collate_fn=WFLWDataset.collate_fn, persistent_workers=True)  # 创建验证数据加载器# 定义优化器optimizer = torch.optim.Adam(model.parameters(), lr=args.lr)# 定义学习率调度器warmup_scheduler = torch.optim.lr_scheduler.LinearLR(optimizer=optimizer, start_factor=0.01, end_factor=1.0, total_iters=len(train_loader) * args.warmup_epoch)multi_step_scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer=optimizer, milestones=[len(train_loader) * i for i in args.lr_steps], gamma=0.1)lr_scheduler = torch.optim.lr_scheduler.ChainedScheduler([warmup_scheduler, multi_step_scheduler])if args.resume:  # 如果有恢复训练的检查点assert os.path.exists(args.resume)checkpoint = torch.load(args.resume, map_location='cpu')model.load_state_dict(checkpoint['model'])optimizer.load_state_dict(checkpoint['optimizer'])lr_scheduler.load_state_dict(checkpoint['lr_scheduler'])start_epoch = checkpoint['epoch'] + 1print("the training process from epoch{}...".format(start_epoch))if args.test_only:  # 如果仅进行测试evaluate(model=model, epoch=start_epoch, val_loader=val_loader, device=device, tb_writer=tb_writer, affine_points_torch_func=transforms.affine_points_torch, num_keypoints=num_keypoints, img_hw=img_hw)returnfor epoch in range(start_epoch, epochs):  # 开始训练循环# 训练一个周期train_one_epoch(model=model, epoch=epoch, train_loader=train_loader, device=device, optimizer=optimizer, lr_scheduler=lr_scheduler, tb_writer=tb_writer, num_keypoints=num_keypoints, img_hw=img_hw)# 每隔一定周期进行评估if epoch % eval_freq == 0 or epoch == args.epochs - 1:evaluate(model=model, epoch=epoch, val_loader=val_loader, device=device, tb_writer=tb_writer, affine_points_torch_func=transforms.affine_points_torch, num_keypoints=num_keypoints, img_hw=img_hw)# 按照设定的频率保存模型权重if epoch % save_freq == 0 or epoch == args.epochs - 1:save_files = {'model': model.state_dict(), 'optimizer': optimizer.state_dict(), 'lr_scheduler': lr_scheduler.state_dict(), 'epoch': epoch}torch.save(save_files, os.path.join(save_weights_dir, f"model_weights_{epoch}.pth"))if __name__ == '__main__':args = get_args_parser().parse_args()  # 解析命令行参数main(args)  # 调用主函数

测试人脸检测:
在这里插入图片描述
预测结果:
在这里插入图片描述

总结

DeepPose作为首个将深度神经网络引入人体姿态估计的经典框架,通过级联回归结构实现了单人关键点的高效检测。其核心流程分为两个阶段:在初始阶段(Initial Stage),模型通过归一化人体边界框坐标构建尺度不变的输入,利用卷积网络直接回归输入图像中所有关节点的位置;在后续级联阶段(Cascade),模型基于上一阶段预测结果对局部图像区域进行精细化裁剪,通过多层级联DNN逐步修正关节点偏移量,最终输出精确的关节点位置。这种端到端的回归方法简化了传统流程,但存在对局部上下文细节捕捉不足的局限性,且依赖高分辨率输入导致计算成本较高。未来研究可结合多尺度特征融合提升遮挡场景下的鲁棒性,或引入轻量化设计优化实时性,同时探索与多模态数据(如骨骼几何关系)的协同建模以突破单帧图像的空间约束。

相关文章:

【第二十五周】:DeepPose:通过深度神经网络实现人体姿态估计

DeepPose 摘要Abstract文章信息引言DeepPose归一化网络结构初始网络(粗略估计所有关节点位置)精细化级联网络(分别修正每个关节点的位置) 疑问与解决代码实践总结 摘要 这篇博客介绍了DeepPose,这是首个基于深度神经网…...

SVN 简介

SVN 简介 引言 版本控制系统(Version Control System,VCS)是软件开发过程中不可或缺的工具之一。它能够帮助开发者管理代码的版本,追踪代码变更,协同工作,以及确保代码的稳定性和安全性。Subversion(简称SVN)是一种流行的版本控制系统,本文将为您详细介绍SVN的基本概…...

ARM Linux LCD上实时预览摄像头画面

文章目录 1、前言2、环境介绍3、步骤4、应用程序编写4.1、lcd初始化4.2、摄像头初始化4.3、jpeg解码4.4、开启摄像头4.5、完整的程序如下 5、测试5.1、编译应用程序5.2、运行应用程序 6、总结 1、前言 本次应用程序主要针对支持MJPEG格式输出的UVC摄像头。 2、环境介绍 rk35…...

基于DeepSeek 的图生文最新算法 VLM-R1

目录 一、算法介绍 二 算法部署 三 模型下载 四 算法测试 五 可视化脚本 一、算法介绍 VLM-R1:稳定且可通用的 R1 风格大型视觉语言模型 自从 Deepseek-R1 推出以来,出现了许多专注于复制和改进它的作品。在这个项目中,我们提出了 VLM-R1,一种稳定且可通用的 R1 风格…...

《论软件测试中缺陷管理及其应用》审题技巧 - 系统架构设计师

论软件测试中缺陷管理及其应用写作框架 一、考点概述 本论题“论软件测试中缺陷管理及其应用”主要考查的是软件测试领域中的缺陷管理相关知识与实践应用。论题涵盖了以下几个核心内容: 首先,需要理解软件缺陷的基本概念,即软件中存在的破坏正常运行能力的问题、错误或隐…...

MacOS本地部署Deepseek,不联网也可以使用AI,保护隐私

苹果笔记本本地部署deepseek主要用到Ollama与open-webui 1. 安装Ollama “Ollama” 是一个轻量级的 AI 模型运行时环境(runtime),旨在简化在本地部署和使用大语言模型(LLM)的过程。它由 Vicarious 公司开发&#xff…...

python爬虫:pyspider的详细使用

文章目录 一、pyspider介绍1.1 核心概念1.2 与其他爬虫框架的比较二、 安装 pyspider三、编写爬虫脚本四、运行和监控爬虫4.1 启动爬虫4.2 监控任务状态4.3 任务管理五、高级功能5.1 分布式爬取5.2 JavaScript 渲染5.3 数据存储5.4 定时任务5.5 错误处理和重试机制六、示例:采…...

3-5 WPS JS宏 工作表的移动与复制学习笔记

************************************************************************************************************** 点击进入 -我要自学网-国内领先的专业视频教程学习网站 *******************************************************************************************…...

Sqlserver安全篇之_启用TLS即配置SQL Server 数据库引擎以加密连接

官方文档 https://learn.microsoft.com/zh-cn/sql/database-engine/configure-windows/configure-sql-server-encryption?viewsql-server-ver16 https://learn.microsoft.com/zh-cn/sql/database-engine/configure-windows/manage-certificates?viewsql-server-ver15&pre…...

删除变慢问题

问题&#xff1a; 有一个场景&#xff0c;每天都会删除数据&#xff0c;SQL为delete from xxx where record_date < DATE_SUB(now(), INTERVAL ? DAY) limit 1000 &#xff0c;一直循环执行&#xff0c;当执行到最后一次满足条件的时候&#xff0c;就会很慢 原理分析 索引与…...

创建一个MCP服务器,并在Cline中使用,增强自定义功能。

MCP介绍 MCP 是一个开放协议&#xff0c;它标准化了应用程序如何向LLMs提供上下文。可以将 MCP 视为 AI 应用程序的 USB-C 端口。正如 USB-C 提供了一种标准化的方法来将您的设备连接到各种外围设备和配件一样&#xff0c;MCP 提供了一种标准化的方法来将 AI 模型连接到不同的…...

游戏引擎学习第131天

仓库:https://gitee.com/mrxiao_com/2d_game_3 运行游戏并识别我们的小问题 今天的工作重点是对游戏引擎进行架构优化&#xff0c;特别是针对渲染和多线程的部分。目前&#xff0c;我们的目标是让地面块在独立线程上进行渲染&#xff0c;以提高性能。在此过程中&#xff0c;我…...

人大金仓国产数据库与PostgreSQL

一、简介 在前面项目中&#xff0c;我们使用若依前后端分离整合人大金仓&#xff0c;在后续开发过程中&#xff0c;我们经常因为各种”不适配“问题&#xff0c;但可以感觉得到大部分问题&#xff0c;将人大金仓视为postgreSQL就能去解决大部分问题。据了解&#xff0c;Kingba…...

《认知·策略·跃迁:新能源汽车工程师的深度学习系统构建指南》

--- ## 前言&#xff1a;为什么传统学习法正在杀死你的竞争力&#xff1f; 在新能源汽车领域&#xff0c;我们正经历着每18个月知识体系更新迭代的指数级变革。当磷酸铁锂电池能量密度刚突破200Wh/kg时&#xff0c;固态电池已进入量产倒计时&#xff1b;当自动驾驶还在L2级徘…...

存贮论模型案例与Matlab实现

摘要&#xff1a;本文结合存贮论确定性模型&#xff0c;详细解析经济订购批量&#xff08;EOQ&#xff09;、允许缺货生产批量等核心模型&#xff0c;并通过商品库存管理、生产计划等实际案例&#xff0c;配合Matlab代码实现&#xff0c;展示模型求解过程。涵盖公式推导、参数优…...

MacBook Pro使用FFmpeg捕获摄像头与麦克风推流音视频

FFmpeg查看macos系统音视频设备列表 ffmpeg -f avfoundation -list_devices true -i "" 使用摄像头及麦克风同时推送音频及视频流: ffmpeg -f avfoundation -pixel_format yuyv422 -framerate 30 -i "0:1" -c:v libx264 -preset ultrafast -b:v 1000k -…...

linux 内核dumpstack定位使用举例说明

1,在 Linux 内核中&#xff0c;当你需要定位问题时&#xff0c;dump_stack() 函数是一个非常有用的工具&#xff0c;那么什么时候使用dump_stack&#xff0c;怎么使用dump_stack呢 通常使用的是前者&#xff09;函数通常在以下情况下被用来帮助定位问题&#xff1a; 调试内核代…...

360个人版和企业版的区别

功能方面 管理能力 个人版&#xff1a;主要用于单台设备的安全防护&#xff0c;只能在单独的电脑上进行安装使用&#xff0c;无集中管理和监控其他设备的功能。企业版&#xff1a;可批量管理大量电脑&#xff0c;如公司的十台、百台甚至千台电脑。管理员能通过管理控制台对所有…...

服务器迁移记录【腾讯云-->阿里云】

准备工作 压缩/root /usr/local/nginx /data三个目录到zip&#xff0c;并下载到本地。 zip root.zip /root zip nginx.zip /usr/local/nginx zip data.zip /datasz root.zip sz nginx.zip sz data.zip连接mysql数据库&#xff0c;导出数据库结构与数据到dzs_mysql.sql 安装l…...

APISIX Dashboard上的配置操作

文章目录 登录配置路由配置消费者创建后端服务项目配置上游再创建一个路由测试 登录 http://192.168.10.101:9000/user/login?redirect%2Fdashboard 根据docker 容器里的指定端口&#xff1a; 配置路由 通过apisix 的API管理接口来创建&#xff08;此路由&#xff0c;直接…...

【vue-echarts】——05.柱状图

文章目录 一、柱状图基本设置1.实现代码2.结果展示二、柱状图效果实现11.代码实现2.结果展示三、柱状图效果实现21.代码实现2.结果展示一、柱状图基本设置 柱状图:一种图表类型,因为构成是由一根一根类似柱子的数据条组合而成的坐标平面,所以命名为柱状 图。主要是用来反应对…...

计算机毕业设计SpringBoot+Vue.js人力资源管理系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

腾讯云扩容记录

腾讯云扩容&#xff1a; sudo yum install -y cloud-utils-growpart 安装扩容工具 sudo file -s /dev/vda1 有数据 sudo LC_ALLen_US.UTF-8 growpart /dev/vda 1 sudo resize2fs /dev/vda1 df -Th 完毕 以下是对执行的命令的详细解释以及背后的原理&#xff1a; 1. 安装 cloud…...

Cherry Studio + 火山引擎 构建个人AI智能知识库

&#x1f349;在信息化时代&#xff0c;个人知识库的构建对于提高工作效率、知识管理和信息提取尤为重要。尤其是当这些知识库能结合人工智能来智能化地整理、分类和管理数据时&#xff0c;效果更为显著。我最近尝试通过 Cherry Studio 和 火山引擎 来搭建个人智能知识库&#…...

RocketMQ启动教程

环境是ubuntu&#xff0c;建议ubuntu&#xff0c;因为有root用户权限够大&#xff0c;不像windows十分费劲&#xff0c;跑Docker总是遇到权限问题&#xff0c;但是ubuntu的话就很轻松了&#xff0c;整个流程非常顺利 文章目录 1.Docker安装NameServer2.安装broker3.Docker安装 …...

完美解锁便捷版!

视频文件的种类繁多&#xff0c;包括常见的格式如MP4、AVI、MOV、MKV等。随着视频技术的发展&#xff0c;新的编码格式如HEVC&#xff08;H.265&#xff09;和AV1也逐渐被广泛应用&#xff1b;视频文件通常会经过压缩&#xff0c;并且每种格式都有其独特的编码方式和特性&#…...

JAVA SE 包装类和泛型

文章目录 &#x1f4d5;1. 包装类✏️1.1 基本数据类型和对应的包装类✏️1.2 装箱和拆箱✏️1.3 自动装箱和自动拆箱 &#x1f4d5;2. 泛型✏️2.1 泛型的语法✏️2.2 泛型类的使用✏️2.3 裸类型(Raw Type)✏️2.4 擦除机制✏️2.5 泛型的上界✏️2.6 泛型方法✏️2.7 通配符…...

人工智能AI在汽车设计领域的应用探索

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 简单&#xff0c;单纯&#xff0c;喜欢独处&#xff0c;独来独往&#xff0c;不易合同频过着接地气的生活…...

driver中为什么要使用非阻塞赋值

1. 模拟硬件时序行为 实际硬件行为&#xff1a;DUT的输入信号通常在时钟边沿被采样。Driver需要确保信号的更新与时钟同步&#xff0c;而非阻塞赋值的延迟更新特性&#xff08;在时间步结束时统一生效&#xff09;能够准确模拟寄存器的行为。 示例&#xff1a; always (posedg…...

Vue3国际化开发实战:i18n-Ally + vue-i18n@next高效配置教程,项目中文显示

本文详解 Vue3 国际化开发全流程&#xff1a;从安装 vue-i18nnext 到配置多语言文件&#xff08;JSON/YAML&#xff09;&#xff0c;结合 i18n-Ally 插件实现高效翻译管理。重点涵盖&#xff1a; 工程配置&#xff1a;创建 i18n 实例、模块化语言文件结构&#xff08;支持命名…...