アウトライン
OpenCV4.0深ニューラルネットワークモジュールは、モデルがインポートopenface顔特徴ベクトル128、類似度比較、顔認識抽出をサポートしています。詳細については、こちらをOpenfaceモデルを参照してください
http://www.cv-foundation.org/openaccess/content_cvpr_2015/app/1A_089.pdf
主な原則は、それが導入されたときに、紙faceネットは2015 CVPRは、ネットワークベースの表示、こちらをクリックして詳細をお知りになりたい、昨年の記事を書いたということです
OpenCVの+ Tensorflowリアルタイム顔認識デモ
主なアイデア
次いで、画像またはビデオ、値、プレトレーニングモデルopenfaceの特徴によって抽出された顔領域128のコサイン類似度特性に顔検出のためOpenCV4.0 DNN第一支持顔検出モジュールモデルを使用値の比較、顔認識。次のように完全なプロセスを説明することができます。
コサイン類似度の式と解説:
コード実装手順
01
負荷ネットワーク
あなたは次のようにコードが実装され、ネットワークモデルopenface顔検出と顔認識をロードする必要があります。
String modelDesc = "D:/projects/opencv_tutorial/data/models/resnet/deploy.prototxt"; String modelBinary = "D:/projects/opencv_tutorial/data/models/resnet/res10_300x300_ssd_iter_140000.caffemodel"; String facemodel = "D:/projects/opencv_tutorial/data/models/face_detector/openface.nn4.small2.v1.t7"; // 初始化网络 Net net = readNetFromCaffe(modelDesc, modelBinary); Net netRecogn = readNetFromTorch(facemodel);
ダウンロードは以下のように、これらの2つのモデルがあります:
https://github.com/gloomyfish1998/opencv_tutorial/tree/master/data/models/face_detector
02
設定コンピューティングの背景
OpenCVのは、異なるコンピューティングの背景をサポートし、次のように、ここで我々は、コンピューティングの背景としてOpenVINOを使用し、コンピューティングは、加速することができます。
// 设置计算后台Net netRecogn = readNetFromTorch(facemodel);net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);net.setPreferableTarget(DNN_TARGET_CPU);netRecogn.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);netRecogn.setPreferableTarget(DNN_TARGET_CPU);// load face datavector<vector<float>> face_data;vector<string> labels;vector<string> faces;glob("D:/my_faces/zhigang", faces);for (auto fn : faces) { vector<float> fv; Mat sample = imread(fn); recognize_face(sample, netRecogn, fv); face_data.push_back(fv); printf("file name : %s\n", fn.c_str()); labels.push_back("zhigang");}faces.clear();glob("D:/my_faces/balvin", faces);for (auto fn : faces) { vector<float> fv; Mat sample = imread(fn); recognize_face(sample, netRecogn, fv); face_data.push_back(fv); printf("file name : %s\n", fn.c_str()); labels.push_back("balvin");}if (net.empty() || netRecogn.empty()){ printf("could not load net...\n"); return -1;}
03
顔検出
次のように顔検出ネットワークによって検出された顔のために、コードが実装されています。
// 输入数据调整Mat inputBlob = blobFromImage(frame, inScaleFactor, Size(inWidth, inHeight), meanVal, false, false);net.setInput(inputBlob, "data");// 人脸检测Mat detection = net.forward("detection_out");vector<double> layersTimings;double freq = getTickFrequency() / 1000;double time = net.getPerfProfile(layersTimings) / freq;Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());
04
フェイスアライメント
ROIは、リアルタイム検出とサンプルは最小距離が閾値T未満である見つけるために比較される面を与えるように予め装填され、出力は、認識、顔検出および分析顔認識コードの結果は以下の通りであります:
for (int i = 0; i < detectionMat.rows; i++){ // 置信度 0~1之间 float confidence = detectionMat.at<float>(i, 2); if (confidence > confidenceThreshold) { 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)); if (object.width < 5 || object.height < 5) { continue; } // 截取人脸ROI区域 Mat roi = frame(object); // 人脸比对,发现相似度最高的 vector<float> curr_fv; recognize_face(roi, netRecogn, curr_fv); float minDist = 10; int index = -1; for (int i = 0; i < face_data.size(); i++) { float dist = compare(curr_fv, face_data[i]); if (minDist > dist) { minDist = dist; index = i; } } // 阈值与显示识别结果 printf("index : %d, dist: %.2f \n", index, minDist); if (index >= 0 && minDist < 0.30) { putText(frame, labels[index].c_str(), Point(xLeftBottom, yLeftBottom-20), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 0, 255)); } rectangle(frame, object, Scalar(0, 255, 0)); ss.str(""); 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 compare(vector<float> &fv1, vector<float> fv2) { // 计算余弦相似, 0 ~ 1 距离,距离越小越相似, // 0表示夹角为0°,1表示夹角为90° float dot = 0; float sum2 = 0; float sum3 = 0; for (int i = 0; i < fv1.size(); i++) { dot += fv1[i] * fv2[i]; sum2 += pow(fv1[i], 2); sum3 += pow(fv2[i], 2); } float norm = sqrt(sum2)*sqrt(sum3); float similarity = dot / norm; float dist = acos(similarity) / CV_PI; return dist;}
業績