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