网上搜了一圈,关于CenterNet 训练关键点数据的资料非常少,而且讲得都很模糊,没法解决实际问题,也未说明细节和要素。在踏坑许久之后,才跑通CenterNet的关键点训练,于是记录一下踏坑历程,以备后忘
cuda11.0
torch1.7.1
torchvision0.8.2
numpy 1.19.2
这是我的环境版本,不是非得这个版本
参考我的另一篇文章
COCO KeyPoints关键点数据集准备
我的数据集 的类别是1类, 关键点是3个
CenterNet/src/lib/datasets/datasets 目录, coco_hp.py是原来的coco keypoints官方数据集的数据集代码, 我们从这文件copy一份, 命名为handKeyPoints.py
修改其中内容, 先看下对比图
修改代码
num_classes = 1 #类别1num_joints = 3 #关键点个数3default_resolution = [512, 512]mean = np.array([0.636623, 0.642096, 0.649946],dtype=np.float32).reshape(1, 1, 3) #数据集计算出的meanstd = np.array([0.318729, 0.316616, 0.297199], #数据集计算出的stddtype=np.float32).reshape(1, 1, 3)flip_idx = [[1, 2]] #图像翻转,这个我也不懂, 就照着官方的写了一个,跟实际的关键点数对应def __init__(self, opt, split):super(HandKeyPoints, self).__init__()self.edges = [[0, 1], [1, 2]]self.acc_idxs = [1, 2, 3]#数据集文件夹 目录 data/HandCupKeyPoints , 这个文件夹里面是annotations、test2017 、train2017三个文件夹self.data_dir = os.path.join(opt.data_dir, 'HandCupKeyPoints') if split == 'val': #这里我们的是test而不是val,所以改一下split = 'test'self.img_dir = os.path.join(self.data_dir, '{}2017'.format(split))if split == 'test':self.annot_path = os.path.join(self.data_dir, 'annotations', 'test.json') #直接指定文件名else:self.annot_path = os.path.join(self.data_dir, 'annotations', 'train.json') #直接指定文件名
这个文件就修改完毕, 其他不用动
对比如下:
我这里大小写不一致,不用管, dataset_factory 字段 key 就是 刚刚创建的handKeyPoints.py 的前缀 , value就是 文件里 class 的类名
第15行 修改默认数据集为 handKeyPoints 数据集
第323行
opt.flip_idx = False#dataset.flip_idxopt.heads = {'hm': opt.num_classes, 'wh': 2, 'hps': 34} #17个点的x、y 共 34个值
修改为:
# opt.flip_idx = Falseopt.flip_idx = dataset.flip_idxopt.heads = {'hm': opt.num_classes, 'wh': 2, 'hps': 6} #3个点的x、y 共 6个值
第345行
'multi_pose': {'default_resolution': [512, 512], 'num_classes': 1, 'mean': [0.408, 0.447, 0.470], 'std': [0.289, 0.274, 0.278], #数据集的 mean std'dataset': 'coco_hp', 'num_joints': 17, #关键点个数 17个'flip_idx': [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12], [13, 14], [15, 16]]}, #flip_idx
修改为 自己数据集的 mean 和std
flip_idx 修改为相应的
'multi_pose': {'default_resolution': [512, 512], 'num_classes': 1, 'mean': [0.614, 0.612, 0.622], 'std': [0.348, 0.347, 0.329], #数据集的 mean std'dataset': 'handKeyPoints', 'num_joints': 3, #关键点个数 3个'flip_idx': [[1, 2]]}, #flip_idx 看情况写
编写脚本train.sh, 内容
python main.py multi_pose --arch dla_34 --dataset handKeyPoints --lr 0.25e-4 --batch_size 16 --gpus 0 --load_model ../models/multi_pose_dla_3x.pth
学习率自定义设置,
–batch_size 依据GPU显存大小, 如果CUDA out of memery 就改小点
–load_model …/models/multi_pose_dla_3x.pth 这个是官方训练好的模型,
报一堆警告,不用管, 如下:
输出训练过程日志
训练的结果保存在exp目录下
模型文件如下:
这样我们就得到了 训练好的模型,
我的数据集较少,不知道是由于标注质量的问题还是学习率的问题,最终验证损失loss=2.7左右时不再下降。
增加handKeyPoints 数据集类别判断
第45行增加
elif num_classes == 1 or dataset == 'handKeyPoints': #增加自定义的handKeyPoints类别self.names = handKeyPoints_class #类别名称self.names = ['p'] #类别名称self.num_class = 1 #类别数self.num_joints = 3 #关键点数量self.edges = [[0, 1], [1, 2]] #关键点连接关系self.ec = [(255, 0, 0), (0, 0, 255), (255, 0, 0)] #颜色self.colors_hp = [(255, 0, 255), (255, 0, 0), (0, 0, 255)]
第467行增加
handKeyPoints_class = ['hand']
第85行
dets[:, :, :4] *= self.opt.down_ratio #bbox 的4个值 dets[:, :, 5:39] *= self.opt.down_ratioemmina.mo #5~39 是17个关键点的坐标34个值
这里修改为:
dets[:, :, :4] *= self.opt.down_ratio #bbox 的4个值 dets[:, :, 5:11] *= self.opt.down_ratioemmina.mo #5~11 是3个关键点的坐标6个值
第101行
debugger.add_coco_bbox(bbox[:4], 0, bbox[4], img_id='multi_pose') #bbox 的4个值 debugger.add_coco_hp(bbox[5:39], img_id='multi_pose') #5~39 是17个关键点的坐标34个值
修改为
debugger.add_coco_bbox(bbox[:4], 0, bbox[4], img_id='multi_pose') #bbox 的4个值 debugger.add_coco_hp(bbox[5:11], img_id='multi_pose') #5~11 是3个关键点的坐标6个值
编写测试脚本test_keyPoints.sh, 内容如下:
python demo.py multi_pose --demo ../images/16.jpg --load_model ../models/model_best_keypoints.pth
模型用的就是上述训练好的模型
识别出了手臂, 置信度为0.9
本文是西门子开放式TCP通信的第2篇,上一篇我们讲了使用西门子1200PLC作为TCP服务器的程序编写,可以点击下方链接阅读:【公众号dotNet工控上位机:thinger_swj】基于Socket访问西门子PLC系列教程(一)在完成上述步骤后,接下来就是编写上位机软件与PLC之间进行通信。上位机UI界面设计如下图所示:从上图可以看出...
我有一个大型数据集,列出了在全国不同地区销售的竞争对手产品。我希望通过使用这些新数据帧名称中的列值的迭代过程,根据区域将该数据帧分成几个其他区域,以便我可以分别处理每个数据帧-例如根据价格对每个地区的信息进行排序,以了解每个地区的市场情况。我给出了以下数据的简化版本:Competitor Region ProductA Product...
作为一名IT从业者,我来回答一下这个问题。首先,对于具有Java编程基础的人来说,学习Python的初期并不会遇到太大的障碍,但是要结合自己的发展规划来制定学习规划,尤其要重视学习方向的选择。Java与Python都是比较典型的全场景编程语言,相比于Java语言来说,当前Python语言在大数据、人工智能领域的应用更为广泛一些,而且大...
这段时间通过学习相关的知识,最大的变化就是看待事物更加喜欢去了解事物后面的本质,碰到问题后解决问题思路也发生了改变。举个具体的例子,我在学习数据分析,将来会考虑从事这方面的工作,需要掌握的相关专业知识这个问题暂且按下不表,那哪些具体的问题是我需要了解的呢,以下简单罗列:1、了解数据分析师这个岗位在各个地区的需求情况?2、数据分析师的薪...
这一节将开始学习python的一个核心数据分析支持库---pandas,它是python数据分析实践与实战的必备高级工具。对于使用 Python 进行数据分析来说,pandas 几乎是无人不知,无人不晓的。今天,我们就来认识认识数据分析界鼎鼎大名的 pandas。目录一. pandas主要数据结构 SeriesDataFrame二...
【从零开始的ROS四轴机械臂控制(五)】八、运动控制节点1.定义服务GoToPosition.srv2.修改CMakeLists.txt3.修改package.xml4.构建包5.arm_mover节点代码6.Arm Mover的启动和互动(1)修改gazebo.launch(2)测试arm_mover服务...
Alt+Shift+H 查看整个代码文件的修改历史记录 Ctrl+Shift+H 只查看被选中代码内容的修改历史记录(更具针对性)...
第一种情况修改下面这个位置 第二种情况修改 如果还是不行就把模式改成hash...
锁的类型:(1) 共享锁:共享锁用于所有的只读数据操作.(2) 修改锁:修改锁在修改操作的初始化阶段用来锁定可能要被修改的资源,这样可以避免使用共享锁造成的死锁现象(3) 独占锁:独占锁是为修改数据而保留的。它所锁定的资源,其他事务不能读取也不能修改。独占锁不能和其他锁兼容。(4) 架构锁结构锁分为结构修改锁(Sch-M)和结构稳定锁...
一.安装postgresql 本文仅以 redhat,postgresql9.4为例,使用yum方式进行介绍。 官网:http://www.postgresql.org/download/linux/redhat/ 1.下载postgresql的yum源 yum install http://yum.postgresql.org...