關於DPM(Deformable Part Model)演算法中模型結構的解釋

masikkk發表於2014-05-16

       關於可變部件模型的描述在作者[2010 PAMI]Object Detection with Discriminatively Trained Part Based Models的論文中已經有說明:

     含有n個部件的目標模型可以形式上定義為一個(n+2)元組:(F0,P1,..., Pn, b),F0是根濾波器,Pi是第i個部件的模型,b是表示偏差的實數值。每個部件模型用一個三元組定義:(Fi,vi, di),Fi是第i個部件的濾波器;vi是一個二維向量,指定第i個濾波器的錨點位置(anchor position,即未發生形變時的標準位置) 相對於根的座標;di是一個四維向量,指定了一個二次函式的引數,此二次函式表示部件的每個可能位置相對於錨點位置的變形花費(deformation cost)。

          但是有了這個說明我們在看原始碼時還是會有很多不明白的地方,剛開始困擾我很長時間,經過一段時間的分析,有了一定的理解,下面是我對這個模型的分析,如有不妥之處,請大家留言指正。

        我分析的原始碼版本是voc-release3.1,從第4版開始加入了語法模型,更加複雜了,這裡不討論。

        分析模型結構體主要看initmodel.m這個檔案,通過看他如何初始化模型,我們可以明白其中大多數字段的含義。

        在這之前,我們可以在matlab中開啟一兩個原始碼中自帶的訓練好的模型m檔案,看看是什麼樣的。


inria_final.mat,Inria資料集上訓練的單元件模型



person_final.mat,VOC2007資料集上訓練的2元件人體模型


下面我會依次對各個欄位做詳細解釋

(1) sbin,整型標量

 sbin是HOG特徵中cell的尺寸,即cell的尺寸為sbin * sbin
定義cell是為了將畫素級特徵聚合成為基於cell的特徵C(i,j),0<=i<=|(w-1)/k|,0<=j<=|(h-1)/k|,參見[2010 PAMI]論文6.1.2 空間聚合,這裡的k就是cell尺寸sbin,這樣可以更明確的理解sbin的用處。


(2) interval,整型標量

HOG金字塔每組的層數


(3) numblocks,整型標量

模型中總的資料塊的個數


(4) numcomponents,整型標量

元件的個數(含多少個元件模型)


(5) blocksizes,double陣列,長度等於numblock

blocksizes[]陣列的元素個數等於numblock,指明每個資料塊的大小,
所以,想知道哪個資料的大小,就先找到他的資料塊標識,然後去blocksizes[]陣列查詢對應的資料塊大小。


(6) regmult,double陣列,長度等於numblock

還不清楚幹什麼的


(7) learnmult,double陣列,長度等於numblock

還不清楚幹什麼的


(8) lowerbounds,cell型別陣列,長度等於numblock

每個資料塊的資料值的下界,lowerbounds[]陣列的元素個數等於numblock。

假如某個資料塊的資料是向量或矩陣的話,則對應的lowerbounds元素值也是一個下界向量或矩陣


(9) maxsize,二元組

所有元件的根濾波器的[高度 寬度]的最大值,maxsize是統計所有元件的根濾波器的尺寸獲得的。


(10) minsize,二元組

所有元件的根濾波器的[高度 寬度]的最小值,minsize是統計所有元件的根濾波器的尺寸獲得的。


(11) thresh,double型別標量

保證高召回率需要的得分閾值,根據訓練結果計算得到的。

也就是說,如果用此模型進行目標檢測時,將得分閾值設為thresh能夠保證很高的召回率(recall rate),但是同時精度肯定就低了。


(12) rootfilters,cell型別陣列,長度為元件個數

根濾波器陣列,其每個元素表示一個元件模型的根濾波器的資訊,每個元素包括3個欄位:

        size:根濾波器的尺寸,以cell為單位,w*h

        w:根濾波器的引數向量,維數為(w*h)*31

        blocklabel:此根濾波器所在的資料塊標識


(13) partfilters,cell型別陣列,長度為模型中所有元件的部件的個數之和

部件濾波器陣列,其每個元素表示一個部件濾波器的資訊,每個元素包括4個欄位,注意:所有元件的部件是連續編號的

        w:部件濾波器的引數向量,維數為(w*h)*31

        partner:此部件對應的夥伴部件(對稱部件)的索引,如果partner的值為0,表示此部件沒有夥伴部件。

        fake:是否假部件,值為1表示此部件是假部件,假部件不需要blocklabel

        blocklabel:此部件濾波器所在的資料塊標識


(14) defs,cell型別陣列,長度為模型中所有元件的部件的個數之和

部件的錨點陣列 (變形資訊陣列),每個元素表示對應部件的可變形資訊。注意:所有元件的部件在defs中也是連續編號的每個元素包含3個欄位:

        anchor:部件的錨點座標,即部件未變形時的左上角點座標,參見論文[2010 PAMI]中的公式(3)中的vi變數

        w:w是一個四維向量,指明部件的變形花費函式的引數,參見論文[2010 PAMI]中的公式(2)中的di變數

        blocklabel:所在的資料塊標識


(15) offsets,cell型別陣列,長度為元件個數

偏移量陣列,每個元素表示對應元件模型的偏移量,每個元素又含有2個欄位

        w:元件的偏移量,是個實數值

        blocklabel:所在的資料塊標識


(16) components,cell型別陣列,長度為元件個數

元件資訊陣列,每個元素儲存一個元件模型的資訊,每個元素又包含7個欄位:

        rootindex:根濾波器的索引,指出元件的根濾波器在rootfilters[]陣列的位置

        offsetindex:元件的偏移量索引,指出元件的偏移量在offsets[]陣列的位置

        part:元件的部件資訊陣列,長度為該元件的部件個數,每個元素表示一個部件,每個元素又有2個欄位:

                partindex:部件的索引,指出此部件在partfilters[]陣列的位置,注意:所有元件的部件是連續編號的

                defindex:部件的錨點陣列索引,指出此部件的錨點在defs[]陣列的位置,注意:所有元件的部件是連續編號的

        dim:元件的維數(至於這個值具體是怎麼計算來的,我現在還不清楚,弄清楚了來更新)

        numblocks:元件所佔的資料塊個數(需要多少個資料塊來儲存此元件模型)

        x1,y1,x2,y2:包圍盒預測引數


一些需要解釋的地方

關於模型中的blocklabel的理解說明
模型中有好多陣列,例如rootfilters[],partfilters[],defs[],offsets[],這些陣列的資料是以塊block為單位進行儲存的,通過塊標識blocklabel來識別哪個資料位於哪個塊上,所以上述陣列的每個成員都有一個blocklabel域,來指明此資料所在的塊。numblock是總的資料塊個數。blocksizes[]陣列的元素個數等於numblock,指明每個資料塊的大小,
所以,想知道哪個資料的大小,就先找到他的資料塊標識,然後去blocksizes[]陣列查詢對應的資料塊大小。


關於部件的夥伴partner的解釋

在voc-release3.1中,模型是關於中軸對稱的,所以就有了夥伴部件(或稱為對稱部件)的概念。注意:從第4版開始模型不再要求是對稱的。一個部件存在夥伴,就說明有和此部件對稱的部件。夥伴部件的引數向量和此部件的引數向量w完全相同,一個部件和其夥伴部件是關於模型的中軸對稱的,所以不需要重複儲存引數向量w,這樣,就產生了一些假(fake)部件,它們只有一個空殼。假部件(fake=1)沒有blocklabel,因為它們不需要資料塊來儲存資訊,它們的資訊儲存在對應的夥伴部件中。如果partner的值為0,表示此部件沒有夥伴部件。


關於偏移量offset的解釋

偏移量offset就是加在每個元件模型的得分公式最後的一個實數值,參見論文[2010 PAMI]中的公式(2)中的b值


關於錨點陣列defs的解釋

一開始我以為def是定義definition的縮寫,但解釋不通,現在知道了,def是可變形deformable的縮寫,所以defs陣列中儲存的是所有部件的變形引數。anchor,錨點座標,是部件未發生移動時的座標,即理想狀況下的位置,更詳細的說,anchor是部件未變形時的左上角點座標。w,是個4維向量,指明部件i的變形花費函式的引數,參見論文[2010 PAMI]中的公式(2)中的di變數。通過分析原始碼發現w中4個引數分別對應這4個偏移量[Δx^2, Δx, Δy^2, Δy](分析視覺化變形花費的程式碼時確定的,在檔案visualizemodel.m中)。


關於每個cell的特徵向量的維數為什麼是31維的解釋

設C是聚合有9個對比度不敏感方向的畫素級特徵對映而獲得的基於cell的特徵對映,D是聚合有18個對比度敏感方向的畫素級特徵而獲得的基於cell的特徵對映。用4種不同的歸一化方法對C(i,j)和D(i,j)進行歸一化和截斷(限幅),可以獲得一個4*(9+18)=108維的特徵向量F(i,j)。實際中我們使用此108維向量的一個解析投影,此投影由下面幾個統計量定義:27個在不同歸一化因子上的累加和(即列的和),F中的每個方向通道對應一個;以及4個在不同方向(9維對比度不敏感方向)上的累加和(即行的和),每個歸一化因子對應一個。cell尺寸k=8,截斷(限幅)閾值α=0.2。最終的特徵對映是31維向量G(i,j),其中27維對應不同的方向通道(9個對比度不敏感方向和18個對比度敏感方向),剩下4維表示(i,j)周圍4個cell組成的block的梯度能量。詳見[2010 PAMI]論文中6.2節 PCA和解析降維


明白了這些,初始化的過程就很容易看懂了,初始化的過程在下面的原始碼上有註釋:

function model = initmodel(pos, sbin, size)
% 初始化模型結構
% 引數
% pos:用來訓練此模型的正樣本陣列
% sbin:HOG特徵的最小單位,cell的長度
% size:根濾波器尺寸
% 如果不提供根濾波器的尺寸,則根據正樣本的長寬比統計資訊計算得出
%
% model = initmodel(pos, sbin, size)
% Initialize model structure.
% If not supplied,the dimensions of the model template are computed from statistics in the postive examples.
% 
% 關於cell尺寸sbin的解釋:
% 將畫素級特徵聚合成為基於cell的特徵C(i,j),0<=i<=|(w-1)/k|,0<=j<=|(h-1)/k|,參見[2010 PAMI]論文6.1.2 空間聚合,
% 這裡的k就是cell尺寸sbin,這樣可以更明確的理解sbin的用處
% 
% 關於部件的夥伴partner的解釋:
% 在voc-release3.1中,模型是關於中軸對稱的,所以就有了夥伴部件(或稱為對稱部件)的概念。注意:從第4版開始模型不再要求是對稱的。
% 一個部件存在夥伴,就說明有和此部件對稱的部件。夥伴部件的引數向量和此部件的引數向量w完全相同,一個部件和其夥伴部件是關於模型的中軸對稱的,
% 所以不需要重複儲存引數向量w,這樣,就產生了一些假(fake)部件,它們只有一個空殼。假部件(fake=1)沒有blocklabel,因為它們不需要資料塊來儲存資訊,
% 它們的資訊儲存在對應的夥伴部件中。如果partner的值為0,表示此部件沒有夥伴部件。
%
% 關於每個cell的特徵向量的維數為什麼是31維的解釋:
% 設C是聚合有9個對比度不敏感方向的畫素級特徵對映而獲得的基於cell的特徵對映,D是聚合有18個對比度敏感方向的畫素級特徵而獲得的基於cell的特徵對映。
% 用4種不同的歸一化方法對C(i,j)和D(i,j)進行歸一化和截斷(限幅),可以獲得一個4*(9+18)=108維的特徵向量F(i,j)。
% 實際中我們使用此108維向量的一個解析投影,此投影由下面幾個統計量定義:
% 27個在不同歸一化因子上的累加和(即列的和),F中的每個方向通道對應一個;以及4個在不同方向(9維對比度不敏感方向)上的累加和(即行的和),每個歸一化因子對應一個。
% cell尺寸k=8,截斷(限幅)閾值α=0.2。最終的特徵對映是31維向量G(i,j),其中27維對應不同的方向通道(9個對比度不敏感方向和18個對比度敏感方向),
% 剩下4維表示(i,j)周圍4個cell組成的block的梯度能量。詳見[2010 PAMI]論文中6.2節 PCA和解析降維
%
% 關於模型中的blocklabel的理解說明:
% 模型中有好多陣列,例如rootfilters[],partfilters[],defs[],offsets[],這些陣列的資料是以塊block為單位進行儲存的,
% 通過塊標識blocklabel來識別哪個資料位於哪個塊上,所以上述陣列的每個成員都有一個blocklabel域,來指明此資料所在的塊。
% numblock是總的資料塊個數(注意不是總的部件個數,剛開始理解錯了),blocksizes[]陣列的元素個數等於numblock,指明每個資料塊的大小,
% 所以,想知道哪個資料的大小,就先找到他的資料塊標識,然後去blocksizes[]陣列查詢對應的資料塊大小。
%
% 關於偏移量offset的解釋:
% 偏移量offset就是加在每個元件模型的得分公式最後的一個實數值,參見論文[2010 PAMI]中的公式(2)中的b值
%
% 關於錨點座標陣列defs[]的解釋:
% 一開始我以為def是定義definition的縮寫,但解釋不通,現在知道了,def是可變形deformable的縮寫,所以defs陣列中儲存的是所有部件的變形引數
% anchor,錨點座標,是部件未發生移動時的座標,即理想狀況下的位置,更詳細的說,anchor是部件未變形時的左上角點座標
% w,是個4維向量,指明部件i的變形花費函式的引數,參見論文[2010 PAMI]中的公式(2)中的di變數
% 通過分析原始碼發現w中4個引數分別對應這4個偏移量[Δx^2, Δx, Δy^2, Δy](分析視覺化變形花費的程式碼時確定的,在檔案visualizemodel.m中)
%
% model.sbin             HOG cell的尺寸
% model.interval         金字塔每組的層數
% model.numblocks        總的資料塊個數
% model.numcomponents    元件的個數(含多少個元件模型)
% model.blocksizes       每個資料塊的大小,blocksizes[]陣列的元素個數等於numblock
% model.regmult
% model.learnmult
% model.lowerbounds      每個資料塊的資料值的下界,lowerbounds[]陣列的元素個數等於numblock
                         %假如某個資料塊的資料是向量或矩陣的話,則對應的lowerbounds元素值也是一個下界向量或矩陣
% model.maxsize          所有元件的根濾波器的[高度 寬度]的最大值
% model.minsize          所有元件的根濾波器的[高度 寬度]的最小值
% model.rootfilters{i}   元件i的根濾波器,根濾波器陣列的長度等於元件個數
%   .size                  元件i的根濾波器的尺寸(以cell為單位),w*h
%   .w                     元件i的根濾波器向量,維數為(w*h)*31
%   .blocklabel            元件i的根濾波器所在的資料塊標識
% model.partfilters{i}   第i個部件濾波器,部件濾波器陣列的長度等於所有元件的部件個數的總和,注意:所有元件模型的part是連續編號的
%   .w                     第i個部件濾波器向量,維數為(w*h)*31
%   .blocklabel            第i個部件濾波器所在的資料塊標識
% model.defs{i}          第i個部件的錨點,部件錨點陣列的長度等於所有元件的部件個數的總和,所有元件模型的part是連續編號的
%   .anchor                第i個部件的錨點座標,即部件i未變形時的左上角點座標,參見論文[2010 PAMI]中的公式(3)中的vi變數
%   .w                     w是一個四維向量,指明部件i的變形花費函式的引數,參見論文[2010 PAMI]中的公式(2)中的di變數
%   .blocklabel            第i個部件的錨點所在的資料塊標識
% model.offsets{i}       第i個元件的偏移量,偏移量陣列的長度等於元件個數
%   .w                     第i個元件的偏移量,是個實數值
%   .blocklabel            第i個元件的偏移量所在的資料塊標識
% model.components{i}    第i個元件的資訊
%   .rootindex             第i個元件的根濾波器的索引,指出元件i的根濾波器在rootfilters[]陣列的位置
%   .parts{j}              第i個元件的第j個部件的資訊
%     .partindex             第i個元件的第j個部件的部件濾波器陣列索引,指出在partfilters[]陣列的位置,注意:所有元件模型的part是連續編號的
%     .defindex              第i個元件的第j個部件的錨點座標陣列索引,指出在defs[]陣列的位置,注意:所有元件模型的part是連續編號的
%   .offsetindex           第i個元件的偏移量的索引,指出在offsets[]陣列的位置
%   .dim                   第i個元件的維數
%   .numblocks             第i個元件模型的資料塊個數(需要多少個資料塊來儲存元件模型i),所有元件的numblocks之和等於整個模型的numblocks


% 計算此組正樣本典型的高寬比aspect
% pick mode of aspect ratios
h = [pos(:).y2]' - [pos(:).y1]' + 1; % 所有正樣本的高度陣列
w = [pos(:).x2]' - [pos(:).x1]' + 1; % 所有正樣本的寬度陣列
xx = -2:.02:2;
filter = exp(-[-100:100].^2/400);
aspects = hist(log(h./w), xx);
aspects = convn(aspects, filter, 'same');
[peak, I] = max(aspects);
aspect = exp(xx(I));

% 選擇根濾波器的面積(以畫素為單位)
% pick 20 percentile area
areas = sort(h.*w); % 對面積從小到大排序
area = areas(floor(length(areas) * 0.2)); % 選擇從小到大20%處的面積
area = max(min(area, 5000), 3000); % 面積最大值5000,最小值3000

% 根據以上計算出的高寬比和麵積,得到根濾波器的高度和寬度(以畫素為單位)
% pick dimensions
w = sqrt(area/aspect); % 根的寬度(以畫素為單位),area=w*h,aspect=h/w,所以area/aspect = (w*h)*(w/h) = w^2
h = w*aspect; % 根的高度(以畫素為單位)

% HOG cell的尺寸,預設為8
% size of HOG features
if nargin < 4
  model.sbin = 8;
else
  model.sbin = sbin;
end

% 設定根濾波器尺寸(以cell為單位)
% size of root filter
if nargin < 5
  model.rootfilters{1}.size = [round(h/model.sbin) round(w/model.sbin)]; % 以畫素為單位的根的尺寸除以cell的尺寸,等於以cell為單位的根的尺寸
else
  model.rootfilters{1}.size = size;
end

% 初始化偏移量陣列
% 偏移量offset就是加在每個元件模型的得分公式最後的一個實數值,參見論文[2010 PAMI]中的公式(2)中的b值
model.offsets{1}.w = 0; % 元件1的偏移量的初始值設為0
model.offsets{1}.blocklabel = 1; % 元件1的偏移量的塊標識,值為1表明元件1的偏移量是模型中的第一個資料塊
model.blocksizes(1) = 1; % 第一個資料塊的大小,值為1,因為只用來儲存元件1的偏移量,即一個實數值
model.regmult(1) = 0;
model.learnmult(1) = 20;
model.lowerbounds{1} = -100; % 第一個資料塊的資料值的下界,-100

% 初始化根濾波器陣列
model.rootfilters{1}.w = zeros([model.rootfilters{1}.size 31]); % 元件1的初始根濾波器的向量值為全0
height = model.rootfilters{1}.size(1); % 元件1的根濾波器的高度
% root filter is symmetric 注意:根濾波器是左右對稱的
width = ceil(model.rootfilters{1}.size(2)/2); % 元件1的根濾波器的寬度的一半
model.rootfilters{1}.blocklabel = 2; % 元件1的根濾波器的塊標識
model.blocksizes(2) = width * height * 31; % 儲存元件1的根濾波器的資料塊(第二個資料塊)的大小,由於根濾波器是左右對稱的,所以是h*(w/2)*31
model.regmult(2) = 1;
model.learnmult(2) = 1;
model.lowerbounds{2} = -100*ones(model.blocksizes(2),1); % 第二個資料塊的值的下界,-100

% 初始化元件模型
% set up one component model
model.components{1}.rootindex = 1; % 元件1的根濾波器陣列索引
model.components{1}.offsetindex = 1; % 元件1的偏移量陣列索引
model.components{1}.parts = {}; % 元件1的部件資訊,當前為空
model.components{1}.dim = 2 + model.blocksizes(1) + model.blocksizes(2); % 元件1的模型引數向量維數
model.components{1}.numblocks = 2; % 元件1的資料塊個數

% 初始化剩下的模型引數
% initialize the rest of the model structure
model.interval = 10; % 金字塔每組的層數
model.numcomponents = 1; % 模型的元件個數
model.numblocks = 2; % 模型的總的資料塊個數
model.partfilters = {}; % 部件濾波器陣列
model.defs = {}; % 部件錨點陣列
model.maxsize = model.rootfilters{1}.size; % 所有元件的根濾波器的最大值
model.minsize = model.rootfilters{1}.size; % 所有元件的根濾波器的最小值


相關連結

Deformable Part Model 相關網頁http://www.cs.berkeley.edu/~rbg/latent/index.html

Pedro Felzenszwalb的個人主頁http://cs.brown.edu/~pff/

PASCAL VOC 目標檢測挑戰http://pascallin.ecs.soton.ac.uk/challenges/VOC/


A Discriminatively Trained, Multiscale, Deformable Part Model [CVPR 2008] 中文翻譯

Object Detection with Discriminatively Trained Part Based Models [PAMI 2010]中文翻譯

有關可變形部件模型(Deformable Part Model)的一些說明


在Windows下執行Felzenszwalb的Deformable Part Models(voc-release4.01)目標檢測matlab原始碼

在Windows下執行Felzenszwalb的star-cascade DPM(Deformable Part Models)目標檢測Matlab原始碼

在windows下執行Felzenszwalb的Deformable Part Model(DPM)原始碼voc-release3.1來訓練自己的模型

用DPM(Deformable Part Model,voc-release3.1)演算法在INRIA資料集上訓練自己的人體檢測模型

關於DPM(Deformable Part Model)演算法中模型結構的解釋




相關文章