热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

coco关键点标注json_OpenCV图像处理基于OpenPose的关键点检测

OpenCV基于OpenPose的手部关键点检测概述✔️手部关键点检测,旨在找出给定图片中手指上的关节点及指尖关节点,其中手部关键点检测的应用场景主要包括࿱
92bcd7dfb4cdc87bc242b325e3bb7e28.png

OpenCV基于OpenPose的手部关键点检测

概述

✔️ 手部关键点检测,旨在找出给定图片中手指上的关节点及指尖关节点, 其中手部关键点检测的应用场景主要包括:

  • 手势识别
  • 手语识别与理解
  • 手部的行为识别

✔️ Opencv的DNN手部识别主要基于 CMU Perceptual Computing Lab 开源的手部关键点检测模型OpenPose。

手部关键点检测器的实现主要是基于论文:Hand Keypoint Detection in Single Images using Multiview Bootstrapping - CVPR2017

其中,如下:

44f05dd6eb9c4a1e81554db4e3a20767.png

✏️ 论文中,首先采用少量标注的人手部关键点图像数据集,训练类似于人体姿态关键点所使用的CPM - Convolutional Pose Machines 网络,以得到手部关键点的粗略估计. 采用了 31个 HD 高清摄像头从不同的视角对人手部进行拍摄。然后,将拍摄图像送入手部关键点检测器,以初步得到许多粗略的关键点检测结果。一旦有了同一手部的不同视角的关键点,则构建关键点测量(Keypoint triangulation),以得到关键点的3D位置。关键点的3D位置被从3D重新投影到每一幅不同视角的 2D 图片,并采用2D图像和关键点,进一步训练网络,以鲁棒的预测手部关键点位置,这对于关键点难以预测的图片而言是尤其重要的。采用这种方式,通过少量几次迭代,即可得到较为准确的手部关键点检测器.

⛳ 总之,关键点检测器和多视角图像(multi-view images) 一起构建了较为准确的手部关键点检测模型. 采用的检测网络类似于人体关键点中所用的网络结构. 进度提升的主要因素是采用了多视角图片标注图片数据集.

✔️ 手部关键点检测模型共输出 22 个关键点,其中包括手部的 21 个点,第 22 个点表示背景. 如图:

24041b4a2ed75b985504ba190774157f.png
手部关键点

代码示例

☑️️ ️模型文件准备:

[1] - hand/pose_deploy.prototxt

[2] - hand/pose_iter_102000.caffemodel

☑️️ python代码:

import os
import cv2
import time
import numpy as np
import matplotlib.pyplot as pltclass general_pose_model(object):def __init__(self, modelpath):self.num_points = 22self.point_pairs = [[0,1],[1,2],[2,3],[3,4],[0,5],[5,6],[6,7],[7,8],[0,9],[9,10],[10,11],[11,12],[0,13],[13,14],[14,15],[15,16],[0,17],[17,18],[18,19],[19,20]]self.inHeight = 368self.threshold = 0.1self.hand_net = self.get_hand_model(modelpath)# 模型加载def get_hand_model(self, modelpath):prototxt = os.path.join(modelpath, "pose_deploy.prototxt")caffemodel = os.path.join(modelpath, "../pose_iter_102000.caffemodel")hand_model = cv2.dnn.readNetFromCaffe(prototxt, caffemodel)return hand_model# 预测def predict(self, imgfile):img_cv2 = cv2.imread(imgfile)img_height, img_width, _ = img_cv2.shapeaspect_ratio = img_width / img_heightinWidth = int(((aspect_ratio * self.inHeight) * 8) // 8)inpBlob = cv2.dnn.blobFromImage(img_cv2, 1.0 / 255, (inWidth, self.inHeight), (0, 0, 0), swapRB=False, crop=False)self.hand_net.setInput(inpBlob)output = self.hand_net.forward()# vis heatmapsself.vis_heatmaps(imgfile, output)points = []for idx in range(self.num_points):probMap = output[0, idx, :, :] # confidence map.probMap = cv2.resize(probMap, (img_width, img_height))# Find global maxima of the probMap.minVal, prob, minLoc, point = cv2.minMaxLoc(probMap)if prob > self.threshold:points.append((int(point[0]), int(point[1])))else:points.append(None)return points# heatmap可视化def vis_heatmaps(self, imgfile, net_outputs):img_cv2 = cv2.imread(imgfile)plt.figure(figsize=[10, 10])for pdx in range(self.num_points):probMap = net_outputs[0, pdx, :, :]probMap = cv2.resize(probMap, (img_cv2.shape[1], img_cv2.shape[0]))plt.subplot(5, 5, pdx+1)plt.imshow(cv2.cvtColor(img_cv2, cv2.COLOR_BGR2RGB))plt.imshow(probMap, alpha=0.6)plt.colorbar()plt.axis("off")plt.show()# 手部关键点可视化def vis_pose(self, imgfile, points):img_cv2 = cv2.imread(imgfile)img_cv2_copy = np.copy(img_cv2)for idx in range(len(points)):if points[idx]:cv2.circle(img_cv2_copy, points[idx], 8, (0, 255, 255), thickness=-1,lineType=cv2.FILLED)cv2.putText(img_cv2_copy, "{}".format(idx), points[idx], cv2.FONT_HERSHEY_SIMPLEX,1, (0, 0, 0), 2, lineType=cv2.LINE_AA)# 绘制连接点for pair in self.point_pairs:partA = pair[0]partB = pair[1]if points[partA] and points[partB]:cv2.line(img_cv2, points[partA], points[partB], (0, 255, 255), 3)cv2.circle(img_cv2, points[partA], 8, (0, 0, 255), thickness=-1, lineType=cv2.FILLED)plt.figure(figsize=[10, 10])plt.subplot(1, 2, 1)plt.imshow(cv2.cvtColor(img_cv2, cv2.COLOR_BGR2RGB))plt.axis("off")plt.subplot(1, 2, 2)plt.imshow(cv2.cvtColor(img_cv2_copy, cv2.COLOR_BGR2RGB))plt.axis("off")plt.show()if __name__ == '__main__':print("[INFO]Pose estimation.")os.listdir(imgs_path)]img_files = ['hand.jpg']start = time.time()modelpath = ""pose_model = general_pose_model(modelpath)print("[INFO]Model loads time: ", time.time() - start)for img_file in img_files:start = time.time()res_points = pose_model.predict(img_file)print("[INFO]Model predicts time: ", time.time() - start)pose_model.vis_pose(img_file, res_points)print("[INFO]Done.")

[1] - 输出heatmap:

cfce8cde8113d05fb38f9ae042454cf3.png

[2] - 输出关键点:

c12db60773b6ce02f5b89fb5bf79b3c2.png

OpenCV于OpenPose的人体姿态估计

✔️ 同样,Opencv也可以结合OpenPose进行人体姿态估计,具体实现和手部关键点检测类似,只是调用的模型函数有所区别,具体代码实现可以参考下文。

☑️ 模型文件下载:

OpenPose 人体姿态模型下载路径:

BODY25: http://posefs1.perception.cs.cmu.edu/OpenPose/models/pose/body_25/pose_iter_584000.caffemodel
COCO: http://posefs1.perception.cs.cmu.edu/OpenPose/models/pose/coco/pose_iter_440000.caffemodel
MPI: http://posefs1.perception.cs.cmu.edu/OpenPose/models/pose/mpi/pose_iter_160000.caffemodelCOCO prototxt:https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/models/pose/coco/pose_deploy_linevec.prototxt

☑️ 代码实现:

import cv2
import time
import numpy as np
import matplotlib.pyplot as plt
import osclass general_pose_model(object):def __init__(self, modelpath, mode="BODY25"):# 指定采用的模型# Body25: 25 points# COCO: 18 points# MPI: 15 pointsself.inWidth = 368self.inHeight = 368self.threshold = 0.1if mode == "BODY25":self.pose_net = self.general_body25_model(modelpath)elif mode == "COCO":self.pose_net = self.general_coco_model(modelpath)elif mode == "MPI":self.pose_net = self.get_mpi_model(modelpath)def get_mpi_model(self, modelpath):self.points_name = { "Head": 0, "Neck": 1, "RShoulder": 2, "RElbow": 3, "RWrist": 4,"LShoulder": 5, "LElbow": 6, "LWrist": 7, "RHip": 8, "RKnee": 9, "RAnkle": 10, "LHip": 11, "LKnee": 12, "LAnkle": 13, "Chest": 14, "Background": 15 }self.num_points = 15self.point_pairs = [[0, 1], [1, 2], [2, 3], [3, 4], [1, 5], [5, 6], [6, 7], [1, 14],[14, 8], [8, 9], [9, 10], [14, 11], [11, 12], [12, 13]]prototxt = os.path.join(modelpath,"pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt")caffemodel = os.path.join(modelpath, "pose/mpi/pose_iter_160000.caffemodel")mpi_model = cv2.dnn.readNetFromCaffe(prototxt, caffemodel)return mpi_modeldef general_coco_model(self, modelpath):self.points_name = {"Nose": 0, "Neck": 1, "RShoulder": 2, "RElbow": 3, "RWrist": 4,"LShoulder": 5, "LElbow": 6, "LWrist": 7, "RHip": 8, "RKnee": 9, "RAnkle": 10, "LHip": 11, "LKnee": 12, "LAnkle": 13, "REye": 14, "LEye": 15, "REar": 16, "LEar": 17, "Background": 18}self.num_points = 18self.point_pairs = [[1, 0], [1, 2], [1, 5], [2, 3], [3, 4], [5, 6], [6, 7], [1, 8], [8, 9],[9, 10], [1, 11], [11, 12], [12, 13], [0, 14], [0, 15], [14, 16], [15, 17]]prototxt = os.path.join(modelpath, "openpose_pose_coco.prototxt")caffemodel = os.path.join(modelpath, "../pose_iter_440000.caffemodel")print(prototxt, caffemodel)coco_model = cv2.dnn.readNetFromCaffe(prototxt, caffemodel)return coco_modeldef general_body25_model(self, modelpath):self.num_points = 25self.point_pairs = [[1, 0], [1, 2], [1, 5], [2, 3], [3, 4], [5, 6], [6, 7], [0, 15], [15, 17], [0, 16], [16, 18], [1, 8],[8, 9], [9, 10], [10, 11], [11, 22], [22, 23], [11, 24],[8, 12], [12, 13], [13, 14], [14, 19], [19, 20], [14, 21]]prototxt = os.path.join(modelpath, "pose/body_25/pose_deploy.prototxt")caffemodel = os.path.join(modelpath, "pose/body_25/pose_iter_584000.caffemodel")coco_model = cv2.dnn.readNetFromCaffe(prototxt, caffemodel)return coco_modeldef predict(self, imgfile):img_cv2 = cv2.imread(imgfile)img_height, img_width, _ = img_cv2.shapeinpBlob = cv2.dnn.blobFromImage(img_cv2, 1.0 / 255, (self.inWidth, self.inHeight),(0, 0, 0), swapRB=False, crop=False)self.pose_net.setInput(inpBlob)self.pose_net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)self.pose_net.setPreferableTarget(cv2.dnn.DNN_TARGET_OPENCL)output = self.pose_net.forward()H = output.shape[2]W = output.shape[3]print(output.shape)# vis heatmapsself.vis_heatmaps(img_file, output)#points = []for idx in range(self.num_points):probMap = output[0, idx, :, :] # confidence map.# Find global maxima of the probMap.minVal, prob, minLoc, point = cv2.minMaxLoc(probMap)# Scale the point to fit on the original imagex = (img_width * point[0]) / Wy = (img_height * point[1]) / Hif prob > self.threshold:points.append((int(x), int(y)))else:points.append(None)return pointsdef vis_heatmaps(self, imgfile, net_outputs):img_cv2 = cv2.imread(imgfile)plt.figure(figsize=[10, 10])for pdx in range(self.num_points):probMap = net_outputs[0, pdx, :, :]probMap = cv2.resize(probMap, (img_cv2.shape[1], img_cv2.shape[0]))plt.subplot(5, 5, pdx+1)plt.imshow(cv2.cvtColor(img_cv2, cv2.COLOR_BGR2RGB))plt.imshow(probMap, alpha=0.6)plt.colorbar()plt.axis("off")plt.show()def vis_pose(self, imgfile, points):img_cv2 = cv2.imread(imgfile)img_cv2_copy = np.copy(img_cv2)for idx in range(len(points)):if points[idx]:cv2.circle(img_cv2_copy, points[idx], 3, (0, 0, 255), thickness=-1,lineType=cv2.FILLED)cv2.putText(img_cv2_copy, "{}".format(idx), points[idx], cv2.FONT_HERSHEY_SIMPLEX,.6, (0, 255, 255), 1, lineType=cv2.LINE_AA)# Draw Skeletonfor pair in self.point_pairs:partA = pair[0]partB = pair[1]if points[partA] and points[partB]:cv2.line(img_cv2, points[partA], points[partB], (0, 255, 0), 3)cv2.circle(img_cv2, points[partA], 3, (0, 0, 255), thickness=-1, lineType=cv2.FILLED)

[1] - 输出heatmap:

ebc1a3258fd70af965715d73e58f012c.png

[2] - 输出姿态:

19538c006c201da3ffefb8e41e2ceb3d.png

------------------------------------------可爱の分割线------------------------------------------

更多Opencv教程可以 Follow github的opencv教程,中文&English 欢迎Star❤️❤️❤️

JimmyHHua/opencv_tutorials​github.com
d3719a6fa97e50c640bf4b650d1c5b7e.png



推荐阅读
  • Ext JS MVC系列一:环境搭建与框架概览
    本文主要介绍了如何在项目中使用Ext JS 4作为前端框架,并详细讲解了Ext JS 4的MVC开发模式。文章将从项目目录结构、相关CSS和JS文件的引用以及MVC框架的整体认识三个方面进行总结。 ... [详细]
  • Python全局解释器锁(GIL)机制详解
    在Python中,线程是操作系统级别的原生线程。为了确保多线程环境下的内存安全,Python虚拟机引入了全局解释器锁(Global Interpreter Lock,简称GIL)。GIL是一种互斥锁,用于保护对解释器状态的访问,防止多个线程同时执行字节码。尽管GIL有助于简化内存管理,但它也限制了多核处理器上多线程程序的并行性能。本文将深入探讨GIL的工作原理及其对Python多线程编程的影响。 ... [详细]
  • REST与RPC:选择哪种API架构风格?
    在探讨REST与RPC这两种API架构风格的选择时,本文首先介绍了RPC(远程过程调用)的概念。RPC允许客户端通过网络调用远程服务器上的函数或方法,从而实现分布式系统的功能调用。相比之下,REST(Representational State Transfer)则基于资源的交互模型,通过HTTP协议进行数据传输和操作。本文将详细分析两种架构风格的特点、适用场景及其优缺点,帮助开发者根据具体需求做出合适的选择。 ... [详细]
  • 本文介绍如何在 Android 中自定义加载对话框 CustomProgressDialog,包括自定义 View 类和 XML 布局文件的详细步骤。 ... [详细]
  • MicrosoftDeploymentToolkit2010部署培训实验手册V1.0目录实验环境说明3实验环境虚拟机使用信息3注意:4实验手册正文说 ... [详细]
  • 使用多项式拟合分析淘宝双11销售趋势
    根据天猫官方数据,2019年双11成交额达到2684亿元,再次刷新历史记录。本文通过多项式拟合方法,分析并预测未来几年的销售趋势。 ... [详细]
  • 原文网址:https:www.cnblogs.comysoceanp7476379.html目录1、AOP什么?2、需求3、解决办法1:使用静态代理4 ... [详细]
  • 开发技巧:在Interface Builder中实现UIButton文本居中对齐的方法与步骤
    开发技巧:在Interface Builder中实现UIButton文本居中对齐的方法与步骤 ... [详细]
  • Python 序列图分割与可视化编程入门教程
    本文介绍了如何使用 Python 进行序列图的快速分割与可视化。通过一个实际案例,详细展示了从需求分析到代码实现的全过程。具体包括如何读取序列图数据、应用分割算法以及利用可视化库生成直观的图表,帮助非编程背景的用户也能轻松上手。 ... [详细]
  • Python 程序转换为 EXE 文件:详细解析 .py 脚本打包成独立可执行文件的方法与技巧
    在开发了几个简单的爬虫 Python 程序后,我决定将其封装成独立的可执行文件以便于分发和使用。为了实现这一目标,首先需要解决的是如何将 Python 脚本转换为 EXE 文件。在这个过程中,我选择了 Qt 作为 GUI 框架,因为之前对此并不熟悉,希望通过这个项目进一步学习和掌握 Qt 的基本用法。本文将详细介绍从 .py 脚本到 EXE 文件的整个过程,包括所需工具、具体步骤以及常见问题的解决方案。 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 在 Linux 环境下,多线程编程是实现高效并发处理的重要技术。本文通过具体的实战案例,详细分析了多线程编程的关键技术和常见问题。文章首先介绍了多线程的基本概念和创建方法,然后通过实例代码展示了如何使用 pthreads 库进行线程同步和通信。此外,还探讨了多线程程序中的性能优化技巧和调试方法,为开发者提供了宝贵的实践经验。 ... [详细]
  • 本文探讨了一种高效的算法,用于生成所有数字(0-9)的六位组合,允许重复使用数字,并确保这些组合的和等于给定的整数N。该算法通过优化搜索策略,显著提高了计算效率,适用于大规模数据处理和组合优化问题。 ... [详细]
  • 本文深入探讨了Ajax的工作机制及其在现代Web开发中的应用。Ajax作为一种异步通信技术,改变了传统的客户端与服务器直接交互的模式。通过引入Ajax,客户端与服务器之间的通信变得更加高效和灵活。文章详细分析了Ajax的核心原理,包括XMLHttpRequest对象的使用、数据传输格式(如JSON和XML)以及事件处理机制。此外,还介绍了Ajax在提升用户体验、实现动态页面更新等方面的具体应用,并讨论了其在当前Web开发中的重要性和未来发展趋势。 ... [详细]
  • 本文探讨了利用Python实现高效语音识别技术的方法。通过使用先进的语音处理库和算法,本文详细介绍了如何构建一个准确且高效的语音识别系统。提供的代码示例和实验结果展示了该方法在实际应用中的优越性能。相关文件可从以下链接下载:链接:https://pan.baidu.com/s/1RWNVHuXMQleOrEi5vig_bQ,提取码:p57s。 ... [详细]
author-avatar
棉花小姐啦啦啦取_649
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有