实验:如何在YOLO8中添加PnP算法来实现Head Pose Estimation


目录

  • 前言
  • 一、步骤
  • 二、PnP估计Head Pose,并显示
    • 1.引入库
    • 2.结果展示
  • 总结


前言

YOLO8的集成度比较高,如何在简洁的代码中加入Head Pose的东西,不是一件简单的事情.这里介绍如何插入PnP算法实现头部姿态估计的代码?


一、步骤

修改predict中的模型,改为我们自己训练的YOLOLandmark模型.
在这里插入图片描述
修改cfg入口,由于我们修改来config中不少超参数,因此我们干脆修改来为finetune.yaml,替换默认的cfg即可.
在这里插入图片描述
funetune.yaml主要修改的点如下:

model: path to model
name: results saved directory.
conf: object confidence threshold
source: source video path
show: True # to show the live demo.

注意这些点需要根据工程去调整.

二、PnP估计Head Pose,并显示

1.引入库

参考github VHead的项目,我们将head pose进行模块化,传入图片和keypoints即可通过PnP算法估计出Head Pose

代码如下(示例):


def draw_headpose(im0, kpts):landmarks = kpts.view(-1).tolist()POINTS_NUM_LANDMARK = 68clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) # CLAHE Object (for Adaptive histogram equalization)boxPoints3D = np.array(([500., 500., 500.],[-500., 500., 500.],[-500., -500., 500.],[500., -500., 500.],[500., 500., -500.],[-500., 500., -500.],[-500., -500., -500.],[500., -500., -500.]))boxPoints2D = np.zeros((1,1,8,2))# parameters for mean filterwindowlen_1 = 5queue3D_points = np.zeros((windowlen_1,POINTS_NUM_LANDMARK,2))windowlen_2 =5queue1D = np.zeros(windowlen_2)# pamameters for kalman filterXX = 0PP = 0.01lms_x = landmarks[0::3]lms_y = landmarks[1::3]lms = [lms_x, lms_y] # [[x,y] for x,y in zip(lms_x, lms_y)]lms = [ ([x,y]) for x,y in zip(lms_x, lms_y)]test_data = [0]test_time = [0]# # Socket Connect# try:#     client = socket(AF_INET, SOCK_STREAM)  # 创建Socket的客户端#     # client.connect(('127.0.0.1',1755))#     client.connect(('10.8.220.128',1755))# except:#     print("\nERROR: No socket connection.\n")#     sys.exit(0)# initialize kalman objectKalmanX = KalmanObject(POINTS_NUM_LANDMARK, 1,10) # Tune Q, R to change landmarks_x sensitivityKalmanY = KalmanObject(POINTS_NUM_LANDMARK, 1,10) # Tune Q, R to change landmarks_y sensitivityuu_ = np.zeros((POINTS_NUM_LANDMARK))# initialize PARAMETERStemp_landmarks = np.zeros((POINTS_NUM_LANDMARK,2))# Apply kalman filter to landmarks FOR POSE ESTIMATIONKalmanX.kalman_update(uu_, lms_x) KalmanY.kalman_update(uu_, lms_y) temp_landmarks[:,0] = KalmanX.xx.astype(np.int32)temp_landmarks[:,1] = KalmanY.xx.astype(np.int32)temp_landmarks = mean_filter_for_landmarks(temp_landmarks) # Apply smooth filter to landmarks FOR POSE ESTIMATIONleftEyeWid, rightEyewid, mouthWid,mouthLen = get_feature_parameters(lms) #landmarks_orig)parameters_str = 'leftEyeWid:{}, rightEyewid:{}, mouthWid:{}, mouthLen:{}'.format(leftEyeWid, rightEyewid, mouthWid, mouthLen)print(parameters_str)# Five feature points for pose estimation# image_points = np.vstack((landmarks[30],landmarks[8],landmarks[36],landmarks[45],landmarks[48],landmarks[54]))image_points = np.vstack((temp_landmarks[30],temp_landmarks[8],temp_landmarks[36],temp_landmarks[45],temp_landmarks[1],temp_landmarks[15]))ret, rotation_vector, translation_vector, camera_matrix, dist_coeffs = get_pose_estimation(im0.shape, image_points)if ret != True:print('ERROR: get_pose_estimation failed')# continue# used_time = time.time() - start_time# print("used_time:{} sec".format(round(used_time, 3)))# Convert rotation_vector to quaternionw,x,y,z = get_quaternion(rotation_vector)quaternion_str = 'w:{}, x:{}, y:{}, z:{}'.format(w, x, y, z)print(quaternion_str)# Packing data and transmit to server through Socketdata = str(translation_vector[0,0])+':'+str(translation_vector[1,0])+':'+str(translation_vector[2,0])+':'+str(w)+':'+str(x)+':'+str(y)+':'+str(z)+':'+str(leftEyeWid)+':'+str(rightEyewid)+':'+str(mouthWid)+':'+str(mouthLen)# Project a 3D point set onto the image plane# We use this to draw a bounding box(nose_end_point2D, jacobian) = cv2.projectPoints(np.array([(0.0, 0.0, 1000)]), rotation_vector, translation_vector, camera_matrix, dist_coeffs)# global  boxPoints2D for i in range(8):(boxPoints2D[:,:,i,:], jacobian) = cv2.projectPoints(np.array([boxPoints3D[i]]), rotation_vector, translation_vector, camera_matrix, dist_coeffs)        boxPoints2D =  boxPoints2D.astype(int)for p in image_points:cv2.circle(im0, (int(p[0]), int(p[1])), 3, (0,0,255), -1)boxset_1 = boxPoints2D[0,0,0:4,:]boxset_2 = boxPoints2D[0,0,4:8,:]boxset_3 = np.vstack((boxPoints2D[0,0,0,:],boxPoints2D[0,0,4,:]))boxset_4 = np.vstack((boxPoints2D[0,0,1,:],boxPoints2D[0,0,5,:]))boxset_5 = np.vstack((boxPoints2D[0,0,2,:],boxPoints2D[0,0,6,:]))boxset_6 = np.vstack((boxPoints2D[0,0,3,:],boxPoints2D[0,0,7,:]))cv2.polylines(im0, [boxset_1], True, (255,0,0), 3)cv2.polylines(im0, [boxset_2], True, (255,0,0), 3)cv2.polylines(im0, [boxset_3], True, (255,0,0), 3)cv2.polylines(im0, [boxset_4], True, (255,0,0), 3)cv2.polylines(im0, [boxset_5], True, (255,0,0), 3)cv2.polylines(im0, [boxset_6], True, (255,0,0), 3)p1 = ( int(image_points[0][0]), int(image_points[0][1]))p2 = ( int(nose_end_point2D[0][0][0]), int(nose_end_point2D[0][0][1]))cv2.line(im0, p1, p2, (0,255,0), 2)##########################################################################

在这里插入图片描述
这里需要判断ktps是否为空,再进行画图操作.

2.结果展示

在这里插入图片描述
可以看到左上角,head box的角度基本上与真实的头部姿态相吻合.

总结

这里,我们使用了Kalman 滤波来消除跳跃的情况,让pose变得更加平滑.但是Kalman 滤波的学习暂时没有具体取探索.在评估学习中.

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

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

相关文章

Linux学习之vim在光标所在处写入内容,保存退出

vim insertTest使用vim打开一个叫做insertTest新文件。 输入命令之后,按下Enter(回车键),就可以进入下边的操作页面。 按i在当前光标位置处,就可以插入内容了。 接下来写入内容跟记事本里边是差不多的。 按一下…

python_day8_综合案例

综合案例,全球GDP排行榜 1、知识点补充:sort()方法 sort()方法: 列表.sort(key选择排序依据的函数,reverseTrue|False) my_list [[a, 33], [b, 55], [c, 11]]def choose_sort_key(element):return element[1] # 列表中每个元素传进来&am…

Office如何通过VSTO进行PPT插件开发?

文章目录 0.引言1.工具准备2.PPT外接程序创建和生成3.外接程序生成并使用 0.引言 VSTO(Visual Studio Tools for Office )是VBA的替代,是一套用于创建自定义Office应用程序的Visual Studio工具包。VSTO可以用Visual Basic 或者Visual C#扩展O…

(转载)从0开始学matlab(第11天)—关系运算符和逻辑运算符

选择结构的运算由一个表达式控制的,这个表达式的结果只有 true(1)和 false(0)。有两种形式的运算符可以在 MATLAB 中关系得到 true/false:关系运算符和逻辑运算符。跟 C 语言一样,MATLAB 没有布尔型和逻辑数据类型。MATLAB 把 0 值作为结果fa…

android JSBridge的加载时机问题

https://github.com/lzyzsd/JsBridge 也算是比较悠久和使用了。 可供参考的android和IOS,以及前端的使用 https://segmentfault.com/a/1190000018208609 遇到的问题: 比如: 从前端在加载WebView的时候,执行了某些动作&#xff0c…

FreeRTOS 低功耗模式设计 STM32平台

1. STM32F105RBT6 的三种低功耗模式 1.1 sleep睡眠模式、stop停机模式、standby 待机模式 1.2 STM32中文参考手册有介绍STM32 低功耗模式的介绍 2. FreeRTOS 采用的是时间片轮转的抢占式任务调度机制,其低功耗设计思路一般是: ① 当运行空闲任务&#…

【UE4 C++】08-生成抛射物来模拟攻击效果

步骤 新建一个C类,父类为Actor,命名为“ASMagicProjectile” 在“ASMagicProjectile.h”中添加如下代码: 在“ASMagicProjectile.cpp”中添加如下代码: 编译后在虚幻编辑器中新建一个蓝图,选择父类为我们刚创建的C类…

Java设计模式之行为型-迭代器模式(UML类图+案例分析)

目录 一、基础概念 二、UML类图 三、角色设计 四、案例分析 五、总结 一、基础概念 迭代器模式是一种常用的设计模式,它主要用于遍历集合对象,提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。 举个简单的…

分布式微服务架构下网络通信的底层实现原理

在分布式架构中,网络通信是底层基础,没有网络,也就没有所谓的分布式架构。只有通过网络才能使得一大片机器互相协作,共同完成一件事情。 同样,在大规模的系统架构中,应用吞吐量上不去、网络存在通信延迟、…

Android Framework岗位面试真题分享

Handler是Android中的消息处理机制,是一种线程间通信的解决方案,同时你也可以理解为它天然的为我们在主线程创建一个队列,队列中的消息顺序就是我们设置的延迟的时间,如果你想在Android中实现一个队列的功能,不妨第一时…

【UE】运行游戏时就获取鼠标控制

问题描述 我们经常在点击运行游戏后运行再在视口界面点击一下才能让游戏获取鼠标控制。其实只需做一个设置就可以在游戏运行后自动获取鼠标控制。 解决步骤 点击编辑器偏好设置 如下图,点击“播放”,再勾选“游戏获取鼠标控制” 这样当你运行游戏后直…

shardingsphere mybatisplus properties和yml配置实现

shardingsphere mybatisplus properties和yml配置实现 目录结构 model package com.oujiong.entity; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.util.Date;/*** user表*/ TableName("user") Data public class Use…