公式完整版請移步[個人博客](..io/2018/07/03/harr%E7%89%B9%E5%BE%81%E5%8A%A0%E7%BA%A7%E8%81%94%E5%88%86%E7%B1%BB%E5%99%A8%E7%9A%84%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B%E7%B3%BB%E7%BB%9F/)1.識別系統架構
以上是Harr特征+級聯分類器的識別系統架構圖,系統分為以下幾個部分:
對于該目標識別器多特征融合分類器代碼,將目標檢測問題轉換為目標分類問題:滑動框在原圖上滑動,識別部分識別每一個滑動子圖,判斷是否為需要識別的目標。
1.1.Harr特征
Harr特征是一類非常簡單的特征,如下圖所示有四個框,這四個框的大小是可變的,使用黑色部分覆蓋的像素之和減去白色部分覆蓋的像素之和即為Harr特征:
Harr(x) = \sum pic_{black}(x) - \sum pic_{white}(x)
例如以下圖片示意:
取第一個4x4的區域數據計算第二種harr特征,被黑色覆蓋的區域和為3,被白色區域覆蓋的和為2,因此可獲得基于第二種模板下滑動框的harr特征為3-2=1。對于基于某一個模板,一個候選框可取多個特征,例如對于24x24的滑動框,基于第一種模板(對角線模板),可以在2x2,3x3,...,24x24等多個尺寸取特征,對于2x2的特征而言,也可以在24x24的框內取23x23個特征,因此,每個滑動框的harr特征數量都是海量的,在原論文中,使用20x20的滑動框,每個滑動框有約18k個特征值。
1.2.級聯分類器
由于Harr特征數量過多,已經幾乎超過任何一種機器學習算法的輸入特征數量極限(2001年),因此直接訓練一個分類器是不現實的,于是使用多個弱分類器組成一個強分類器的方法訓練。在本系統中,每一個弱分類器只針對一個單獨的特征:
h_j(x) = \begin{cases} 1 & f_j(x) < \ \\ 0 & other \end{cases}
該級聯分類器使用方法訓練,訓練分類器的同時也篩選特征,最終分類器的級數與使用的特征數量相同(每個分類器只使用一個特征)。最終的分類器為:
$$
h(x) = \begin{cases} 1 & \sum_\{t=1}^{T}(x) \geq \frac{1}{2}\sum\^T_{t=1}a_t \\ 0 & other \end{cases}
$$
T為級聯分類器的數量,同時也是選擇特征的數量,級聯分類器不使用的特征在計算Harr特征時可以不計算以減少計算量;$a_t$為單個分類器的權重,在訓練過程中得到。
2.訓練方法
需要訓練的部分為級聯分類器,由于每個弱分類器僅使用一個特征,因此每個弱分類器的參數為閾值$\$。訓練算法如下圖所示:
首先,初始化樣本權值$w_{1,i} = \begin{cases}\frac{1}{2m} & y_i = 0 \ \frac{1}{2l} & y_i = 1\end{cases}$,其中$y_i$為當前樣本的標簽,1表示正例;m和l為反例和正例的數量。進入訓練循環后,對于每次迭代:
首先標準化樣本權值$ w_{t,i} = \cfrac{w_{t,i}}{\sum^n_{j=1}w_{t,j}} $
根據每個特征訓練弱分類器$h(x)$,訓練過程中,代價函數與樣本權值有關,代價函數為$ \ = \|h_j(x_i)-y_i| $。
所有特征對應的弱分類器訓練完成后,選擇代價函數最低的分類器和對應特征,同時該特征從待選則特征中移除。
最后更新樣本權值:$ w_{t+1,i} = w_{t,i}\^{1-e_i} $,其中 e_i = \begin{cases}1 & \ \\ 0 & \end{cases},\ = \cfrac{\ }{1-\}
最終獲得分類器$h(x)$和每個分類器的權值$a_t = log\cfrac{1}{\}$。
3.加速方法
為了達到較快的檢測速度,該系統分別對計算Harr特征和級聯分類器提出了加速方案
3.1.積分圖
積分圖用于加速計算Harr特征,其方法是生成一個與原圖片大小相同的圖,使用以下公式:
$$
ii(x) = \sum\{x' \leq x,y' \leq y}{i(x',y')}
$$
如下圖所示,積分圖的數據為以圖片對應位置和圖片左上角連線為對角線的矩形覆蓋的所有像素的和。在按行生成計算圖的過程中,每個位置的值可以由計算圖上方的數據和這一行之前的累加與該位置的值相加得到,因此計算圖的生成比較簡單。
在計算harr特征時,需要計算大量的一定面積像素和,基于積分圖,若要計算以下計算區域的和多特征融合分類器代碼,僅需要計算:$A-B-C+D$即可,其中ABCD分別為積分圖對應位置的值,因此任何一個矩形區域的求和都可以用3次加減法計算完成,有效的加速了Harr特征的提取速度。
3.2.級聯計算
在基本級聯分類器需要計算全部所需要的Harr特征,盡管已經使用學習算法篩選過,特征數量仍然較多,基于大部分子圖中沒有需要識別的物品,提出了級聯的方法:
4.代碼實踐
4.1.使用自帶級聯分類器
自帶了一些級聯分類器,可以用于識別人臉,五官和人體等等,在下使用方法如下:
face_cascade = cv2.CascadeClassifier("./haarcascades/haarcascade_frontalface_alt2.xml")
faces = face_cascade.detectMultiScale(
gray, scaleFactor=1.3, minNeighbors=2, minSize=(60, 60), maxSize=(300, 300))
首先調用cv2.()打開一個級聯分類器,這里載入的xml為自帶的人臉識別級聯分類器,隨后調用.()方法進行識別,參數含義為:
該函數返回一個list,其中每個元素為一個有4個元素的list,分別是[x,y,w,h],可直接用于繪制矩形框。
4.2.訓練級聯分類器
選擇FDDB數據集訓練針對人臉的級聯分類器
4.2.1.處理標簽
FDDB的標注方式是橢圓形標注,提供橢圓形的中心,長短軸和角度信息,原label為\,先要將label轉為的格式??紤]簡便,使用以下公式:
$$
= clamp( - ,0,-1) \
top_y = clamp( - ,0,-1) \
width = 2 \times \
= 2 \times
$$
該公式簡單的將橢圓轉為矩形,clamp為鉗位函數,將輸入限制在0~-1,-1表示不限制。同時限制矩形的范圍一定在圖片范圍中。代碼如下:
def FDDB2label(source_path, target_path):
source_list = read_ellipseList(source_path) //讀取原有label文件
target_list = change_label(source_list) //轉換label格式
save_rec_label(target_list, target_path) //保存label格式

轉換label的部分如下:
def change_label(source):
"""source:list[[path,label],...],label:[major_axis_radius minor_axis_radius angle center_x center_y detection_score]"""
result = []
for name, label in source:
name = name + ".jpg"
data = [float(x) for x in label.replace(" ", ' ').split(' ')]
data = [int(data[3] - data[1]), int(data[4] - data[0]),
int(data[1] * 2), int(data[0] * 2)]
data = check_label(name, data, root="../FDDB-folds/")
result.append(
[name, data])
return result
檢查部分如下:
def check_label(name, data, root=""):
img_shape = cv2.imread(os.path.join(root, name)).shape
if data[0] < 0:
data[0] = 0
if data[1] < 0:

data[1] = 0
if data[0] + data[2] > img_shape[1]:
data[2] = img_shape[1] - data[0] - 1
if data[1] + data[3] > img_shape[0]:
data[3] = img_shape[0] - data[1] - 1
return data
共檢查兩種情況:
4.2.2.準備文件
訓練前需要準備數據,包括正例和反例。
4.2.2.1.準備正例
正例使用自帶的.exe生成,注意該exe文件不可獨立運行,因此不能拷貝出來使用,其依賴的其他文件,因此必須從中調用(\build\x64\vc14\bin\.exe),該工具將正例轉為.vec文件,主要有以下命令行參數:
使用之前,需要準備一個描述正例文件的文件info.dat,其格式如下:
FDDB-folds\2002\08\11\big\img_591.jpg 1 184 38 171 247
FDDB-folds\2002\07\19\big\img_423.jpg 1 196 46 118 174
FDDB-folds\2002\08\24\big\img_490.jpg 1 110 23 70 109
<相對路徑> <目標數量n> <目標1的x,y,w,h> ... <目標n的x,y,w,h>
隨后使用該工具,生成正例文件pos.vec。
.\opencv\build\x64\vc14\bin\opencv_createsamples.exe -vec .\pos.vec -info info.dat -num 178 -w 40 -h 40
4.2.2.2.準備反例
對于反例,反例只需要準備一個文件列表.dat即可:
.\dataset\negtive\neg_img2698.jpg
.\dataset\negtive\neg_img2699.jpg
.\dataset\negtive\neg_img2700.jpg
<相對路徑>
4.2.3.模型訓練
模型訓練使用的.exe,主要的參數如下:
本次使用的命令行參數如下圖所示:
.\opencv\build\x64\vc14\bin\opencv_traincascade.exe -data . -vec .\pos
.vec -bg .\neg_list.dat -numPos 178 -numNeg 200 -numStages 10 -w 40 -h 40
最終訓練的模型會保存在-data/.xml中。
4.2.4.模型測試
可以使用官方提供的測試工具.exe測試,該工具會可視化測試過程并打印使用的分類器的類型,命令行參數如下:
官方給出的例子如下:
.\opencv\build\x64\vc14\bin\opencv_visualisation --image=\data\object.png --model=\
data\model.xml --data=\data\result\
參考文獻
理論部分:Viola P, Jones M. Rapid using a of [C]// IEEE on & . IEEE , 2001:511.
實踐部分:官方教程——訓練級聯分類器