1. 程式人生 > >Python—OpenCV建立級聯檔案(Windows7/10環境)

Python—OpenCV建立級聯檔案(Windows7/10環境)

目錄

搭建環境

準備資料集

訓練級聯檔案


之前使用Python+OpenCV實現交通路標識別,具體實現步驟及心得如下:

OpenCV訓練屬於自己的xml檔案,需以下幾個步驟:

1、首先下載OpenCV(Windows版);       

2、準備資料集,分為正樣本集和負樣本集;

3、生成路徑,將正樣本集的路徑要存成 *.vec格式;負樣本集的路徑不做要求,*.txt就可以;

4、訓練xml檔案。

  • 搭建環境

OpenCV建立級聯檔案需要先下載OpenCV(Windows版)。

 接下來傻瓜式安裝操作,安裝到指定路徑。

安裝成功後開始配置環境變數(配置環境變數比較簡單,此處省略),稍後會用到OpenCV中的opencv_createsamples.exe和opencv_traincascade.exe檔案訓練級聯檔案,我的安裝路徑在D盤,所以設定環境變數的路徑是D:\opencv\opencv\build\x64\vc15\bin。 注意:若直接在D:\opencv\opencv\build\x64\vc15\bin路徑下訓練模型,可以不用配置環境變數。

  • 準備資料集

需要準備正樣本資料集(所要識別的物體)和負樣本資料集(背景圖片、干擾圖片),資料集數量越多種類越複雜越好。

通常正樣本資料裁剪為20*20或40*40大小的畫素即可(這裡我使用40*40畫素訓練模型,9小時+可以訓練完成),注意:畫素過大訓練速度相當慢,圖片畫素最好是正方形圖片,長寬相等。

通常負樣本資料集是識別物體的背景環境照片,圖片越多越複雜抗干擾能力越強,負樣本圖片可以不用裁剪為固定大小,但是為了提升訓練速度建議進行合理裁剪。

正樣本圖片如下:

 負樣本圖片如下:

 為了操作方便,我寫了Python程式實現批量調整圖片資料大小和圖片命名,具體如下:

# -*- coding:utf8 -*-
import os
from PIL import Image
'''
批量重新命名資料夾中的圖片檔案

'''
class BatchRename():
    def __init__(self):
        self.path = r'C:\Users\Administrator\Desktop\opencv-haar-classifier-training-master\positive_images'

    def rename(self):
        filelist = os.listdir(self.path)
        total_num = len(filelist)
        i = 0
        for item in filelist:
            if item.endswith('.jpg'):
                src = os.path.join(os.path.abspath(self.path), item)
                print(src)
                dst = os.path.join(os.path.abspath(self.path), str(i) + '.jpg')
                try:
                    os.rename(src, dst)
                    print ('converting %s to %s ...' % (src, dst))
                    i = i + 1
                except :
                    continue
        print ('total %d to rename & converted %d jpgs' % (total_num, i))

if __name__ == '__main__':
    demo = BatchRename()
    demo.rename()

'''
批量修改圖片尺寸
'''
#提取目錄下所有圖片,更改尺寸後儲存到另一目錄
import os.path
import glob
def convertjpg(jpgfile,outdir,width=40,height=40):
    img=Image.open(jpgfile)
    try:
        new_img=img.resize((width,height),Image.BILINEAR)   
        new_img.save(os.path.join(outdir,os.path.basename(jpgfile)))
    except Exception as e:
        print(e)
for jpgfile in glob.glob(r"C:\Users\Administrator\Desktop\opencv-haar-classifier-training-master\positive_images\*.jpg"):
    #畫素修改後存入images檔案
    convertjpg(jpgfile,r"C:\Users\Administrator\Desktop\opencv-haar-classifier-training-master\images")
  • 訓練級聯檔案

1、首先按照要求建立訓練資料夾

negative_images資料夾存放負樣本圖片。

positive_images資料夾存放正樣本圖片。

xml資料夾存放稍後生成的xml級聯檔案。

opencv_createsamples.exe負責生成*.vec檔案。

opencv_traincascade.exe負責訓練級聯檔案模型。

另外我還寫了兩個Python檔案負責批量處理圖片命名、尺寸縮小和生成對應的txt檔案。

2、生成指定的txt檔案路徑

執行這一步之前保證檔案已經命名規範,尺寸縮小到合適大小。

執行生成txt檔案.py檔案,生成對應的正樣本路徑和負樣本路徑檔案,效果如下:

資料夾結構如下:

正樣本路徑檔案(pos.txt)格式如下:

正樣本路徑檔案(neg.txt)格式如下:

 生成對應的txt檔案Python程式碼如下:

import os
'''
正樣本資料生成txt檔案
'''
file_dir=os.getcwd()
file_dir=r'C:\Users\Administrator\Desktop\opencv-haar-classifier-training-master\positive_images'
L=[]
i=0
with open("pos.txt","w+") as f:
    for root, dirs, files in os.walk(file_dir):  
        for file in files:  
            if os.path.splitext(file)[1] == '.jpg':  
                L.append(os.path.join(root, file))
                f.write(L[i]+' 1'+' 0'+' 0'+' 40'+' 40'+'\n')
                i+=1
'''
負樣本資料生成txt檔案
'''
file_dir=r'C:\Users\Administrator\Desktop\opencv-haar-classifier-training-master\negative_images'
L=[]
i=0
with open("neg.txt","w+") as f:
    for root, dirs, files in os.walk(file_dir):  
        for file in files:  
            if os.path.splitext(file)[1] == '.jpg':  
                L.append(os.path.join(root, file))
                f.write(L[i]+'\n')
                i+=1  

 3、獲取正樣本向量集vec檔案

在資料夾下新建createsamples.bat,批處理檔案,內容如下:

opencv_createsamples.exe -vec pos.vec  -info pos.txt -num 1100 -w 40 -h 40
pause

其中,-vec後面是將生成的正樣本向量集vec檔案,-info後面是正樣本路徑檔案,-num後面的數字是正樣本個數,-w後面的數字是正樣本圖片的長,-h後面的數字是正樣本圖片的高。 

雙擊createsamples.bat後出現pos.vec即為執行成功。

此時資料夾結構如下:

 4、訓練級聯檔案模型

 在資料夾下新建train.dat檔案,內容如下:

opencv_traincascade.exe -data xml -vec pos.vec -bg neg.txt -numPos 1100 -numNeg 3205 -numStages 15 -w 40 -h 40 -minHitRate 0.999 -maxFalseAlarmRate 0.5 -mode ALL 
pause

其中,-data 是存放訓練好的分類器的路徑 ,-vec 就是存放.vec的路徑, -bg 負樣本描述檔案, -numPos 每一階段訓練的正樣本數量 , -numNeg 每一階段訓練的負樣本數量 (網上說-numPos的引數要比實際正樣本數量小,-numNeg 的引數要比實際負樣本數量大 ), -numStages 訓練階段數 (這個引數不能太大也不能太小 ,太大訓練時間過長,如果太小的話 生成的xml文件分類效果可能就不太好 ), -featureType 選擇LBP還是HAAR 在此選用LBP ,-w -h 訓練樣本尺寸 和vec生成的尺寸大小相同 不然會宕機, -minHitRate  最小命中率 ,-maxFalseAlarmRate 最大虛警率 ,最後需要在加上 -mode ALL。

此時資料夾結構如下:

 雙擊train.bat後進入訓練模式,進入漫長等待,效果如下:

最後訓練完成之後級聯檔案儲存在xml資料夾中。

其中,只有第一個cascade.xml檔案是我們所需要的檔案,其餘檔案是訓練過程中生成的檢查的檔案,防止訓練過程中出現意外程式重頭訓練。 

下面使用Python程式碼進行模型測試,效果如下:

驗證Python程式碼如下:

import numpy as np
import cv2
face_cascade = cv2.CascadeClassifier('cascade.xml')
cap = cv2.VideoCapture(0)
while True:
    ret,img = cap.read()
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)
    for (x,y,w,h) in faces:
        cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
    cv2.imshow('img',img)       
    if cv2.waitKey(1) &0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

最後我將模型搭建在樹莓派上,發現識別效果,處理速度還是蠻不錯的。