日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ DNN Opencv3.4 实现人脸计数和人脸检测

發(fā)布時間:2025/3/11 c/c++ 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ DNN Opencv3.4 实现人脸计数和人脸检测 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

OpenCV 3.3正式發(fā)布后,對深度學習(dnn模塊)提供了更好的支持,dnn模塊目前支持Caffe、TensorFlow、Torch、PyTorch等深度學習框架。

另外,新版本中使用預(yù)訓練深度學習模型的API同時兼容C++和Python,讓系列操作變得非常簡便

  • 從硬盤加載模型;
  • 對輸入圖像進行預(yù)處理;
  • 將圖像輸入網(wǎng)絡(luò),獲取輸出的分類。

當然,我們不能、也不該用OpenCV訓練深度學習模型,但這個新版本讓我們能把用深度學習框架訓練好了的模型拿來,高效地用在OpenCV之中。

在很久很久以前,用Opencv2.4x跟Opencv3.0進行人臉檢測的時候,都是基于HAAR級聯(lián),但是我測試過HAAR級聯(lián),明顯不太準,而且速度慢。但是現(xiàn)在2020年啦,深度學習的快速發(fā)展,使人臉檢測 越來越精準,在Opencv4發(fā)布以來,官方支持的人臉檢測方法已經(jīng)轉(zhuǎn)換為支持深度學習的快準狠的方法了,就連HAAR級聯(lián)訓練的工具都在Opencv4中除名了,其實已經(jīng)有了支持深度學習的人臉檢測算法,并且準確率和速度都比HAAR好,那再學HAAR級聯(lián)無疑是浪費時間和精力了,要學會跟著時代的步伐嘛,所以與時俱進很重要的。

注意:本文不涉及任何原理,只講具體的應(yīng)用。

一、下載模型文件

在OpenCV的\sources\samples\dnn\face_detector目錄下,有一個download_weights.py腳本文件,首先運行一下,下載模型文件。下載的模型文件分別為:
Caffe模型:

res10_300x300_ssd_iter_140000_fp16.caffemodel
deploy.prototxt

tensorflow模型:

opencv_face_detector_uint8.pb
opencv_face_detector.pbtxt

pb文件的能夠保存tensorflow計算圖中的操作節(jié)點以及對應(yīng)的各張量,方便我們?nèi)蘸笾苯诱{(diào)用之前已經(jīng)訓練好的計算圖。

其中tensorflow的模型OpenCV官方對它進行了量化處理,大小只有2MB左右,非常適合在各種場景下使用。

如果沒有安裝python,我將這幾個模型文件上傳到了網(wǎng)盤,直接下載下來就可以了。

鏈接:https://pan.baidu.com/s/19XUTKXBriInd9goHWBwLSg?
提取碼:fye8

二、演示代碼

1.讀入模型文件

String modelDesc = "D:/VC projects/dnn_face_detection-model/opencv_face_detector.pbtxt"; String modelBinary = "D:/VC projects/dnn_face_detection-model/opencv_face_detector_uint8.pb";
  • 1
  • 2

2.初始化網(wǎng)絡(luò),讀入權(quán)重和網(wǎng)絡(luò)結(jié)構(gòu),調(diào)用cv::dnn對應(yīng)的后端設(shè)置函數(shù)

dnn::Net net = readNetFromTensorflow(modelBinary, modelDesc); net.setPreferableBackend(DNN_BACKEND_OPENCV); net.setPreferableTarget(DNN_TARGET_CPU);
  • 1
  • 2
  • 3

這樣子程序再運行dnn計算時,用CPU運行。
當然也可以用GPU加速:

// when using opencv 4 and data > 20191022, the cuda is support net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA); net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
  • 1
  • 2
  • 3

3.對輸入數(shù)據(jù)進行調(diào)整。

Mat inputBlob = blobFromImage(frame, inScaleFactor, Size(inWidth, inHeight), meanVal, false, false);
  • 1

4.輸入、輸出

net.setInput(inputBlob, "data"); //detection返回值標簽、置信度、目標位置的4個坐標信息[xmin ymin xmax ymax] Mat detection = net.forward("detection_out");
  • 1
  • 2
  • 3

完整代碼:

#include <opencv2/dnn.hpp> #include <opencv2/opencv.hpp>using namespace cv; using namespace cv::dnn;#include <iostream> #include <cstdio> using namespace std;const size_t inWidth = 300; const size_t inHeight = 300; const double inScaleFactor = 1.0; //為了減去平均值(mean):為了消除同一場景下不同光照的圖片,對我們最終的分類或者神經(jīng)網(wǎng)絡(luò)的影響,我們常常對圖片的R、G、B通道的像素求一個平均值,然后將每個像素值減去我們的平均值,這樣就可以得到像素之間的相對值,就可以排除光照的影響。 const Scalar meanVal(104.0, 177.0, 123.0); const float confidenceThreshold = 0.7; void face_detect_dnn(); void mtcnn_demo(); int main(int argc, char** argv) {face_detect_dnn();waitKey(0);return 0; } void face_detect_dnn() {//讀入模型路徑//String modelDesc = "D:/VC projects/dnn_face_detection-model/deploy.prototxt";//String modelBinary = "D:/VC projects/dnn_face_detection-model/res10_300x300_ssd_iter_140000_fp16.caffemodel";String modelDesc = "D:/VC projects/dnn_face_detection-model/opencv_face_detector.pbtxt";String modelBinary = "D:/VC projects/dnn_face_detection-model/opencv_face_detector_uint8.pb";//初始化網(wǎng)絡(luò)//dnn::Net net = readNetFromCaffe(modelDesc, modelBinary);dnn::Net net = readNetFromTensorflow(modelBinary, modelDesc);net.setPreferableBackend(DNN_BACKEND_OPENCV);net.setPreferableTarget(DNN_TARGET_CPU);if (net.empty()) {printf("could not load net...\n");return;}//打開攝像頭//VideoCapture capture("D:/images/video/Boogie_Up.mp4");VideoCapture capture(0);if (!capture.isOpened()) {printf("Could not load camera...\n");return;}Mat frame;int count = 0;while (capture.read(frame)) {//用于返回從操作系統(tǒng)啟動到當前所經(jīng)的計時周期數(shù)int64 start = getTickCount();if (frame.empty()) break;//水平鏡像調(diào)整//flip(frame, frame, 1);imshow("input", frame);if (frame.channels() == 4) cvtColor(frame, frame, COLOR_BGRA2BGR);//輸入數(shù)據(jù)調(diào)整/*深度學習或圖片分類的預(yù)處理blobFromImage1.整體像素值減去平均值(mean)2.通過縮放系數(shù)(scalefactor)對圖片像素值進行縮放*/Mat inputBlob = blobFromImage(frame, inScaleFactor, Size(inWidth, inHeight), meanVal, false, false);net.setInput(inputBlob, "data");//人臉檢測Mat detection = net.forward("detection_out");//detection返回值標簽、置信度、目標位置的4個坐標信息[xmin ymin xmax ymax]vector<double> layersTimings;//用于返回CPU的頻率,也就是一秒內(nèi)重復(fù)的次數(shù)//1000 *總次數(shù)/一秒內(nèi)重復(fù)的次數(shù)= 時間(ms)double freq = getTickFrequency() / 1000;double time = net.getPerfProfile(layersTimings) / freq;Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());ostringstream ss;for (int i = 0; i < detectionMat.rows; ++i) {//置信度0-1之間float confidence = detectionMat.at<float>(i, 2);if (confidence > confidenceThreshold) {count++;//坐標int xLeftBottom = static_cast<int>(detectionMat.at<float>(i, 3)*frame.cols);int yLeftBottom = static_cast<int>(detectionMat.at<float>(i, 4) * frame.rows);int xRightTop = static_cast<int>(detectionMat.at<float>(i, 5) * frame.cols);int yRightTop = static_cast<int>(detectionMat.at<float>(i, 6) * frame.rows);//畫框Rect object((int)xLeftBottom, (int)yLeftBottom,(int)(xRightTop - xLeftBottom),(int)(yRightTop - yLeftBottom));rectangle(frame, object, Scalar(0, 255, 0));ss << confidence;//添加標簽String conf(ss.str());String label = "Face: " + conf;int baseLine = 0;Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);rectangle(frame, Rect(Point(xLeftBottom, yLeftBottom - labelSize.height),Size(labelSize.width, labelSize.height + baseLine)),Scalar(255, 255, 255), FILLED);putText(frame, label, Point(xLeftBottom, yLeftBottom),FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0));}}float fps = getTickFrequency() / (getTickCount() - start);ss.str("");ss << "FPS:" << fps << ";inference time: " << time << " ms";putText(frame, ss.str(), Point(20, 20), 0, 0.75, Scalar(0, 0, 255), 2, 8);imshow("dnn_face_detect", frame);if (waitKey(1) >= 0) break;}printf("total face: %d\n", count); }

總結(jié)

以上是生活随笔為你收集整理的C++ DNN Opencv3.4 实现人脸计数和人脸检测的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。