学习使用paddle来构造hrnet网络模型

1、首先阅读了hrnet的网络结构分析,了解到了网络构造如下:

参考博文姿态估计之2D人体姿态估计 - (HRNet)Deep High-Resolution Representation Learning for Human Pose Estimation(多家综合)-CSDN博客

最重要的就是这个图了:

在这里主要是注释自己对这个图的认识和理解:

在RGB图片(256*192*3)输入主干网络之前先经过了两次conv卷积网络(包含3*3的卷积层和归一层,激活函数relu),然后就来到了layer1(主要是改变了通道数,通过重复堆叠Bottleneck来实现),然后进行两个层次的特征处理,一个是向下进行二倍采样,一个是直接过来,这就形成了所谓的不同维度的特征信息,然后进行融合,因为它们的通道数并不相同,所以就需要进行下采样(down),和上采样(up),具体这两个网络结构也已经放出来了。然后就是将前面得到的不同维度的特征信息融合·,输入到下一层里面。按照这个流程做下去,到最后,也就是stage4的时候,进行最后一次的多维度的特征信息融合,然后输入到最后一个卷积里面,这个卷积主要是输出17个关键点的预测信息,所以可以看到那里是C17(17个通道)也相当于17个卷积核(1*1的)。

然后图片里面的

k3, s2, p1, 和 c64 通常是卷积层的超参数,它们分别代表:

k3:这通常指的是卷积核(kernel)的大小。k3 表示卷积核的大小为 3x3,即宽度和高度都是3。

s2:这是步长(stride)的参数。s2 表示卷积操作的步长为2。步长决定了卷积核在输入特征图上滑动时,每次移动的像素数量。

p1:这是填充(padding)的参数。p1 表示在输入特征图的边界周围填充1个像素。填充通常用于控制输出特征图的大小,以及确保在特征图的边缘信息不会被丢失。

c64:这指的是输出通道数(number of output channels)。c64 表示该卷积层有64个输出通道,即卷积操作会产生64个不同的特征图。

其中输出通道数C64是和卷积核相对应的,有多少个卷积核就有多少个输出通道。

我去学习,看了一哈paddledetection里面的,发现有使用paddle实现HRNet网络,于是我就打算进行复现,训练出自己想要的模型效果,

值得一提的是这个hrnetpostprocess的代码的实现,运用了中心点+尺度因子+热力图的关系,来改变固定预测关键点是整数值。

class HRNetPostProcess(object):def __init__(self, use_dark=True):self.use_dark = use_darkdef get_max_preds(self, heatmaps):'''get predictions from score maps
该类主要用于从热图(heatmaps)中获取预测的关键点坐标和对应的最大置信度Args:heatmaps: numpy.ndarray([batch_size, num_joints, height, width])heatmaps是一个四维数组  batch_size是批处理大小,num_joints是关键点的数量,height和width是热图的高度和宽度Returns:preds: numpy.ndarray([batch_size, num_joints, 2]), keypoints coordsmaxvals: numpy.ndarray([batch_size, num_joints, 2]), the maximum confidence of the keypoints输出:两个numpy数组,preds和maxvals。preds的形状为[batch_size, num_joints, 2],表示每个关键点的坐标;maxvals的形状也为[batch_size, num_joints, 1],表示每个关键点的最大置信度。'''assert isinstance(heatmaps,np.ndarray), 'heatmaps should be numpy.ndarray'assert heatmaps.ndim == 4, 'batch_images should be 4-ndim'#检查heatmaps是否是4维的batch_size = heatmaps.shape[0]num_joints = heatmaps.shape[1]width = heatmaps.shape[3]heatmaps_reshaped = heatmaps.reshape((batch_size, num_joints, -1))#代码重新整形heatmaps,使其从[batch_size, num_joints, height, width]变为[batch_size, num_joints, height*width]idx = np.argmax(heatmaps_reshaped, 2)#使用np.argmax获取每个位置的最大值的索引,这对应于每个关键点在热图中的位置。maxvals = np.amax(heatmaps_reshaped, 2)#使用np.amax获取每个位置的最大值,这对应于每个关键点的置信度。# 将maxvals和idx重新整形为[batch_size, num_joints, 1]maxvals = maxvals.reshape((batch_size, num_joints, 1))idx = idx.reshape((batch_size, num_joints, 1))preds = np.tile(idx, (1, 1, 2)).astype(np.float32)#使用np.tile复制idx的每一行和每一列,生成一个新的三维数组preds[:, :, 0] = (preds[:, :, 0]) % width #对这个新数组的第三列(即每个关键点的x坐标)进行模运算,以确保其值在[0, width)范围内preds[:, :, 1] = np.floor((preds[:, :, 1]) / width)#对新数组的第二列(即每个关键点的y坐标)进行整除运算,然后取整,以获取每个关键点的y坐标。pred_mask = np.tile(np.greater(maxvals, 0.0), (1, 1, 2))#创建一个掩码pred_mask,其中最大置信度大于0的位置为1,否则为0。pred_mask = pred_mask.astype(np.float32)#使用pred_mask将preds中置信度不为0的位置设置为0。preds *= pred_mask#preds *= pred_mask这一行,实际上是将那些置信度不大于0的关键点坐标设置为0。这可能是为了确保只返回那些有足够置信度的预测结果。return preds, maxvalsdef gaussian_blur(self, heatmap, kernel):#对热力图进行高斯模糊border = (kernel - 1) // 2#根据核大小计算边界大小,用于扩展热图以处理边界效应batch_size = heatmap.shape[0]num_joints = heatmap.shape[1]height = heatmap.shape[2]width = heatmap.shape[3]for i in range(batch_size):#遍历批处理中的每个热图:对于每个热图,遍历每个关键点。for j in range(num_joints):origin_max = np.max(heatmap[i, j])dr = np.zeros((height + 2 * border, width + 2 * border))dr[border:-border, border:-border] = heatmap[i, j].copy()#将原始热图扩展,以便在应用高斯模糊时不会丢失边界信息dr = cv2.GaussianBlur(dr, (kernel, kernel), 0)#使用OpenCV的GaussianBlur函数对扩展的热图进行高斯模糊heatmap[i, j] = dr[border:-border, border:-border].copy()#还原热图:将模糊后的热图裁剪回原始大小。heatmap[i, j] *= origin_max / np.max(heatmap[i, j])#确保模糊后的热图的最大值与原始热图的最大值相同。return heatmapdef dark_parse(self, hm, coord):#两个参数:hm(一个二维numpy数组,表示一个关键点的热图)和coord(一个包含x和y坐标的列表或元组)heatmap_height = hm.shape[0]heatmap_width = hm.shape[1]px = int(coord[0])py = int(coord[1])if 1 < px < heatmap_width - 2 and 1 < py < heatmap_height - 2:#确保提供的坐标位于热图的有效范围内dx = 0.5 * (hm[py][px + 1] - hm[py][px - 1])#计算梯度和Hessian矩阵:基于热图在给定坐标周围的像素值,计算梯度(dx, dy)和Hessian矩阵(dxx, dxy, dyy)。dy = 0.5 * (hm[py + 1][px] - hm[py - 1][px])dxx = 0.25 * (hm[py][px + 2] - 2 * hm[py][px] + hm[py][px - 2])dxy = 0.25 * (hm[py + 1][px + 1] - hm[py - 1][px + 1] - hm[py + 1][px - 1] \+ hm[py - 1][px - 1])dyy = 0.25 * (hm[py + 2 * 1][px] - 2 * hm[py][px] + hm[py - 2 * 1][px])derivative = np.matrix([[dx], [dy]])hessian = np.matrix([[dxx, dxy], [dxy, dyy]])if dxx * dyy - dxy ** 2 != 0:#如果Hessian矩阵的行列式不为零(确保Hessian矩阵非奇异),则使用计算出的偏移量更新原始坐标。hessianinv = hessian.Ioffset = -hessianinv * derivativeoffset = np.squeeze(np.array(offset.T), axis=0)coord += offsetreturn coorddef dark_postprocess(self, hm, coords, kernelsize):#hm(热图),coords(关键点的初步坐标),和kernelsize(高斯模糊核的大小)'''DARK postpocessing, Zhang et al. Distribution-Aware CoordinateRepresentation for Human Pose Estimation (CVPR 2020).'''hm = self.gaussian_blur(hm, kernelsize)#进行高斯模糊hm = np.maximum(hm, 1e-10)#为了确保数值稳定性,热图中的值被限制为最小为 1e-10hm = np.log(hm)#对热图应用对数变换for n in range(coords.shape[0]):for p in range(coords.shape[1]):coords[n, p] = self.dark_parse(hm[n][p], coords[n][p])#对于每一个初步坐标,使用 dark_parse 函数来修正坐标return coordsdef get_final_preds(self, heatmaps, center, scale, kernelsize=3):"""the highest heatvalue location with a quarter offset in thedirection from the highest response to the second highest response.Args:heatmaps (numpy.ndarray): The predicted heatmapscenter (numpy.ndarray): The boxes centerscale (numpy.ndarray): The scale factorReturns:preds: numpy.ndarray([batch_size, num_joints, 2]), keypoints coordsmaxvals: numpy.ndarray([batch_size, num_joints, 1]), the maximum confidence of the keypoints"""coords, maxvals = self.get_max_preds(heatmaps)#使用 get_max_preds 函数从热图中获取初步的关键点坐标和最大置信度heatmap_height = heatmaps.shape[2]#获取热图的高度和宽度heatmap_width = heatmaps.shape[3]#if self.use_dark:#如果启用了 use_dark,则使用 dark_postprocess 函数对坐标进行后处理。否则,对于每个初步坐标,如果它不在热图的边界内,则根据热图在该点的梯度进行简单的偏移coords = self.dark_postprocess(heatmaps, coords, kernelsize)else:for n in range(coords.shape[0]):#将修正后的坐标复制到 preds 变量中。for p in range(coords.shape[1]):hm = heatmaps[n][p]px = int(math.floor(coords[n][p][0] + 0.5))py = int(math.floor(coords[n][p][1] + 0.5))if 1 < px < heatmap_width - 1 and 1 < py < heatmap_height - 1:diff = np.array([hm[py][px + 1] - hm[py][px - 1],hm[py + 1][px] - hm[py - 1][px]])coords[n][p] += np.sign(diff) * .25preds = coords.copy()# Transform back    将关键点坐标从热图的空间转换回原始图像的空间for i in range(coords.shape[0]):preds[i] = transform_preds(coords[i], center[i], scale[i],[heatmap_width, heatmap_height])#根据每个图像的中心点(center)、尺度因子(scale)以及热图的尺寸(heatmap_width 和 heatmap_height)来调整坐标return preds, maxvalsdef __call__(self, output, center, scale):preds, maxvals = self.get_final_preds(output.numpy(), center, scale)#获得最终的预测结果"""将 preds 和 maxvals 沿着最后一个维度(axis=-1)进行连接。这意味着如果 preds 的形状是 (batch_size, num_joints, 2)(每个关键点的二维坐标),而 maxvals 的形状是 (batch_size, num_joints, 1)(每个关键点的最大置信度),那么连接后的结果将具有形状 (batch_size, num_joints, 3),其中最后一列是每个关键点的最大置信度。np.mean(maxvals, axis=1) 计算 maxvals 沿着第二个维度(axis=1)的均值。这通常用于获取每个图像(或批次中的每个样本)上所有关键点置信度的平均值。"""outputs = [[np.concatenate((preds, maxvals), axis=-1), np.mean(maxvals, axis=1)]]return outputs#连接后的 preds 和 maxvals 可以直接用于可视化,而 maxvals 的均值则可以用于评估模型的整体性能

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

类和对象提高

此篇继续讲解类和对象的提高知识&#xff0c;包括默认成员函数、运算符重载等相关内容&#xff0c;没有看过 C基础知识和类和对象基础知识&#xff08;可翻阅我的文章&#xff09;的小伙伴&#xff0c;可以先收藏&#xff0c;之后学习完再看效果会更好哦。 默认成员函数 在一…

力扣 第 387 场周赛 解题报告 | 珂学家 | 离散化树状数组 + 模拟场

前言 整体评价 手速场模拟场&#xff0c;思路和解法都蛮直接的。 所以搞点活 如果T2&#xff0c;如果不固定左上角&#xff0c;批量查询某个点为左上角&#xff0c;求满足总和 ≤ k \le k ≤k的子矩阵个数 如果T2&#xff0c;如果不固定左上角&#xff0c;求总和 ≤ k \le k…

老年人居家安全问题,全视通社区居家养老解决方案来赋能

近年来&#xff0c;老年人居家环境问题逐渐受到社会的关注。从新闻报道得知&#xff0c;传统居家环境对老年人存在诸多挑战&#xff0c;比如在入户空间、起居&#xff08;室&#xff09;厅、卧室、卫生间、厨房等区域。这些挑战不仅影响老年人的生活质量&#xff0c;还可能导致…

【大厂AI课学习笔记NO.60】(13)模型泛化性的评价

我们学习了过拟合和欠拟合&#xff0c;具体见我的文章&#xff1a;https://giszz.blog.csdn.net/article/details/136440338 那么今天&#xff0c;我们来学习模型泛化性的评价。 泛化性的问题&#xff0c;我们也讨论过了&#xff0c;那么如何评价模型的泛化性呢&#xff1f; …

vue 常用的 UI 组件库之一:Vuetify组件库

Vuetify是一个基于Vue.js 的Material Design组件库&#xff0c;它提供了一套完整的、预构建的、可自定义的、响应式的组件&#xff0c;以便开发者可以快速构建美观且功能强大的Web应用程序。Vuetify遵循Material Design设计指南&#xff0c;提供了一系列易于使用的组件&#xf…

[项目设计] 从零实现的高并发内存池(二)

&#x1f308; 博客个人主页&#xff1a;Chris在Coding &#x1f3a5; 本文所属专栏&#xff1a;[高并发内存池] ❤️ 前置学习专栏&#xff1a;[Linux学习] ⏰ 我们仍在旅途 ​ 目录 2.高并发内存池整体架构 3.ThreadCache实现 3.1 ThreadCache整体架构…

这是开玩笑吗?加个工具,WPS与Excel表格变成了应用系统

表格处理数据简单快捷&#xff0c;是个人用户的首选。然而&#xff0c;当企业长期使用&#xff0c;成本表、客户表、销售表等堆积如山&#xff0c;寻找所需表格如同大海捞针&#xff0c;稍有不慎便可能导致数据丢失、混乱。即便使用WPS和Excel这样的表格软件&#xff0c;处理大…

Harmony OS 父子组件传参

Harmony OS 父子组件传参案例 一、Prop&#xff1a;从父组件单向同步状态 类似于vue的prop传参&#xff0c;只能父组件传参给子组件 当点击父组件的按钮时&#xff0c;改变message值&#xff0c;参数跟着更新。并且子组件也跟着更新&#xff08;前提是要子组件加上prop装饰器…

力扣hot100:1.两数之和

输入中可能存在重复值 。 分析&#xff1a; 本题需要返回的是数组下标&#xff0c;因此如果需要使用排序然后双指针的话&#xff0c;需要用到哈希表&#xff0c;但是由于输入中可能存在重复值&#xff0c;因此哈希表的value值必须是vector<int>。 使用双指针求目标值targ…

Ansible setup 模块 该模块主要用于收集信息,是通过调用facts组件来实现的。

目录 作用查看信息验证保存信息验证 作用 该模块主要用于收集信息&#xff0c;是通过调用facts组件来实现的。   facts组件是Ansible用于采集被管机器设备信息的一个功能&#xff0c;我们可以使用setup模块查机器的所有facts信息&#xff0c;可以使用filter来查看指定信息。…

【系统维护】-微软电脑管家官网

以前没注意&#xff0c;最近一次升级后给安装了微软电脑管家&#xff0c;特别是瘦身功能感觉比较好&#xff0c;以前总是装第三方或者用命令行情况&#xff0c;有时候不小心还会给系统搞崩溃。感觉这个会安全很多。 还有其他一些功能&#xff0c;建议感兴趣的的可以试一下&…

Axure导入使用ElementUI组件库

在使用Axure进行UI设计时&#xff0c;我们可能导入ElementUI组件库或者一些其他的元件库&#xff0c;其实非常简单&#xff0c;如果你还没有装好Axure可以先安装好AxureRP9汉化版&#xff0c;接下来&#xff0c;我们以AxureRP9汉化版来演示如何导入ElementUI组件库。 第一步&a…