OpenCV如何实现口罩识别
本篇內容介紹了“OpenCV如何實現口罩識別”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
昨天在GitHub上看到了一個開源的項目,是利用深度學習來檢測是否有佩戴口罩的,感覺還挺好玩的,于是就去下載了訓練好的模型,打算用OpenCV的dnn模塊來跑一跑。然而,在經過前向傳播后,得到的推理矩陣prob是一個1x5972x2 的Mat矩陣,和之前遇到過的推理結果都不太一樣,在經過多種解碼方式的嘗試后,還是沒能夠對這個推理結果正確得解碼。并且在網上搜索也沒有找到相關的內容,幾乎沒有網友使用OpenCV來運行這個模型,基本都是使用深度學習的框架來運行。這就很無奈了,現在只能暫時把這個模型放一邊,等其他時候再來研究一下該怎么對它的推理結果進行解碼。
然而,我還是想嘗試一下做有無佩戴口罩的檢測,因為被勾起了好奇心哈哈哈哈哈哈哈哈哈哈,然后又因為使用開源項目的預訓練模型解碼失敗,一氣之下,我就想要不自己試一試搞一個。說搞就搞,由于本人對深度學習的涉及面并不深入,所以我的思路是:使用OpenCV的dnn模塊來進行人臉檢測及定位,然后將檢測出的人臉利用OpenCV的ml模塊進行識別是否佩戴口罩。
那么要做的第一步,就是訓練出我們需要的分類器,我選用OpenCV中ml模塊的SVM分類器來訓練口罩識別分類器。訓練部分的代碼如下:
stringpositive_path="D:\\opencv_c++\\opencv_tutorial\\data\\test\\positive\\";stringnegative_path="D:\\opencv_c++\\opencv_tutorial\\data\\test\\negative\\";vector<string>positive_images_str,negative_images_str;glob(positive_path,positive_images_str);glob(negative_path,negative_images_str);vector<Mat>positive_images,negative_images;for(inti=0;i<positive_images_str.size();i++){Matpositive_image=imread(positive_images_str[i]);positive_images.push_back(positive_image);}for(intj=0;j<negative_images_str.size();j++){Matnegative_image=imread(negative_images_str[j]);negative_images.push_back(negative_image);}stringsavePath="face_mask_detection.xml";trainSVM(positive_images,negative_images,savePath);
首先讀取所有的訓練圖像,包含正樣本(戴口罩)圖像和負樣本(不戴口罩)圖像,然后分別將正負樣本集打包成vector<Mat>類型,傳入訓練函數trainSVM()中,這個函數定義在頭文件 “face_mask.h” 中。
在訓練過程中,我們不是把圖像完全展開進行訓練,而是通過特征提取,得到每個樣本圖像的HOG特征,再計算每個HOG特征的特征描述子,通過特征描述子來訓練SVM分類器。
要注意的是,我們并不是對完整的樣本圖像進行HOG特征的提取與描述,而是對樣本圖像先進行人臉區域的提取,將提取出來的人臉區域圖像再進行HOG特征提取與描述并進行訓練。
同時,還需要對正負樣本集進行標注,正樣本標記為1,負樣本標記為-1。
代碼如下:
for(inti=0;i<positive_num;i++){Matpositive_face;Rectpositive_faceBox;if(faceDetected(positive_images[i],positive_face,positive_faceBox)){resize(positive_face,positive_face,Size(64,128));Matgray;cvtColor(positive_face,gray,COLOR_BGR2GRAY);vector<float>descriptor;hog_train->compute(gray,descriptor);train_descriptors.push_back(descriptor);labels.push_back(1);}}for(intj=0;j<negative_num;j++){Matnegative_face;Rectnegative_faceBox;if(faceDetected(negative_images[j],negative_face,negative_faceBox)){resize(negative_face,negative_face,Size(64,128));Matgray;cvtColor(negative_face,gray,COLOR_BGR2GRAY);vector<float>descriptor;hog_train->compute(gray,descriptor);train_descriptors.push_back(descriptor);labels.push_back(-1);}}intwidth=train_descriptors[0].size();intheight=train_descriptors.size();Mattrain_data=Mat::zeros(Size(width,height),CV_32F);for(intr=0;r<height;r++){for(intc=0;c<width;c++){train_data.at<float>(r,c)=train_descriptors[r][c];}}autotrain_svm=ml::SVM::create();train_svm->trainAuto(train_data,ml::ROW_SAMPLE,labels);train_svm->save(path);hog_train->~HOGDescriptor();train_svm->clear();
其中進行人臉提取的函數faceDetected()定義在頭文件 “face.h” 中。在這里我們使用opencv_face_detector_uint8.pb人臉檢測模型。
那么到這一步,就實現了檢測是否佩戴口罩的SVM分類器的訓練工作,訓練得到的模型文件如下:
接下來,我們就要加載這個xml文件并且對輸入的圖像進行檢測啦。其中,檢測用的的函數是FaceMaskDetect(),這個函數定義在 “face_mask.h” 頭文件中。
autodetecModel=ml::SVM::load("face_mask_detection.xml");Mattest_image=imread("D:/BaiduNetdiskDownload/人臉口罩檢測數據集/val/test_00004577.jpg");FaceMaskDetect(test_image,detecModel);imshow("test_image",test_image);
到這里,我們就實現了從訓練,到運行檢測的過程,下面來看一下運行的效果怎樣:
先看下沒帶口罩的圖像,如果檢測到沒佩戴口罩,那么人臉就用紅色框框出,而且標記紅色的 “ Not Face Mask ” 字樣:
如果是有佩戴口罩,那么就用綠色框框出人臉,并且標記 “ Face Mask ” :
從效果上來看,所采用的測試圖像都不在訓練集之內,對單個人臉的照片識別成功率還是可以的,但是肯定沒有開源項目里神經網絡模型的識別正確率高。而且我這里訓練的時候,正負樣本比例大約是1:2,總樣本集是四百多張訓練圖像,相比起開源項目里八千多張圖像的訓練集來說簡直是不值一提。
不過由于人臉檢測那一部分中,并沒有對同一幅圖像中出現多個人臉這種情況進行處理,以至于當一副圖像中出現多個人臉時,只會對其中人臉置信度最高的那個人進行佩戴口罩檢測,所以這個部分還需要進一步優化。
當然了,只對一張圖像進行檢測就沒啥意思了,我們同樣可以聯合攝像頭來實現實時檢測,演示代碼如下:
VideoCapture capture;capture.open(0);if (!capture.isOpened()){cout << "can't open camera" << endl;exit(-1);}Mat frame;while (capture.read(frame)){FaceMaskDetect(frame, detecModel);imshow("test_image", frame);char ch = waitKey(1);if (ch == 27){break;}}
總結
以上是生活随笔為你收集整理的OpenCV如何实现口罩识别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win 2016 ssh_如何使用BPF
- 下一篇: iphone7防水_什么是IP68防尘防