---
tags: openpose
---
# 輸出關節資料格式
## 2021/3/02
### 1.在桌面新增openpose資料夾
### 2.在Anaconda Prompt(虛擬機) 打路徑
輸入下面指令,啟動 Openpose 虛擬環境
```
activate Openpose
```
#### 本機跟虛擬機差別在python版本不同
上面是利用 Anaconda 的 conda 來建立虛擬機(相同作業系統),如果要用在不同作業系統,則是使用VirtualBox
#### 自行建立 Python 3.7的 Wrapper :
在之前新增的openpose資料夾下,新增openpose資料夾(放套件包),將
(1)
D:\openpose\build\python\openpose\Release\pyopenpose.cp37-win_amd64.pyd文件及D:\openpose\build\python\openpose\__init__.py文件複製進去。
(2)
D:\openpose\build\bin中的所有文件也複製進去。
(3)D:\openpose\build\x64\Release\openpose.dll複製進文件夾。
這樣openpose就可以使用Python 3.7的OpenPose庫了。最後在將模型D:\openpose\models資料夾複製進去就完成了。
上述方法介紹:[在Windows上编译OpenPose Python Wrapper](https://yuanze.wang/posts/build_openpose_python_api/)
### (1) 精簡 openpose_python.py => openpose_python_sample.py
[openpose_python_sample](https://repl.it/join/bljqbswn-lilysally)
```
# From Python
# It requires OpenCV installed for Python
import sys
import cv2
import openpose.pyopenpose as op
try:
params = dict()
params["model_folder"] = "openpose\\models"
opWrapper = op.WrapperPython(op.ThreadManagerMode.Synchronous)
opWrapper.configure(params)
opWrapper.execute()
except Exception as e:
print(e)
sys.exit(-1)
```
### 顯示結果:

### 程式碼解釋:
#### (1) 異常處理程序 - try...except...
語法結構:
```
try:
指令 #預先設想可能引發錯誤異常的指令
except 異常物件: #ZeroDivisionError
異常處理程序 #通常是指出異常原因,方便修正
```
[為什麼要用異常處理?](https://ithelp.ithome.com.tw/articles/10231653)
[Python例外處理機制的四種語法介紹](https://www.learncodewithmike.com/2019/12/python-exceptions.html)
#### (2) 使用python的dict存取檔案,還是 opWrapper.configure(params)的參數裡必須是字典格式?
### 資料結構-字典介紹:
#### (3) op.WrapperPython():
openpose裡的Wrapper,是OpenPose多合一包裝器模板類。Wrapper允許用戶設置輸入(視頻,網絡攝像頭,自定義輸入等),把姿勢,面部和/或手估計和渲染以及輸出。
> * WrapperT: OpenPose all-in-one wrapper template class. Simplified into Wrapper for WrapperT<std::vector<Datum>>
> * WrapperT allows the user to set up the input (video, webcam, custom input, etc.), pose, face and/or hands
> * estimation and rendering, and output (integrated small GUI, custom output, etc.).
github : [openpose/wrapper說明](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/include/openpose/wrapper/wrapper.hpp)
#### (4): https://www.jianshu.com/p/bcdfa75c42ac
```
sys.exit(-1)
```
* sys.exit(0)
* sys.exit(1)
* sys.exit(-1)
[sys.exit()解釋](https://stackoverflow.com/questions/44893807/i-want-to-know-what-exactly-sys-exit-1-returns-in-python)
### 總結 openpose_python_sample.py 解釋:
```
```
---
### 由於 openpose_python.py 是利用 Camera 的視訊內容抓取骨架圖,但想要利用圖片抓取骨架圖
大致流程:圖片輸入端建立->跑不出骨架圖->打開攝像頭->匯入圖片與攝像頭融合
### (2) 使用OpenCV 打開 攝像頭 - cap.py
```
import cv2
cap = cv2.VideoCapture(0)#開啟相機
while(True):
ret,frame = cap.read()#捕獲一幀影象
cv2.imshow('frame',frame)
#判斷按鍵,如果按鍵為q,退出迴圈
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()#關閉相機
cv2.destroyAllWindows()#關閉視窗
```
[python+opencv打開攝像頭,保存視頻、拍照功能的實現](https://www.itread01.com/content/1544442877.html)
### (3)參照 body_from_image.py 找到 影像檔的輸入
```
# From Python
# It requires OpenCV installed for Python
import sys
import cv2
import openpose.pyopenpose as op
try:
params = dict()
params["model_folder"] = "openpose\\models"
opWrapper = op.WrapperPython()
opWrapper.configure(params)
opWrapper.start()
datum = op.Datum()
imageToProcess = cv2.imread()
datum.cvInputData = imageToProcess
opWrapper.emplaceAndPop(op.VectorDatum([datum]))
print("Body keypoints: \n" + str(datum.poseKeypoints))
except Exception as e:
print(e)
sys.exit(-1)
```
### 程式碼解釋:
```
Datum : The OpenPose Basic Piece of Information Between Threads.
//Datum:執行緒之間的OpenPose基本信息。
```
### (4) Camera 與 圖片結合
```
# From Python
# It requires OpenCV installed for Python
import sys
import cv2
import openpose.pyopenpose as op
params = dict()
params["model_folder"] = "openpose\\models"
opWrapper = op.WrapperPython()
opWrapper.configure(params)
opWrapper.start()
cap = cv2.VideoCapture(0)#開啟相機
while(True):
ret,frame = cap.read()#捕獲一幀影象
datum = op.Datum()
imageToProcess = frame
datum.cvInputData = imageToProcess
opWrapper.emplaceAndPop(op.VectorDatum([datum]))
z = datum.cvOutputData
cv2.imshow('frame',z)
# Display Image
print("Body keypoints: \n" + str(datum.poseKeypoints))
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()#關閉相機
cv2.destroyAllWindows()#關閉視窗
```
### (5) Camera 與 影片檔結合
```
# From Python
# It requires OpenCV installed for Python
import sys
import cv2
import openpose.pyopenpose as op
cap = cv2.VideoCapture('test.mp4') #輸入檔案類型的函式
params = dict()
params["model_folder"] = "openpose\\models"
params["net_resolution"] = '128x192' #設定解析度大小
opWrapper = op.WrapperPython() #要放到while前面
opWrapper.configure(params)
opWrapper.start()
while(True):
ret,frame = cap.read()#捕獲一幀影象
datum = op.Datum()
imageToProcess = frame
datum.cvInputData = imageToProcess
opWrapper.emplaceAndPop(op.VectorDatum([datum]))
m = datum.cvOutputData
cv2.imshow('frame',m)
print("Body keypoints: \n" + str(datum.poseKeypoints))
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()#關閉相機
cv2.destroyAllWindows()#關閉視窗
```
### (6) 關節資訊顯示在影片上
關節格式:datum.poseKeypoints[0]的輸出格式為二維陣列?(陣列大小為:1x25),故datum.poseKeypoints[0]是輸出25個關節資訊,如果要找出個別關節,則使用 [ ] (中括號)
### datum.poseKeypoints[0],在cmd 畫面:
```
[[257.54697 272.47083 0.91656864]
[257.61194 337.86185 0.972461 ]
[216.85521 337.894 0.9464247 ]
[186.81346 403.5726 0.86242855]
[181.80258 463.8957 0.96689296]
[302.92554 337.90036 0.9488703 ]
[332.8495 413.4284 0.86522126]
[337.8536 469.1365 0.86683357]
[262.44052 474.13147 0.8797865 ]
[227.2652 479.02014 0.8531483 ]
[222.31241 579.8629 0.97199047]
[222.04073 670.54987 0.9516205 ]
[297.73517 474.0419 0.9056552 ]
[297.56735 579.76276 0.9473028 ]
[297.61746 665.6127 0.93682545]
[252.23906 262.53036 0.92262983]
[262.60666 262.437 0.95570076]
[222.38423 267.5079 0.90364 ]
[282.6488 262.59705 0.75656044]
[302.67032 700.7075 0.8589381 ]
[317.90045 695.64526 0.7964009 ]
[287.68665 680.4798 0.7573683 ]
[227.20302 705.7354 0.88318944]
[212.16296 705.5781 0.875509 ]
[222.2951 685.481 0.82196677]]
```
### 對應的關節格式索引值圖示:

[true.mp4](https://www.dropbox.com/h?preview=true.mp4)
### (1) 以往關節資訊都顯示在cmd
```
# From Python
# It requires OpenCV installed for Python
import cv2
import openpose.pyopenpose as op
cap = cv2.VideoCapture('true.mp4') #輸入檔案類型的函式
params = dict()
params["model_folder"] = "openpose\\models"
params["net_resolution"] = '128x192'
opWrapper = op.WrapperPython() #要放到while前面
opWrapper.configure(params)
opWrapper.start()
frame_num = 0 #計算FPS
while(True):
ret,frame = cap.read()#捕獲一幀影象
datum = op.Datum()
imageToProcess = frame
datum.cvInputData = imageToProcess
opWrapper.emplaceAndPop(op.VectorDatum([datum]))
m = datum.cvOutputData
cv2.imshow('frame',m)
frame_num += 1 #每新增一幀+1
if(str(datum.poseKeypoints)!='None'):
if(frame_num==30):
print('-------------')
#print(datum.poseKeypoints[0][12][0]) //取出關節為12的串列資料
point ='({x},{y})'.format(x=int(datum.poseKeypoints[0][12][0]),y=int(datum.poseKeypoints[0][12][1]))
print(point)
print(str(frame_num))
cv2.putText(m,'Frame :'+str(frame_num), (10, 90),cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
keypress = cv2.waitKey(1)
#----------------按z暫停-------------------
if keypress & 0xFF == ord('z'):
print('暫停(按任意鍵繼續)')
cv2.waitKey(0)
print('繼續')
#------------------------------------------
#-----------按q鍵退出迴圈(攝影機)------------
if keypress & 0xFF == ord('q'):
break
#------------------------------------------
#-----------------------------------------------------
# print(datum.poseKeypoints[0][12])
cap.release()#關閉相機
cv2.destroyAllWindows()#關閉視窗
```
### 顯示結果:
```
(297,474)
30
```
### 顯示畫面 (暫)

## 疑問
```
cv2.putText(m,'Frame :'+str(frame_num), (10, 90),cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
```
為什麼 Frame:30,沒有顯示出來?
https://blog.gtwang.org/programming/opencv-drawing-functions-tutorial/
### 語法解釋:
```
params = dict()
params["model_folder"] = "openpose\\models"
params["net_resolution"] = '128x192'
```
### (2) 顯示在讀取的影片上
```
```
-----
### Openpose_Video.py
```
import cv2
import sys
import openpose.pyopenpose as op
import math
import numpy as np
import time
from openpyxl import Workbook
import os
#----------------------------計算角度函式(餘弦定理)------------------------------
def angle(name,point_number_1,point_number_2,point_number_3):
#----獲取關節點位置-----
point_1 = int(keypoint[frame_num][0][point_number_1][0]),int(keypoint[frame_num][0][point_number_1][1])
point_2 = int(keypoint[frame_num][0][point_number_2][0]),int(keypoint[frame_num][0][point_number_2][1])
point_3 = int(keypoint[frame_num][0][point_number_3][0]),int(keypoint[frame_num][0][point_number_3][1])
#----------------------
#------計算三邊長度-----
a=math.sqrt((point_2[0]-point_3[0])*(point_2[0]-point_3[0])+(point_2[1]-point_3[1])*(point_2[1] - point_3[1]))
b=math.sqrt((point_1[0]-point_3[0])*(point_1[0]-point_3[0])+(point_1[1]-point_3[1])*(point_1[1] - point_3[1]))
c=math.sqrt((point_1[0]-point_2[0])*(point_1[0]-point_2[0])+(point_1[1]-point_2[1])*(point_1[1]-point_2[1]))
#----------------------
if (-2*a*c)!=0:
if (b*b-a*a-c*c)/(-2*a*c)<-1 or (b*b-a*a-c*c)/(-2*a*c)>1:
B=180
print(name)
keepangle.append(B)
else:
B=round(math.degrees(math.acos((b*b-a*a-c*c)/(-2*a*c)))) #取得角度
middle_position = np.array(point_1)-(int((point_1[0] - point_3[0])/2),int((point_1[1] - point_3[1])/2)) #計算部位中間位置(方便顯示)
cv2.putText(OutputData,name+' : '+str(B),(middle_position[0],middle_position[1]), 1, 1,(255,255,255),1,cv2.LINE_AA)
keepangle.append(B)
#----------------------------------------------------------------------------
#------------選擇模式--------------
params = dict()
params["model_folder"] = 'openpose\\models'
params["net_resolution"] = '128x192'
params["model_pose"] = "BODY_25"
params["render_pose"] = 1
#---------------------------------
#----------引入openpose--------
opWrapper = op.WrapperPython()
opWrapper.configure(params)
opWrapper.start()
datum = op.Datum()
cap = cv2.VideoCapture('false.mp4')
#-----------------------------
fps = cap.get(cv2.CAP_PROP_FPS)
size = (int(cap.get(cv2.cv2.CAP_PROP_FRAME_WIDTH)),
int(cap.get(cv2.cv2.CAP_PROP_FRAME_HEIGHT)))
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('false_r.mp4',fourcc, fps,size)
#----------自定義變數----------
start = time.time() #計算時間
frame_num = 0 #計算FPS
Save_point = {}
keypoint ={} #存放每幀關節點數據
position = {'R_armpit':[1,2,3],'R_elbow': [2,3,4], 'R_knee':[9,10,11],'L_armpit':[1,5,6],'L_elbow':[5,6,7],'L_knee':[12,13,14]}
#需要部位的角度計算 = [[右腋下],[右手肘],[右膝蓋],[左腋下],[左手肘],[左膝蓋]]
#-----------------------------
#--------------------資料匯成 Excle(1)---------------------
point_name =['Frame\部位','鼻(0)','胸(1)','右肩(2)','右手肘(3)','右手腕(4)','左肩(5)', '左手肘(6)', '左手腕(7)', '骨盆中(8)', '右骨盆(9)', '右膝蓋(10)', '右腳踝(11)', '左骨盆(12)', '左膝蓋(13)', '左腳踝(14)', '右眼(15)', '左眼(16)', '右耳(17)', '左耳(18)', '左腳尖(19)', '左指頭(20)', '左腳跟(21)', '右腳尖(22)', '右指頭(23)', '右腳跟(24)']
angle_name = ['Frame\部位','右腋下','右手肘','右膝蓋','左腋下','左手肘','左膝蓋']
wb = Workbook() # 創建一個空白活頁簿物件
ws1 = wb.create_sheet('關節座標', 0) #創建活頁簿(在第一位置)
ws2 = wb.create_sheet('關節角度', 1) #創建活頁簿(在第二位置)
ws1.append(point_name) #標題列
ws2.append(angle_name) #標題列
xlsx_name = '關節數據false.xlsx' #Excel命名
#---------------------------------------------------------
#-----------------------------------------進入影像處理----------------------------------------------------
while (cap.isOpened()):
ret, frame = cap.read()
#---------------------如果有獲取影像,即進入運算-----------------------------------
if ret==True:
datum.cvInputData = frame
#opWrapper.emplaceAndPop([datum]) #原本的但有問題
opWrapper.emplaceAndPop(op.VectorDatum([datum])) #改成這個程式碼
OutputData = datum.cvOutputData #加上骨架後影像
keypoint[frame_num] = datum.poseKeypoints #儲存每幀關節點數據
#print(datum.poseKeypoints)
#-----在影像上顯示(部位角度&&關節點座標)----
if(str(datum.poseKeypoints)!='None'):
keeppoing = [frame_num+1] #供excel儲存用
keepangle = [frame_num+1] #供excel儲存用
#------計算每個部位角度----------
for i in position:
angle(i,position[i][0],position[i][1],position[i][2])
ws2.append(keepangle)
#------------------------------
#----------關節座標-------------
for i in datum.poseKeypoints[0]:
x = i[0]
y = i[1]
point = '({x},{y}){score}'.format(x=int(x),y=int(y),score = int(i[2]*100))
keeppoing.append(point)
if x>0:
cv2.putText(OutputData,point,(x,y), 1, 1,(0,0,255),1,cv2.LINE_AA)
ws1.append(keeppoing)
#------------------------------
else:
ws1.append([frame_num,'None'])
#----------------------------------------
#----------------計算時間和FPS------------
frame_num += 1 #每新增一幀+1
optime = round(time.time()-start, 2) #計算時間
cv2.putText(OutputData,'FPS : {0:.2f}'.format(round(frame_num/optime,2)), (10, 30),cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.putText(OutputData,'Time : '+str(optime), (10, 60),cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.putText(OutputData,'Frame :'+str(frame_num), (10, 90),cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
#----------------------------------------
#cv2.putText(OutputData,'Student', (round(OutputData.shape[0])+70, round(OutputData.shape[1]/4+50)),cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 5)
out.write(OutputData)
cv2.imshow("Openpose Python - Press q to Exit",OutputData)
#--------------------------------------------------------------------------------
print(frame_num)
print(datum.poseKeypoints)
print('-----------------')
#------------------------------------按鍵反饋-----------------------------------------
keypress = cv2.waitKey(1)
#----------------按z暫停-------------------
if keypress & 0xFF == ord('z'):
print('暫停(按任意鍵繼續)')
print(datum.poseKeypoints)
cv2.putText(OutputData,'STOP', (round(OutputData.shape[0]/2)+70, round(OutputData.shape[1]/4+50)),cv2.FONT_HERSHEY_SIMPLEX, 5, (0, 0, 255), 10)
cv2.putText(OutputData,'(You can press any key to continue)', (round(OutputData.shape[0]/3+85), round(OutputData.shape[1]/4)+100),cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255),5)
cv2.imshow("Openpose Python - Press q to Exit",OutputData)
cv2.waitKey(0)
print('繼續')
#------------------------------------------
#-----------按q鍵退出迴圈(攝影機)------------
if keypress & 0xFF == ord('q'):
break
#------------------------------------------
#-------------------------------------------------------------------------------------
#----------------------------------資料匯成 Excle(1)---------------------------------------
if os.path.isfile(xlsx_name):
os.remove(xlsx_name)
wb.save(xlsx_name)
else:
wb.save(xlsx_name)
#------------------------------------------------------------------------------------------
out.release()
cap.release()
cv2.destroyAllWindows()
#------------------------------------------------------------------------------------------------------
```


------
### 多補東西

```
conda create --name newOpense python=3.7
conda install -c anaconda opencv
```