基于openpose的引体向上的识别计数统计项目(3)CPoseRender类设计与实现

本文主要是介绍基于openpose的引体向上的识别计数统计项目(3)CPoseRender类设计与实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

CPoseRender 主要是为了简化openpose中的调用方式进行简化重写,只需要opencv的参数即可使用。

1、CPoseRender 声明

#pragma once#include "opencv2/core.hpp"#include "CPoseClassify.h"#include "Keypoints.h"namespace Utils {
// fastmath, taken from op
//
// Use op::round/max/min for basic types (int, char, long, float, double, etc). Never with classes!
// `std::` alternatives uses 'const T&' instead of 'const T' as argument.
// E.g., std::round is really slow (~300 ms vs ~10 ms when I individually apply it to each element of a whole
// image array// VERY IMPORTANT: These fast functions does NOT work for negative integer numbers.
// E.g., positiveIntRound(-180.f) = -179.// Round functions
// Signed
template<typename T>
inline char positiveCharRound(const T a)
{return char(a + 0.5f);
}template<typename T>
inline signed char positiveSCharRound(const T a)
{return (signed char)(a + 0.5f);
}template<typename T>
inline int positiveIntRound(const T a)
{return int(a + 0.5f);
}template<typename T>
inline long positiveLongRound(const T a)
{return long(a + 0.5f);
}template<typename T>
inline long long positiveLongLongRound(const T a)
{return (long long)(a + 0.5f);
}// Unsigned
template<typename T>
inline unsigned char uCharRound(const T a)
{return (unsigned char)(a + 0.5f);
}template<typename T>
inline unsigned int uIntRound(const T a)
{return (unsigned int)(a + 0.5f);
}template<typename T>
inline unsigned long ulongRound(const T a)
{return (unsigned long)(a + 0.5f);
}template<typename T>
inline unsigned long long uLongLongRound(const T a)
{return (unsigned long long)(a + 0.5f);
}// Max/min functions
template<typename T>
inline T fastMax(const T a, const T b)
{return (a > b ? a : b);
}template<typename T>
inline T fastMin(const T a, const T b)
{return (a < b ? a : b);
}template<class T>
inline T fastTruncate(T value, T min = 0, T max = 1)
{return fastMin(max, fastMax(min, value));
}
//
} // namespace Utilsclass CPoseRender
{
public:CPoseRender(PoseModel poseModel);~CPoseRender();void rendPose(cv::Mat& frame, const cv::Mat& poseData, float renderThreshold = 0.05);private:const PoseModel poseModel;
};

2、CPoseRender 实现

#include "CPoseRender.h"#include <vector>
#include <array>//#include "openpose/utilities/fastMath.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"namespace {#define POSE_BODY_25_PAIRS_RENDER \1,8,   1,2,   1,5,   2,3,   3,4,   5,6,   6,7,   8,9,   9,10,  10,11, 8,12,  12,13, 13,14,  1,0,   0,15, 15,17,  0,16, 16,18,   14,19,19,20,14,21, 11,22,22,23,11,24
#define POSE_BODY_25_SCALES_RENDER 1
#define POSE_BODY_25_COLORS_RENDER \255.f,     0.f,    85.f, \255.f,     0.f,     0.f, \255.f,    85.f,     0.f, \255.f,   170.f,     0.f, \255.f,   255.f,     0.f, \170.f,   255.f,     0.f, \85.f,   255.f,     0.f, \0.f,   255.f,     0.f, \255.f,     0.f,     0.f, \0.f,   255.f,    85.f, \0.f,   255.f,   170.f, \0.f,   255.f,   255.f, \0.f,   170.f,   255.f, \0.f,    85.f,   255.f, \0.f,     0.f,   255.f, \255.f,     0.f,   170.f, \170.f,     0.f,   255.f, \255.f,     0.f,   255.f, \85.f,     0.f,   255.f, \0.f,     0.f,   255.f, \0.f,     0.f,   255.f, \0.f,     0.f,   255.f, \0.f,   255.f,   255.f, \0.f,   255.f,   255.f, \0.f,   255.f,   255.fconst std::array<std::vector<unsigned int>, (int)PoseModel::Size> POSE_BODY_PART_PAIRS_RENDER{std::vector<unsigned int>{POSE_BODY_25_PAIRS_RENDER},       // BODY_25
};const std::array<std::vector<unsigned int>, (int)PoseModel::Size> POSE_BODY_PART_PAIRS{// BODY_25std::vector<unsigned int>{1,8, 1,2, 1,5, 2,3, 3,4, 5,6, 6,7, 8,9, 9,10, 10,11, 8,12, 12,13, 13,14, 1,0,  0,15, 15,17, 0,16, 16,18,  2,17, 5,18,  14,19,19,20,14,21, 11,22,22,23,11,24}
};const std::array<std::vector<float>, (int)PoseModel::Size> POSE_SCALES{std::vector<float>{POSE_BODY_25_SCALES_RENDER},       // BODY_25
};const std::array<std::vector<float>, (int)PoseModel::Size> POSE_COLORS{std::vector<float>{POSE_BODY_25_COLORS_RENDER},       // BODY_25
};void renderOpenPoseKeypoints(cv::Mat & frame, const cv::Mat & poseData, PoseModel poseModel, const float threshold)
{const auto thicknessCircleRatio = 1.f / 75.f;const auto thicknessLineRatioWRTCircle = 0.75f;const auto& pairs = POSE_BODY_PART_PAIRS_RENDER.at((int)poseModel);const auto& poseScales = POSE_SCALES.at((int)poseModel);const auto& colors = POSE_COLORS.at((int)(int)poseModel);//-------------------------------------------------------------------------const auto width = frame.size[1];const auto height = frame.size[0];const auto area = width * height;// Parametersconst auto lineType = 8;const auto shift = 0;const auto numberColors = colors.size();const auto numberScales = poseScales.size();const auto thresholdRectangle = float(0.1);const auto numberKeypoints = poseData.cols; //keypoints.getSize(1);// Keypointsfor(auto person = 0; person < poseData.rows; person++) {const auto personRectangle = Utils::getKeypointsRectangle(poseData, person, thresholdRectangle);if(personRectangle.area() > 0) {const auto ratioAreas = Utils::fastMin(float(1), Utils::fastMax(personRectangle.width / (float)width, personRectangle.height / (float)height));// Size-dependent variablesconst auto thicknessRatio = Utils::fastMax(Utils::positiveIntRound(std::sqrt(area)* thicknessCircleRatio * ratioAreas), 2);// Negative thickness in cv::circle means that a filled circle is to be drawn.const auto thicknessCircle = Utils::fastMax(1, (ratioAreas > float(0.05) ? thicknessRatio : -1));const auto thicknessLine = Utils::fastMax(1, Utils::positiveIntRound(thicknessRatio * thicknessLineRatioWRTCircle));const auto radius = thicknessRatio / 2;// Draw linesfor(auto pair = 0u; pair < pairs.size(); pair += 2) {const auto index1 = (person * numberKeypoints + pairs[pair]) * poseData.channels();const auto index2 = (person * numberKeypoints + pairs[pair + 1]) * poseData.channels();if(poseData.at<float>(index1 + 2) > threshold && poseData.at<float>(index2 + 2) > threshold) {const auto thicknessLineScaled = Utils::positiveIntRound(thicknessLine * poseScales[pairs[pair + 1] % numberScales]);const auto colorIndex = pairs[pair + 1] * 3; // Before: colorIndex = pair/2*3;const cv::Scalar color{colors[(colorIndex + 2) % numberColors],colors[(colorIndex + 1) % numberColors],colors[colorIndex % numberColors]};const cv::Point keypoint1{Utils::positiveIntRound(poseData.at<float>(index1)), Utils::positiveIntRound(poseData.at<float>(index1+1))};const cv::Point keypoint2{Utils::positiveIntRound(poseData.at<float>(index2)), Utils::positiveIntRound(poseData.at<float>(index2 + 1))};cv::line(frame, keypoint1, keypoint2, color, thicknessLineScaled, lineType, shift);}}// Draw circlesfor(auto part = 0; part < numberKeypoints; part++) {const auto faceIndex = (person * numberKeypoints + part) * frame.channels();if(poseData.at<float>(faceIndex + 2) > threshold) {const auto radiusScaled = Utils::positiveIntRound(radius * poseScales[part % numberScales]);const auto thicknessCircleScaled = Utils::positiveIntRound(thicknessCircle * poseScales[part % numberScales]);const auto colorIndex = part * 3;const cv::Scalar color{colors[(colorIndex + 2) % numberColors],colors[(colorIndex + 1) % numberColors],colors[colorIndex % numberColors]};const cv::Point center{Utils::positiveIntRound(poseData.at<float>(faceIndex)),Utils::positiveIntRound(poseData.at<float>(faceIndex + 1))};cv::circle(frame, center, radiusScaled, color, thicknessCircleScaled, lineType, shift);}}}}
}} // namespaceCPoseRender::CPoseRender(PoseModel poseModel):poseModel(poseModel)
{
}CPoseRender::~CPoseRender()
{
}void CPoseRender::rendPose(cv::Mat & frame, const cv::Mat & poseData, float renderThreshold)
{if(frame.empty() || poseData.empty())return;renderOpenPoseKeypoints(frame, poseData, poseModel, renderThreshold);
}

这篇关于基于openpose的引体向上的识别计数统计项目(3)CPoseRender类设计与实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/788470

相关文章

部署Vue项目到服务器后404错误的原因及解决方案

《部署Vue项目到服务器后404错误的原因及解决方案》文章介绍了Vue项目部署步骤以及404错误的解决方案,部署步骤包括构建项目、上传文件、配置Web服务器、重启Nginx和访问域名,404错误通常是... 目录一、vue项目部署步骤二、404错误原因及解决方案错误场景原因分析解决方案一、Vue项目部署步骤

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

使用Python快速实现链接转word文档

《使用Python快速实现链接转word文档》这篇文章主要为大家详细介绍了如何使用Python快速实现链接转word文档功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 演示代码展示from newspaper import Articlefrom docx import

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为