C++實現DPM/LatentSVM 完整代碼下載 --- 第三篇

這是我的DPM代碼的第三篇博文,最初發表在http://blog.csdn.net/j56754gefge/article/details/40708679,均是我原創文章,他人轉載請註明出處!


C++實現DPM/LatentSVM,完整代碼下載!BUG持續改進!關注DPM實現的網友可以持續關注下該文章!使用代碼發現BUG的網友請不吝及時向我反饋,我把BUG改進後再在這裏更新出來,讓更多的人受益!


-------------------------------------------------------

此前我已經將Cascade DPM的C++代碼以及Original DPM的C++編譯庫發佈出來,很多人給我發郵件,希望能得到Original DPM的C++代碼,現在我就把這個源代碼發佈出來。

發佈內容:Original DPM,我也稱之爲完整版DPM,是Pedro. Felzenswalb發明的”deformable part based models for object detection”的程序實現,原始程序和參考文獻已經在我另一篇博文裏列出了,這裏不再贅述。我的工作是將原始的Matlab代碼voc-release5中檢測部分用C++實現。檢測部分有完整版DPM的,也有star-cascade版的,後者的c++程序之前已發佈,這裏發佈的則是完整版DPM的C++代碼。

爲什麼Original DPM?首先,原始的DPM算法充分體現了基於部件模型的目標檢測思想,與P.Felzenswalb關於在語法框架下進行目標表示和檢測的思想相應,學習該程序能較好地理解作者的目標檢測思想,而級聯是更早就有的一項技術,其主要思路是將任務分解成一步步去做,在每一步做完都檢查一下有沒有繼續做的必要,這是一個相當工程的東西,在boost分類器裏面就有級聯思想,並非P.F教授的首創。第二,與級聯算法相比,原始DPM的檢測效果更好,一般訓練一個級聯分類器首先要訓練原始DPM模型,然後繼續在數據集上挖掘信息(PCA、級聯訓練)來得到級聯模型。級聯模型對訓練數據集更加依賴,相比之下,原始DPM的推廣能力要強得多。

本文發佈的C++代碼有什麼特色?網上應該可以找到多個不同的關於原始DPM的C/C++實現,其中我覺得最好的一個版本便是集成在openCV庫中的”latentSVM”算法(其實就是DPM的檢測部分),與該代碼相比,本文公佈的代碼更快、效果更好!原因在於:一、我寫代碼嚴格參照voc-release5的matlab代碼,其計算結果和matlab代碼完全一致!(matlab代碼中的圖像縮放用的resize函數是作者自己編寫的,而我的代碼是用openCV自帶的圖像縮放函數——速度更快,這造成了計算結果的些許差異。但是我在調試代碼的時候,寫過一個函數直接將matlab代碼算出來的特徵金字塔加載到c++程序裏,使用同樣的特徵金字塔以後,我的代碼給出和matlab代碼完全一致的結果。)二、我用了近一年時間寫這個代碼,寫代碼的同時還在研究原始算法並寫自己的碩士論文,通過不斷摸索,對算法中很多地方做了優化處理,比如並行化、跳過中間環節的計算等等,直到我認爲再也找不到可以減少的計算。

關於代碼本身:代碼用C++編寫,依賴兩個公開庫——openCV和pthreah線程庫。openCV是著名的計算機視覺公開庫,不需多說。pthread也是公開的線程庫,提供線程管理和互斥鎖功能,是linux內置的庫,在windows下使用需要下載安裝。發佈的代碼是windows下的visual studio的solution,但程序中沒有使用與系統相關的函數,可以很容易移植到linux下使用(實際上我已經在幾乎不修改源代碼的情況下在Ubuntu下編譯並使用過了)。

其它:說一點願景,關於我爲什麼公開此代碼。說實話,很長一段時間內我都捨不得把該代碼給別人,因爲它凝聚了我很多心血,不想輕易送人。但是我現在研究方向已經與當初發生了較大變化,與其把這些代碼放在我硬盤上最終被遺忘,不如讓它們發揮應有的價值。人家P.F教授公開自己的算法代碼並獲得了VOC官方頒發的終身成就獎,我沒人家萬分之一牛,但是也希望能爲後來者學習提供一些幫助。願祖國更好!

代碼下載:http://download.csdn.net/detail/yu_xianguo/9669917

代碼是dpm的檢測部分,我已將voc-release5中包含的所有模型文件轉化成相應txt文件並上傳到網上,需要的話到我的另一篇文章(C++實現DPM/LatentSVM---第一篇)中下載.

代碼只包含檢測部分,如果你們使用voc-release5的matlab代碼訓練了自己的模型,可以用如下的m函數將模型保存爲txt文件以使用:http://download.csdn.net/detail/j56754gefge/8354899

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2015年11月4日   部分BUG修改

感謝網友的使用和回饋,讓我知道了代碼中的部分bug,今天我對到目前爲止所發現的2個bug作修改。修改後的代碼將放到雲盤中替換我原來的壓縮文件,大家直接點擊上文的鏈接下載即可。下面對這兩個bug做出說明。

第一個bug:      感謝湖南師大的李老師的寶貴意見。

有網友反映,當使用自己訓練的模型時,程序運行會報錯,通過檢查我發現這是因爲matlab的模型都有一個bboxpred變量,而自己訓練的模型裏沒有這個變量。其實只要自習看一下matlab代碼就能發現,在matlab中,process.m文件時這樣寫的:

    if isfield(model, 'bboxpred')
      bboxpred = model.bboxpred;
      [ds, bs] = clipboxes(im, ds, bs);
      [ds, bs] = bboxpred_get(bboxpred, ds, reduceboxes(model, bs));
    else
      warning('no bounding box predictor found');
    end
  end

也就是說當模型中沒有bboxpred變量時,直接忽略相應的步驟就行了。我在寫程序時沒考慮到這一點,所以造成了錯誤。

第二個bug:      感謝上海交大的吳同學的寶貴意見。

部分網友質疑我的程序計算得正確性,我在測試程序時針對voc自帶的行人模型和車輛模型,用隨便挑選的圖片進行測試,結果是完全一致的,如下圖所示


上圖是我將matlab計算出的特徵金字塔加載到C程序中得出的結果,是完全一致的。

但是有不少人跟我反應他們自己測試時發現結果不一致,說實話,一開始我是不太相信的,直到湖師大的李老師給我發來了他自己訓練的模型,然後我檢測發現確實不一樣,而且出入較大。再次感謝上交的吳同學,他在很短的時間內就發現了程序中的另一個bug,就是我的FastDPM工程中的apply_rules.cpp / apply_rules2.cpp / apply_rules3.cpp,這三個文件中都有這樣一句話:

int rootSym2 = model.RuleData[1].sym_nonTerminal[0];

把其中的1改成component就行了。這是我的失誤,實在抱歉得很。

修改後的C程序,使用李老師發給我的行人檢測模型,分別使用matlab和C來算(matlab的金字塔算出來給c程序用),最終結果如圖所示:


當然,檢測的閾值我隨手給了個-1,可能不太對,導致結果不好看,但是這不影響我們關注的問題——兩個程序給出幾乎一致的結果。其中微小的差別很可能是因爲我的程序中使用的非最大值抑制函數(NMS)的不同導致的,我的NMS函數繼承自P'Dollar大神的工具箱,是個效率更高的方法,但是與matlab函數有略微不同。

還有個需要解釋的問題,就是大家看我的程序,會發現我有很多同名文件,比如剛纔的applyrules我就有3個文件,這3個文件的功能是一樣的,其接口也是一樣的,它們在程序中可以互換,也就是說你把主程序調用applyrules3函數的地方改成applyrules1應該不會改變結果,但是計算效率略有不同。第一個版本是最基礎的版本,有興趣看我程序的人,可以先從最簡單的版本開始。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章