這段時間在學openCV,準備作一個頭部檢測,可是openCV自帶的分類器只有人臉檢測的,並且準確度不高,就準備本身訓練一個分類器。在網上看了不少的博客,都講得不是很清楚,並且全是在windows上訓練的,對與用習慣linux的我來講,用cmd實在是太痛苦了,而我沒有在網上找到這方面的博客,甚至連opencv_createsamples和 opencv_traincascade在哪都沒說只說在openCV目錄下,可是直接安裝的openCV下不少是沒有的,對於新手來說會很是迷茫,徹底搞不懂。html
而後我就到github上看openCV的倉庫,發現倉庫的apps目錄下有分類器源碼,以爲能夠本身在linux下編譯一個訓練器python
進過幾回嘗試,我發現openCV4以上版本源碼編譯出來是沒有我須要的這兩個訓練器的,3一下版本的會報錯,具體什麼緣由我不清楚,openCV-3.4.9版本的徹底沒有問題linux
sudo apt install cmake
官網:https://cmake.org/filesgit
或者執行命令github
wget https://cmake.org/files/v3.16/cmake-3.16.5-Linux-x86_64.tar.gz
網盤:連接: https://pan.baidu.com/s/1Or1gOkwCozmOTcwKBYErGA 密碼: uu89ubuntu
這裏我下載的是cmake-3.16.5-Linux-x86_64windows
解壓:tar zxvf cmake-3.16.5-Linux-x86_64.tar.gz 緩存
移到opt目錄下:mv cmake-3.16.5-Linux-x86_64 /optapp
創建軟鏈接:ln -s /opt/cmake-3.16.5-Linux-x86_64/bin/* /usr/binide
檢測安裝是否成功:
cmake --version
cmake version 3.16.5
CMake suite maintained and supported by Kitware (kitware.com/cmake).
github地址:https://github.com/opencv/openc
網盤地址:連接: https://pan.baidu.com/s/11drQWD-EjKVHwKmaNk4aRA 密碼: qfuf
我編譯好的:連接: https://pan.baidu.com/s/1STu5cLtAWIkaEns5eVTzOA 密碼: swmw
下面的步驟已經在Ubuntu10.04上測試過了,可是也能夠在其餘發行版上使用。
必需的包
GCC 4.4.x 或更新
CMake 2.8.7 或更高版本
Git
GTK+2.x 或更高版本, including 頭 (libgtk2.0-dev)
pkg-config
Python 2.6或更高版本以及帶有開發人員包的Numpy 1.5或更高版本(Python -dev, Python - Numpy)
ffmpeg或libav開發包:libavcodec-dev,libavformat-dev,libswscale-dev
[可選] libtbb2 libtbb-dev
[可選] libdc1394 2.x
[可選] libjpeg-dev, libpng-dev, libtiff-dev, libjasper-dev, libdc1394-22-dev
[可選] CUDA Toolkit 6.5 or higher
sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main"
sudo apt-get install build-essential
# 若是安裝了cmake 和git 的能夠刪下面的選項
sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev
解壓:unzip mirrors-opencv-3.4.9.zip
cd opencv
mkdir build # 編譯會生成不少文件,最好建一個文件夾來保存
cd build
cmake ../ # 生成makefile
make # 使用makefile編譯 時間會很長,二十分鐘的樣子
編譯好後就能夠找咱們須要的訓練器了
cd build/bin # 這樣就能夠看見了
建立pos目錄裝正樣本
正負樣本都要轉化成灰度圖,並且對於正樣本用haar特徵訓練是規格化成20×20或其餘大小,最好不要太大,過多的haar特徵會影響分類器的訓練時間;對於LBP特徵正樣本要規格化爲24×24大小,而對於HOG要規格化成64×64. 負樣本對尺寸沒有統一要求,在訓練對應的分類器時,選擇的負樣本尺寸必定要大於等於正樣本規定的尺寸。
建立neg目錄裝負樣本
負樣本有兩點要求:1)不能包含正樣本且儘量多的提供場景的背景圖;2)負樣本儘量的多,並且要多樣化,和正樣本有必定的差距可是差異也不要太大,不然容易在第一級就所有被分類器reject,訓練時不能顯示負樣本的個數,從而致使卡死。
建立xml目錄裝訓練數據
將訓練器opencv_createsamples opencv_traincascade拷貝到當前路徑下
ls -rt pos > pos.txt # pos.txt 正樣本相對路徑表
ls -rt neg > neg.txt # neg.txt 負樣本相對路徑表
修改pos.txt和neg.txt
gedit pos.txt
Ctrl + A 全選 ,而後按Tab 鍵
選一個空格
選擇查找替換
所有替換,neg.txt的這一步替換長neg/
pos.txt還須要多一步,不然會報錯,1 表明個數 0 0 表明照片的起點座標,50 50 爲個人照片的大小
./opencv_createsamples -info pos.txt -vec pos.vec -bg neg.txt -num 2874 -w 50 -h 50
以上參數的含義以下: -vec <vec_file_name>:訓練好的正樣本的輸出文件名。 -img<image_file_name>:源目標圖片 -bg<background_file_name>:背景描述文件。 -num<number_of_samples>:要產生的正樣本的數量,和正樣本圖片數目相同。 -bgcolor<background_color>:背景色。背景色制定了透明色。對於壓縮圖片,顏色方差量由bgthresh參數來指定。則在bgcolor-bgthresh 和bgcolor+bgthresh 中間的像素被認爲是透明的。 -bgthresh<background_color_threshold>
-inv:若是指定,顏色會反色 -randinv:若是指定,顏色會任意反色 -maxidev<max_intensity_deviation>:背景色最大的偏離度。 -maxangel<max_x_rotation_angle>, -maxangle<max_y_rotation_angle>, -maxzangle<max_x_rotation_angle>:最大旋轉角度,以弧度爲單位。 -show:若是指定,每一個樣本會被顯示出來,按下"esc"會關閉這一開關,即不顯示樣本圖片,而建立過程 繼續。這是個有用的debug 選項。 -w<sample_width>:輸出樣本的寬度(以像素爲單位) -h<sample_height>:輸出樣本的高度(以像素爲單位)
只須要對正樣本進行以上操做,負樣本不須要生成vec文件。。。
注意:這裏要找一臺好一點的電腦訓練,我訓練一萬的樣本,從最開始一天訓練一級,而後每級的時間增長半天,到第五級已經差很少須要三天了,預計到20級沒一兩月搞不定
./opencv_traincascade -data xml -vec pos.vec -bg neg.txt -numPos 2000 -numNeg 7370 -numStages 20 -featureType HAAR -w 50 -h 50
# 注意大小寫,寫錯可能不會報錯,可是識別不了,就會使用默認值,這裏我就被坑過
# 訓練時間會很是很是長,我第一次用了198正樣本、368負樣本就訓練了一個晚上,第二次用兩千多的正樣本,三千多的負樣本就更長了,可是訓練中途斷了再執行命令時會繼續上一次訓練
# 注意 :這裏的-numPos *** 必定要比 準備.vec文件時的 -num *** 小,不然在訓練時可能會報錯,顯示找不到更多正樣本
像我這裏輸入-numPos 2000 ,在訓練到第三級時就須要2018個正樣本,若是.vec裏只有2000個就會找不到新的正樣本,從而報錯
以上參數的含義以下:
-data <cascade_dir_name>:目錄用於保存訓練產生的分類器xml文件和中間文件,如不存在訓練程序會建立它;
-vec <vec_file_name>:由 opencv_createsamples 程序生成的包含正樣本的vec文件名;
-bg <background_file_name>:背景描述文件,也就是包含負樣本文件名的那個描述文件
-numPos <number_of_positive_samples>:每級分類器訓練時所用的正樣本數目(默認值爲2000); -numNeg <number_of_negative_samples>:每級分類器訓練時所用的負樣本數目,能夠大於 -bg 指定的圖片數目(默認值爲1000);
-numStages <number_of_stages>:訓練的分類器的級數(默認值爲20級);
-precalcValBufSize <precalculated_vals_buffer_size_in_Mb>:緩存大小,用於存儲預先計算的特徵值(feature values),單位爲MB(默認值爲256); -precalcIdxBufSize <precalculated_idxs_buffer_size_in_Mb>:緩存大小,用於存儲預先計算的特徵索引(feature indices),單位爲MB(默認值爲256);
內存越大,訓練時間越短。 -baseFormatSave:這個參數僅在使用Haar特徵時有效。若是指定這個參數,那麼級聯分類器將以老的格式存儲(默認不指定該參數項,此時其值爲false;一旦指定則其值默認爲true);
級聯參數:CvCascadeParams類,定義於cascadeclassifier.h -stageType <BOOST(default)>:級別(stage)參數。目前只支持將BOOST分類器做爲級聯的類型; -featureType<{HAAR(default), LBP}>:特徵的類型: HAAR - 類Haar特徵; LBP - 局部紋理模式特徵(默認Harr); -w <sampleWidth>:訓練樣本的寬(單位爲像素,默認24); -h <sampleHeight>:訓練樣本的高(單位爲像素,默認24); 訓練樣本的尺寸必須跟訓練樣本建立(使用 opencv_createsamples 程序建立)時的尺寸保持一致。
Boosted分類器參數:CvCascadeBoostParams類,定義於boost.h -bt <{DAB, RAB, LB, GAB(default)}>:Boosted分類器的類型(DAB - Discrete AdaBoost, RAB - Real AdaBoost, LB - LogitBoost, GAB - Gentle AdaBoost爲默認); -minHitRate <min_hit_rate>:分類器的每一級但願獲得的最小檢測率(默認值爲0.995),總的檢測率大約爲 min_hit_rate^number_of_stages; -maxFalseAlarmRate <max_false_alarm_rate>:分類器的每一級但願獲得的最大誤檢率(默認值爲0.5),總的誤檢率大約爲 max_false_alarm_rate^number_of_stages; -weightTrimRate <weight_trim_rate>:Specifies whether trimming should be used and its weight,一個還不錯的數值是0.95; -maxDepth <max_depth_of_weak_tree>:弱分類器樹最大的深度。一個還不錯的數值是1,是二叉樹(stumps);
-maxWeakCount <max_weak_tree_count>:每一級中的弱分類器的最大數目(默認值爲100)。The boosted classifier (stage) will have so many weak trees (<=maxWeakCount), as needed to achieve the given -maxFalseAlarmRate;
最後等一夜就能夠獲得訓練的分類器了,cascade.xml就是咱們的分類器
最後放上個人分類器連接
包含訓練5級的分類器和訓練15級的分類器,效果不是很好
連接: https://pan.baidu.com/s/17U3cGaZdGj6glBeWJThtLA 密碼: oc5b
import cv2
face = cv2.CascadeClassifier("./data/cascade.xml") #人臉識別
cap = cv2.VideoCapture(2)
while True:
ret, img = cap.read()
roi_color = 0
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #轉換爲灰度圖片,haar特徵都是在灰度上檢測
faces = face.detectMultiScale(gray,1.3,5) #參數1:灰度圖片數據 2:縮放比例 3:人臉大小不能小於5個像素
# 獲取寬高信息,我的臉畫方框
for (x,y,w,h) in faces:
# img:要畫的圖片,(x,y):起始座標 ,(x+w,y+h):寬高,顏色,線條寬度
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
cv2.imshow('10',img)
if cv2.waitKey(5) & 0xff == ord("q"):
break
cap.release()
cv2.destroyAllWindows()