基于OpenCV训练口罩检测数据集并测试
以下內容是利用opencv自帶的訓練器opencv_traincascade.exe與opencv_createsamples.exe,來對口罩數據集進行訓練。內容是自己操作過程中的筆記,可能會有些雜亂,其他的可以查看一下參考資料。
文章目錄
- 0. 檢測器初體驗
- 1. 數據的準備
- 2. 創建正樣本vec文件
- 3. 訓練獲得xml文件
- 4. 利用訓練出來的cascade.xml來驗證
0. 檢測器初體驗
由于這里需要opencv自帶的xml文件,這里我用的是conda的虛擬環境,所以xml文件處于E:\anacanda\envs\pytorch\Lib\site-packages\cv2\data中,這里使用了一個關于人臉檢測的xml文件。
import cv2 #識別人臉的xml文件,構建人臉檢測器facexml_path = "E:/anacanda/envs/pytorch/Lib/site-packages/cv2/data/haarcascade_frontalface_default.xml" detector= cv2.CascadeClassifier(facexml_path) #獲取0號攝像頭的實例 cap = cv2.VideoCapture(0)while True:# 就是從攝像頭獲取到圖像,這個函數返回了兩個變量,第一個為布爾值表示成功與否,以及第二個是圖像。ret, img = cap.read()assert ret is True,"Cramae Capture Nothing"# 轉為灰度圖gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#獲取人臉坐標faces = detector.detectMultiScale(gray, 1.1, 3)for (x, y, w, h) in faces:#參數分別為 圖片、左上角坐標,右下角坐標,顏色,厚度cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)cv2.imshow('Test Detection', img)# 在10ms內等待按鍵,否則顯示下一幀,也就是10ms內按Esc退出循環if cv2.waitKey(10) == 27:breakcap.release() cv2.destroyAllWindows()這里體驗了一下opencv自帶的xml來構建人臉檢測器,但是,檢測得過程不是特別的穩定。關于opencv自帶的檢測器其實還有關于其他方面的,如下所示,具體的可以自行體驗。
1. 數據的準備
-
正樣本:僅包含被檢測物體的樣本,并且距離邊界盡量要小,圖片尺寸大小一致,附件需要有路徑還需要添加重復吃屬于目標圖片的矩形框。
eg:E:\學習\機器學習\數據集\mask2\positive\100000.jpg 1 0 0 20 20
ps:這里1表示當前圖片重復出現的次數是1, 0 0 50 50表示目標圖片大小是矩形框從(0,0)到(50,50)
-
負樣本:不包含被檢測物體的樣本,圖片尺寸大小無要求,路徑存放沒有要求。
eg:E:\學習\機器學習\數據集\mask2\negative\100000.jpg
這里口罩的數據集中的正樣本數為:352,負樣本數為:1053
- 正樣本名字處理腳本
這里對正樣本進行名字的添加處理我寫了一個腳本來實現,具體變現為:E:\學習\機器學習\數據集\mask2\positive\100000.jpg -> E:\學習\機器學習\數據集\mask2\positive\100000.jpg 1 0 0 20 20
import os# 讀取文件所有數據 rf = open(r"E:/學習/機器學習/數據集/mask2/positive/posdata.txt", "r") rdata = rf.readlines()# 改寫數據并保存 wdata = [] for data in rdata:oneline = data[:-1] + " 1 0 0 20 20\n"wdata.append(oneline)# 寫入數據 wf = open(r"E:/學習/機器學習/數據集/mask2/positive/posdata2.txt", "w") wf.writelines(wdata)# 關閉文件描述符 rf.close() wf.close()- 保存圖片文件名處理腳本
把圖片文件名保存在一個文件中,構建成一個函數使用.
不過這個操作可以通過使用cmd打開對應的文件夾,輸入:dir /b/s/p/w *.jpg > your_filename.txt 來實現,簡潔版本是:dir /b *.jpg > your_filename.txt
ps:dir /b *.jpg > your_filename.txt
輸入完了之后就會生成對應的file,里面存儲的是當前文件夾下全部后綴名為md的文件名。
2. 創建正樣本vec文件
opencv_createsamples.exe -vec pos.vec -info posdata.txt -num 352 -w 20 -h 20
成功獲得pos.vec文件
- info,指樣本說明文件
- vec,樣本描述文件的名字及路徑
- num,總共幾個樣本,要注意,這里的樣本數是指標定后的20x20的樣本數,而不是大圖的數目,其實就是樣本說明文件第2列的所有數字累加
- -w -h指明想讓樣本縮放到什么尺寸。
詳細參數見官方資料:https://docs.opencv.org/3.4.1/dc/d88/tutorial_traincascade.html
3. 訓練獲得xml文件
最后運行成功的代碼:
opencv_traincascade.exe -data xml -vec pos.vec -bg negdata.txt -numPos 100 -numNeg 300 -numStages 20 -w 20 -h 20 -mode ALL參數列表如下所示:
- data <cascade_dir_name>:應存儲經過訓練的分類器的位置。此文件夾應事先手動創建。
- vec <vec_file_name>: 帶有正樣本的 vec 文件(由 opencv_createsamples 實用程序創建)。
- bg <background_file_name>: 背景描述文件。這是包含負樣本圖像的文件。
- numPos <number_of_positive_samples>:每個分類器階段訓練中使用的正樣本數。
- numNeg <number_of_negative_samples>:每個分類器階段訓練中使用的負樣本數。
- numStages <number_of_stages>:要訓練的級聯階段數。
- precalcValBufSize <precalculated_vals_buffer_size_in_Mb>:預先計算的特征值的緩沖區大小(以 Mb 為單位)。您分配的內存越多,訓練過程就越快,但請記住,兩者的-precalcValBufSize總和-precalcIdxBufSize不應超過您可用的系統內存。
- precalcIdxBufSize <precalculated_idxs_buffer_size_in_Mb>:預先計算的特征索引的緩沖區大小(以 Mb 為單位)。您分配的內存越多,訓練過程就越快,但請記住,兩者的-precalcValBufSize總和-precalcIdxBufSize不應超過您可用的系統內存。
- baseFormatSave: 這個論點在 Haar-like 特征的情況下是真實的。如果指定,級聯將以舊格式保存。這只適用于向后兼容的原因,并允許用戶堅持使用舊的已棄用界面,至少可以使用較新的界面訓練模型。
- numThreads <max_number_of_threads>:訓練期間使用的最大線程數。請注意,實際使用的線程數可能會更少,具體取決于您的機器和編譯選項。默認情況下,如果您使用 TBB 支持構建 OpenCV,則會選擇最大可用線程,這是優化所必需的。
- acceptanceRatioBreakValue <break_value>:此參數用于確定您的模型應該保持學習的精確程度以及何時停止。一個好的指導原則是訓練不超過 10e-5,以確保模型不會過度訓練您的訓練數據。默認情況下,此值設置為 -1 以禁用此功能。
詳細參數見官方資料:https://docs.opencv.org/3.4.1/dc/d88/tutorial_traincascade.html
ps:這里需要小心調整numPos與numNeg的大小,這里指的每個分類器階段訓練中使用樣本數,設置得過大可能會引起錯誤。設置的numPos過大,由于訓練時pos count 會從你設置的numPos增大,每一級都按一定的次序增大,后來可能會超過樣本庫中正樣本的個數,就會報這個錯誤。
Error: Bad argument (Can not get new positive sample. The most
possible reason is insufficient count of samples in given vec-file.
根據參考資料3,這里設置調整的值一般滿足關系為:
- numneg (負樣本)數設置為總數的一半,或者其他值,
- numpos (正樣本)數設置為負樣本數的3分1
訓練完成后,得到最后的casce.xml文件
ps:這個xml的文件夾需要自己創建
整個bin的目錄文件如下所示:
在訓練過程中會出現了以下的問題:
1)Error: Bad argument (Can not get new positive sample. The most possible reason is insufficient count of samples in given vec-file
opencv_traincascade.exe -data xml -vec pos.vec -bg negdata.txt -numPos 500 -numNeg 656 -numStages 20 -w 20 -h 20 -mode ALL出現問題:
Error: Bad argument (Can not get new positive sample. The most
possible reason is insufficient count of samples in given vec-file
出現問題:
Error: Bad argument (Can not get new positive sample. The most
possible reason is insufficient count of samples in given vec-file.
問題原因:設置的numPos過大,由于訓練時pos count 會從你設置的numPos增大,每一級都按一定的次序增大,后來可能會超過樣本庫中正樣本的個數,就會報這個錯誤。
2)Required leaf false alarm rate achieved. Branch training terminated.
這不是一個錯誤。鑒于所提供的樣本設置,級聯已達到其預期的潛力。需要添加更多的數據或者設置更苛刻條件。
4. 利用訓練出來的cascade.xml來驗證
下面是調用攝像頭,利用剛剛訓練出來的xml文件來構建口罩的檢測器來對每一幀圖像進行檢測
import cv2# 構建兩個檢測器 facexml_path = "E:/anacanda/envs/pytorch/Lib/site-packages/cv2/data/haarcascade_frontalface_default.xml" maskxml_path = "E:/project/Opencv_Project/dataset/bin/xml/cascade.xml" face_detector = cv2.CascadeClassifier(facexml_path) mask_detector = cv2.CascadeClassifier(maskxml_path)# 獲取攝像頭的實例 cap = cv2.VideoCapture(0)# 不斷對每一幀進行處理 while True:# 返回的第一個參數是成功與否,第二個參數的一幀圖像ret, img = cap.read() assert ret is True,"Capture Noting" # 如果ret為空則報錯# 轉換為灰度圖gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)#獲取人臉坐標faces = face_detector.detectMultiScale(gray, 1.1, 3)# 依次遍歷人臉對象for (x, y, w, h) in faces:#參數分別為 圖片、左上角坐標,右下角坐標,顏色,厚度cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)face=img[y:y+h,x:x+w] # 裁剪坐標為[y0:y1, x0:x1]mask_face=mask_detector.detectMultiScale(face, 1.1, 5)for (x2,y2,w2,h2) in mask_face:cv2.rectangle(img, (x2, y2), (x2 + w2, y2 + h2), (0, 0, 255), 2)cv2.imshow('Mask Detection', img)# 在10ms內等待按鍵,否則顯示下一幀,也就是10ms內按Esc退出循環if cv2.waitKey(10) == 27:break# 釋放緩存,清理窗口 cap.release() cv2.destroyAllWindows()實驗結果:
這里我該了兩次參數訓練了兩個cascade.xml文件,但是效果好像都不好;另外我私下問了參考資料[3]的博主,拿了其提供的cascade.xml文件(這里表示感謝!!有需要的可以關注他的公眾號:矩陣科學),好像效果還是不太好,甚至沒有檢測出口罩,一方面可能是我電腦攝像頭不好,另一方面可能使用opencv提供的工具訓練不是很穩定。
有機會下次使用深度學習的方法來做一些口罩檢測的項目。
參考資料:
總結
以上是生活随笔為你收集整理的基于OpenCV训练口罩检测数据集并测试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ZJOI2018旅游记
- 下一篇: 爱 尔 兰 D e c a W a v