---
# System prepended metadata

title: 輸出關節資料格式
tags: [openpose]

---

---
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)

```
### 顯示結果:

![](https://i.imgur.com/VuK4FSc.jpg)


### 程式碼解釋:

#### (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]]
```

### 對應的關節格式索引值圖示：


![](https://i.imgur.com/QkoEocP.png)



[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
```

### 顯示畫面 (暫)

![](https://i.imgur.com/1IKZJGF.png)


## 疑問

```
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()
#------------------------------------------------------------------------------------------------------

```

![](https://i.imgur.com/vBzIjSj.png)

![](https://i.imgur.com/sfia0ev.jpg)

------
    
### 多補東西
    
![](https://i.imgur.com/A3hjPwv.png)
    

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