基于机器学习的捡球机器人设计与实现(探索)第5篇——训练并使用Haar分类器(2019-03-02)
2019-03-03 by 崔斐然
2019-03-09 更新 視頻上傳到了b站?
不展示成品沒動力寫文章?
? ? ? ?昨天車架和電機之類的都到了,攝像頭準備用的以前玩的ps3 攝像頭 20塊錢,拍照質量渣渣。千萬不要買這款啊。
? ? ? ?那么剩下的任務就是讓小車能識別出網球了。在訓練自己的分類器前不妨先試試OpenCV自帶的分類器吧。
Demo:人臉檢測
? ? ? ?在pycharm中新建一個項目,找一張清晰的含有人臉的照片,找到OpenCV安裝目錄下的?haarcascades?,里面有很多OpenCV3官方訓練好的分類器,我們選擇haarcascade_frontalface_default.xml復制到項目里,為了方便調用重命名為face.xml。
? ? ? ? 測試環境Python3.6 OpenCV3.4,測試代碼:
BUT,你可能會遇到這樣的報錯:
Traceback (most recent call last):File "/Users/dave/PycharmProjects/OpenCVtest/2.py", line 7, in <module>gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) cv2.error: OpenCV(3.4.2) /opt/concourse/worker/volumes/live/9523d527-1b9e-48e0-7ed0-a36adde286f0/volume/opencv-suite_1535558719691/work/modules/imgproc/src/color.hpp:253: error: (-215:Assertion failed) VScn::contains(scn) && VDcn::contains(dcn) && VDepth::contains(depth) in function 'CvtHelper'這個錯誤很大原因因為你沒有使用絕對路徑。我曾經把圖片移動到img文件夾并使用/img/***.jpg相對路徑會報錯。
效果:
test pass!
? ? ? ?那么,我們想要識別其他物體如 顯示器 鍵盤 鼠標等怎么辦呢,辦法有兩個 其一 論壇搜索其他人共享的訓練好的分類器。其二 自己訓練分類器。
如果自己訓練Haar分類器主要步驟:
第0步,安裝OpenCV: 7步完成opencv的安裝
針對物體非剛性:如人臉(丑的帥的都是臉)
????因為人臉千變萬化,好看的不好看的都是人臉,圓的方的臉,被頭發遮住的臉,禿頭的臉,等等這就意味著我們要采集很多正樣本人臉信息,以便提取人臉的主要特征。因為Haar對光影變化比較敏感,針對眼球,鼻影等特征提出來,檢測視頻或者圖片中是否包含人臉時,和訓練結果集xml文件中記錄的特征對比,比如:有鼻子,有眼,就是人臉,OK。那訓練這樣物體的辦法如下:
? ? ? ? 1、搜集制作成千上萬張正樣本圖像,確保這些圖像中包含要檢測的對象
? ? ? ? 2、搜集制作成千上萬張負樣本圖像,什么圖片都行,但是確保要檢測的對象不在圖像中
(http://image-net.org是不錯的圖像資源站)
? ? ? ? 3、創建”積極”向量文件
? ? ? ? 4、使用OpenCV訓練Haar分類器
注意:正負樣本最好源于實際應用場地效果才會最好。
針對剛性物體的辦法:如網球 (都長一個樣)
? ? ? ? 如果像我這樣網球不好采集怎么辦呢,或者網球這樣子不像人臉那樣有諸多特征,這樣可能只需要一張網球全身照就可以了,不過這樣在實際效果中可能差一點(網球也有logo之類不同),可以這樣辦:
? ? ? ? 1、opencv_createsamples命令創建pos.txt文件。它會把要識別的圖片嵌入到消極圖像中,允許我們快速創建”積極”圖像。
? ? ? ? 2、搜集制作成千上萬張負樣本圖像,什么圖片都行,但是確保要檢測的對象不在圖像中
(http://image-net.org是不錯的圖像資源站)
? ? ? ? 3、創建”積極”向量文件
? ? ? ? 4、使用OpenCV訓練Haar分類器
step 1 and 2 采集
? ? ? ?因為是畢設,我想讓預期達到最佳效果,所以才用的是采集大量不同的正負樣本訓練,我還在家,沒有場地,所以網上搜了400張網球照片和1200張負樣本,(截400張圖手指都抽筋,不采集了)如下:
? ? ? ?百度爬的照片然后一張一張裁的 笨辦法。。我感覺負樣本質量可能不好,后面果然出了問題?
? ? ? ?采集好之后我找了個windows電腦,用美圖秀秀批處理成灰度圖然后序列化重命名(重命名這一步可以不做)?其中,按照OpenCV官方建議正樣本是20像素x20像素,但是哪樣的話網球就太模糊了,所以就調整為50X50像素了(是否影響最終效果我弄懂了再修改=_=)。 負樣本除了灰度以外不必調整,分辨率自由。
(2019-03-08更新:采用50x50像素后識別效果好了很多,但同時訓練時間也是成倍增加,在20X20像素下大約3-5分鐘訓練完成。50x50下9小時完成)
(2019-03-14更新:分辨率的選擇可以參考另外一個博主的文章 https://blog.csdn.net/qq_37791134/article/details/80583726)
就這樣 我把正樣本也就是有網球的圖片放在了pos文件夾中,把消極圖片放在了neg文件夾中。
然后創建正負樣本目錄,格式如下:
< 絕對路徑 1 0 0 w h >
在這里有個簡單的方法創建pos.txt文件,我用的Windows 下的這個命令:
這句話的意思是將當前目錄下的文件名寫入到pos.txt文件中,當然最后一行會多出來///pos.txt,需要把這一行刪掉。「特別注意:如果在Mac或者服務器等其他地方訓練記得把pos.txt 和 neg.txt文件的絕對路徑修改正確」
其中 /***/***/***.jpg是圖片的絕對路徑
1 指只這個目錄下只有1個文件
0 0 指的是正樣本從像素的00位置(左上角開始)到20 20(圖像的尺寸) 位置結束是正樣本。
如果你的尺寸和我的不一樣后面那個值改為你的像素即可。
再然后創建負樣本路徑:這里只需寫絕對路徑即可。
step 3:創建向量
一行代碼:
cd 你的pos.txt所在目錄opencv_createsamples -info pos.txt -num 400 -w 20 -h 30 -vec pos.vecpop.txt 是上一步驟的正向量目錄文件
num是其中的正樣本數量,
w是寬h高
pos.vec是生成的正向量文件名
step 4:開始訓練
在你的電腦或者服務器切換到你的工作目錄,我的是
–/boost
----/data (空文件夾,用于存儲訓練結果)
----/neg (消極圖片)
----/pos (積極圖片)
----/pos.txt (積極圖片的絕對路徑等)
----/pos.vec (生成的積極向量)
我的參數:
mkdir data $ opencv_traincascade -data data -vec pos.vec -bg neg.txt -numPos 320 -numNeg 960 -numStages 15 -w 20-h 20????我在服務器訓練的,使用的156G運行內存,在上述命令尾部添加了-mem 150000.實際占用不了這么多,在20x20像素下占用了2-4GB 60x60像素下占用了20-25GB 。訓練的特征值會存入到內存中。在一定條件下內存越大理論訓練速度越快
opencv_createsamples各個參數的意義:
-data:指定保存訓練結果的文件夾;
-vec:指定正樣本集;
-bg:指定負樣本的描述文件夾;
-numPos:指定每一級參與訓練的正樣本的數目(要小于正樣本總數,一般取值85%左右);
-numNeg:指定每一級參與訓練的負樣本的數目(可以大于負樣本圖片的總數,大于的話就會自動裁剪負樣本訓練);
-numStage:訓練的級數;
-w:正樣本的寬;
-h:正樣本的高;
-mem 1280 表示允許使用計算機的1280M內存
-minHitRate:每一級需要達到的命中率(一般取值0.95-0.995);
-maxFalseAlarmRate:每一級所允許的最大誤檢率;
-mode:使用Haar-like特征時使用,可選BASIC、CORE或者ALL;
-featureType:可選HAAR或LBP,默認為HAAR;
????如果你在ssh遠程登陸服務器上訓練的話,建議采用screen窗口來執行,以免訓練時間過長網絡不穩定或者ssh超時等中斷訓練。具體請參見:
樹莓派安裝screen保證SSH斷開任務不中斷
????開始時候忘記截圖了,這邊的是訓練完成的截圖??梢钥吹较旅娴腞equird leaf false alarm rate achieved …… 這個意思是設置的訓練層數過多,設置的15層,實際在11層時候就已經達到了預期效果。
ojbk,現在你會發現在data目錄下多了很多文件,(服務器關了沒截圖=_=),里面的cascade.xml是我們訓練好的級聯分類器?,F在來使用我們自己的這個分類器吧。
Demo和上面的人臉識別一樣,只需要把Demo中cascade.xml替換為我們的就行,Example:
import cv2 # 載入分類器 face_haar = cv2.CascadeClassifier('cascade2.xml') # 載入測試圖 img = cv2.imread('z2.jpg') # 轉換彩色空間 gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) # cv2.imshow('theImg',gray_img) #窗口顯示faces=face_haar.detectMultiScale(gray_img,1.1,2) #目標檢測 # xy是ball起點位置,w h是寬高 for x,y,w,h in faces:# 創建包含圖像的最小矩形cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)cv2.imshow('img',img) #窗口顯示cv2.waitKey(0) cv2.destroyAllWindows()用的20塊錢還包郵的ps3攝像頭,夜間拍攝,能識別出來已經謝天謝地了。
你可能第一次出現檢測不到的情況,別急,試著調節以下參數:
可以吧比例因子 1.1 改為1.2或者1.3試試,minNeighbors 2改為3或者1試試
detectMultiScale函數參數解釋:
cv.CascadeClassifier.detectMultiScale( image [,scaleFactor [,minNeighbors [,flags [,minSize [,maxSize [,outputRejectLevels]]]]]] )image : CV_8U類型的矩陣,包含檢測到對象的圖像。
scaleFactor : 比例因子 參數指定在每個圖像比例下圖像尺寸減少的程度。
minNeighbors: 參數指定每個相鄰候選矩形應保留多少個。
flag標志位:3.X新的級聯已放棄治療。
minSize屬性 最小可能的對象大小。小于該值的對象將被忽略。比如偏遠的網球太小了可以忽略
MAXSIZE 最大可能的對象大小。大于該值的對象將被忽略。
同時,如果maxSize == minSize模型是單一尺度評估的。可以用于檢測正視圖中同一水平線的網球。
詳細可以參考官方文檔或閱讀源碼:https://www.docs.opencv.org/3.4/d1/de5/classcv_1_1CascadeClassifier.html#aaf8181cb63968136476ec4204ffca498
????至此,已經完成了基于Haar分類器的網球識別。再往下呢,不如開啟攝像頭識別下吧。
Demo:
已經23:20了不寫注釋了
test:
視頻怎么上傳啊???黑人問號
總結
以上是生活随笔為你收集整理的基于机器学习的捡球机器人设计与实现(探索)第5篇——训练并使用Haar分类器(2019-03-02)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于机器学习的捡球机器人设计与实现(探索
- 下一篇: 基于机器学习的捡球机器人设计与实现(探索