您好,登錄后才能下訂單哦!
本篇內容介紹了“OpenCV如何實現口罩識別”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
昨天在GitHub上看到了一個開源的項目,是利用深度學習來檢測是否有佩戴口罩的,感覺還挺好玩的,于是就去下載了訓練好的模型,打算用OpenCV的dnn模塊來跑一跑。然而,在經過前向傳播后,得到的推理矩陣prob是一個1x5972x2 的Mat矩陣,和之前遇到過的推理結果都不太一樣,在經過多種解碼方式的嘗試后,還是沒能夠對這個推理結果正確得解碼。并且在網上搜索也沒有找到相關的內容,幾乎沒有網友使用OpenCV來運行這個模型,基本都是使用深度學習的框架來運行。這就很無奈了,現在只能暫時把這個模型放一邊,等其他時候再來研究一下該怎么對它的推理結果進行解碼。
然而,我還是想嘗試一下做有無佩戴口罩的檢測,因為被勾起了好奇心哈哈哈哈哈哈哈哈哈哈,然后又因為使用開源項目的預訓練模型解碼失敗,一氣之下,我就想要不自己試一試搞一個。說搞就搞,由于本人對深度學習的涉及面并不深入,所以我的思路是:使用OpenCV的dnn模塊來進行人臉檢測及定位,然后將檢測出的人臉利用OpenCV的ml模塊進行識別是否佩戴口罩。
那么要做的第一步,就是訓練出我們需要的分類器,我選用OpenCV中ml模塊的SVM分類器來訓練口罩識別分類器。訓練部分的代碼如下:
string positive_path = "D:\\opencv_c++\\opencv_tutorial\\data\\test\\positive\\"; string negative_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 (int i = 0; i < positive_images_str.size(); i++) { Mat positive_image = imread(positive_images_str[i]); positive_images.push_back(positive_image); } for (int j = 0; j < negative_images_str.size(); j++) { Mat negative_image = imread(negative_images_str[j]); negative_images.push_back(negative_image); } string savePath = "face_mask_detection.xml"; trainSVM(positive_images, negative_images, savePath);
首先讀取所有的訓練圖像,包含正樣本(戴口罩)圖像和負樣本(不戴口罩)圖像,然后分別將正負樣本集打包成vector<Mat>類型,傳入訓練函數trainSVM()中,這個函數定義在頭文件 “face_mask.h” 中。
在訓練過程中,我們不是把圖像完全展開進行訓練,而是通過特征提取,得到每個樣本圖像的HOG特征,再計算每個HOG特征的特征描述子,通過特征描述子來訓練SVM分類器。
要注意的是,我們并不是對完整的樣本圖像進行HOG特征的提取與描述,而是對樣本圖像先進行人臉區域的提取,將提取出來的人臉區域圖像再進行HOG特征提取與描述并進行訓練。
同時,還需要對正負樣本集進行標注,正樣本標記為1,負樣本標記為-1。
代碼如下:
for (int i = 0; i < positive_num; i++) { Mat positive_face; Rect positive_faceBox; if (faceDetected(positive_images[i], positive_face, positive_faceBox)) { resize(positive_face, positive_face, Size(64, 128)); Mat gray; cvtColor(positive_face, gray, COLOR_BGR2GRAY); vector<float> descriptor; hog_train->compute(gray, descriptor); train_descriptors.push_back(descriptor); labels.push_back(1); } } for (int j = 0; j < negative_num; j++) { Mat negative_face; Rect negative_faceBox; if (faceDetected(negative_images[j], negative_face, negative_faceBox)) { resize(negative_face, negative_face, Size(64, 128)); Mat gray; cvtColor(negative_face, gray, COLOR_BGR2GRAY); vector<float> descriptor; hog_train->compute(gray, descriptor); train_descriptors.push_back(descriptor); labels.push_back(-1); } } int width = train_descriptors[0].size(); int height = train_descriptors.size(); Mat train_data = Mat::zeros(Size(width, height), CV_32F); for (int r = 0; r < height; r++) { for (int c = 0; c < width; c++) { train_data.at<float>(r, c) = train_descriptors[r][c]; } } auto train_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” 頭文件中。
auto detecModel = ml::SVM::load("face_mask_detection.xml");Mat test_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如何實現口罩識別”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。