1. 程式人生 > >【OpenPose】1.OpenPoseDemo檔案的使用與解讀

【OpenPose】1.OpenPoseDemo檔案的使用與解讀

OpenPose是基於深度學習的姿勢估計開源框架。

    它的原始碼託管在github上:OpenPose的連結

    下載、安裝可以參考官方文件,Visual Studio2017、CUDA9的安裝方法可以參考國內某些部落格【OpenPose-Windows】 OpenPose1.4.0+VS2017+CUDA9.2+cuDNN9.2+Windows配置教程 - CSDN部落格


一、前序準備

    在將Debug換成Release,右鍵openpose專案點選設為啟動專案,再點選生成,等待一段時間。

    生成完畢後,在Examples檔案下找到OpenPoseDemo專案點選設為啟動專案,再點選生成


二、解讀Demo檔案

 

首先是註釋:

註釋說明

翻譯如下:

如果您想學習使用OpenPose庫,我們強烈建議您從examples / tutorial 資料夾開始。

此示例總結了OpenPose庫的所有功能:

    1.讀取影象/視訊/網路攝像頭的資料夾(producer模組)

    2.提取並渲染該影象的身體關鍵點/熱圖/ PAF(Part Affinity Fields)(pose

模組)

    3.提取並渲染該影象的面部關鍵點/熱圖/ PAF(face模組)

    4.將結果儲存在磁碟上(filestream模組)

    5.顯示渲染的姿勢(gui模組)

    多執行緒場景中的所有內容(thread模組)

    第2~5點包含在wrapper模組中

除了之前的OpenPose模組,我們還需要使用:

    1. core

模組:

            對於pose模組需要的Array類

`           Datum是thread模組佇列(queue)之間傳送的結構體

    2. utilities模組:

用於異常(error)和日誌(log)記錄功能,分別是op :: error和op :: log


匯入依賴包

依賴包匯入

chrono是C++中的時間標準模組,擁有表示時間點時間段的類,以及互相轉換的方法

thread模組,顧名思義,是多執行緒標準模組

gflags是Google開源的命令列引數解析工具,用於聲名、定義、驗證命令列引數,後面的程式碼有體現

後面的#ifndef是允許Ubuntu 14使用Google Flags

最後引入openpose依賴庫


 

位址列引數說明

使用`--help`標誌檢視所有可用的引數選項。

例如:

Linux下命令 `build / examples / openpose / openpose.bin --help`(保證根目錄在Openpose中)

Windows的方法下面討論,這個可以先不看


 

位址列引數定義

然後是位址列引數的定義,有兩百多行,並且每個函式的第一個引數都是未定義的符號,於是檢視DEFINE_XXX的定義位置,發現就是gflags的巨集定義類函式

DEFINE_string

格式是DEFINE_XXX(name, val, txt)

第一個引數name是引數名,第二個引數是引數預設值,第三個引數是引數說明

例如DEFINE_string(video, "", "......"),使用時寫上OpenPoseDemo.exe --video path

當OpenPoseDemo --help時就會彈出txt


之後定義的int OpenPoseDemo()函式定義引數的驗證、日誌列印等操作

main函式呼叫OpenPoseDemo函式並返回OpenPoseDemo函式的返回值

具體解析放到最後(參閱附錄二),可以先跳過


三、Demo檔案的使用

    第一種方法(不建議):

        在 build \ x64 \ Release 檔案下找到OpenPoseDemo.exe檔案,單獨執行會顯示找不到各種dll檔案,可以將exe檔案與openpose.dll檔案一同複製到 build \ bin 目錄下,然後在命令列下執行,但是此方法會找不到其他依賴檔案,所以不建議使用

    第二種方法:

        更改位址列引數的預設值。

        我們在Visual Studio中按Ctrl+F彈出的搜尋框中輸入`DEFINE_string(image_dir`,這是預設的影象識別資料夾,將要識別的目錄輸入即可,可以用openpose自帶的測試集,既把預設引數改為:

        同理,在這一行的上一行,或者搜尋`DEFINE_string(video`即可找到視訊的位址列引數定義,輸入路徑及視訊檔名即可

        注意,識別的型別不能既是視訊,又是影象,所以兩個引數不能同時不為空,否則會報錯

    第三種方法:

        真正用位址列傳參的方式,Visual Studio可以找到OpenPoseDemo專案,右鍵點選屬性

        在開啟的屬性頁面中,找到除錯,右側找到命令引數

輸入命令引數即可,上圖的例項中還增加了--face(面部識別)和--hand(手部識別)

按F5執行即可


附錄一、GUI快捷鍵大致翻譯        

    當在UI介面按h時會彈出快捷鍵幫助頁面,大致翻譯一下

快捷鍵

OpenPose命令:

改變預設的OpenPose引數

    Z:是否使用面部檢測(標誌 --face)

    X:是否使用手部檢測(標誌 --hand)

    C:是否使用3D呈現

    -=:減少/增加NMS閾值(NMSThreshold)

    _+:減少/增加連線最小子集(ConnectMinSubsetScore)

    [ ]:減少/增加連線內部閾值(ConnectInterThreshold)

    { }:減少/增加連線內部最小上界閾值(ConnectInterMinAboveThreshold)

    ; \: 減少/增加簡介最小子集計數(ConnectMinSubsetCnt)

呈現命令:

改變顯示型別(姿勢、熱圖、PAF)

    B:是否混合幀的結果

    1:顯示姿勢/骨骼(基礎圖)

    2:顯示背景熱圖

    3:顯示所有熱圖(所有關節)

    4:顯示所有PAF(關節及關節的連結肢體)

    ,.:顯示上一個/下一個元素

    567890:聯想初始化熱圖

雜項

    G:突出顯示眼睛為金魚眼

只能使用GPU呈現

附錄二、openPoseDemo函式解析

    函式引數為空,返回型別為int,函式整體被包含在一個try塊中,可以看出如果程式正常返回0

    如果出現未預料到的異常,將列印error日誌,輸出結果為:錯誤資訊錯誤所在的行錯誤所在的函式名以及錯誤所在的檔名並返回-1

捕獲到錯誤

    再回到函式的開頭首先

op::log("Starting OpenPose demo...", op::Priority::High);

const auto timerBegin = std::chrono::high_resolution_clock::now();  

    在控制檯列印日誌出Starting OpenPose demo...優先順序為高

    timerBegin為當前時間

 

logging_level

    用於檢查引數logging_level,如果不在[0, 255]之間,則列印“錯誤的logging_level值”,並且打印出錯所在的具體資訊。

    下面兩行註釋有解釋:

        這些是用於除錯(Debug)的方法,假如你在op::ConfigureLog::setPriorityThreshold方法中傳入op::Priority::None,則列印所有日誌資訊,op::Profiler::setDefaultX能控制列印日誌的速度

 

    應用使用者定義配置給程式變數的Google標記

    看一下輸出大小, FLAGS_output_resolution看起來沒被定義過,但其實前面得到巨集定義類函式DEFINE_xxx已經給了它定義,這個變數一看就與output_resolution相關,用CTRL+F跳到定義處看看說明

DEFINE_string(output_resolution, "-1x-1",

"The image resolution (display and output). Use \"-1x-1\" to force the program to use the" " input image resolution.");

 

    這個變數定義的是顯示和輸出的解析度。並且規定使用“-1x-1”就是-1乘-1的意思,程式會使用輸入的圖片解析度作為顯示和誒輸出的解析度,同時這個值為這個變數的預設值

    同理,看看第二個“網路輸入大小”變數的含義,它所關聯的變數為net_resolution

DEFINE_string(net_resolution, "-1x368",

"Multiples of 16. If it is increased, the accuracy potentially increases. If it is"

" decreased, the speed increases. For maximum speed-accuracy balance, it should keep the"

" closest aspect ratio possible to the images or videos to be processed. Using `-1` in"

" any of the dimensions, OP will choose the optimal aspect ratio depending on the user's"

" input value. E.g. the default `-1x368` is equivalent to `656x368` in 16:9 resolutions,"

" e.g. full HD (1980x1080) and HD (1280x720) resolutions."); 

    大致意思為:乘號兩側的變數值為16的倍數,如果增加,精度會變高,如果減少,速度會變快。為了獲得最大的速度 - 精度平衡,它應該保持最接近輸入值的寬高比可以處理要處理的影象或視訊。因此,將乘號兩側的任意一值列為“-1”,另一個變數會自動根據輸入的長寬比調整輸出的長寬比,例如:如果輸入的影象長寬比為16:9,那麼“-1x368”就相當於"656x368"

按照同樣的方法即可解析上面的程式碼

    接下來,宣告封裝器型別變數,然後用封裝器結構體(wrapperStructPose)將Pose資料封裝,Face、Hand等同樣如此

    然後用封裝器變數註冊:

    下面是看disable_multi_thread引數值,如果為真值,就要禁用多執行緒

    開始程序,有兩個不同的方法在多執行緒環境下執行程式

    第一個方法是上面的opWrapper.exec(),作用如上面的註釋所說:啟動,執行\停止執行緒,當其他所有執行緒單元完成後啟動該執行緒。

    下面的是註釋掉的是選項B:保持此執行緒空閒,以防你想要同時執行其他操作,例如 分析GPU記憶體。

    注意:如果使用Qt支援編譯OpenCV,選項B將不起作用。 Qt需要主執行緒來繪製視覺化結果,因此最終的GUI(使用OpenCV)將返回類似於以下內容的異常:QMetaMethod :: invoke:無法在排隊連線中呼叫帶有返回值的方法。

    函式的最後,獲取結束時間並計算總時間然後打印出日誌。

    openPoseDemo函式解析完畢!



作者:crossous
連結:https://www.jianshu.com/p/bcdfa75c42ac
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。