Hi !
NET is in anniversary mode, so I think it will be a good idea to share some camera samples in C#. For these demos Iβm using C# 6 and OpenCVSharp as OpenCV wrapper for .NET.
Today post: detect a face using a DNN model and blur the face area. This demo also show the detected face in a separated window (just for fun). And I added the Frame per second (FPS) as additional information in the main window
Easy to implement, and also easy to read:
Code Sample
// Copyright (c) 2022 | |
// Author : Bruno Capuano | |
// Create Time : 2022 Feb | |
// Change Log : | |
// - Open a camera feed from a local USB webcam and analyze each frame to detect faces using a pretrained DNN model | |
// - Download model and prototxt from https://github.com/spmallick/learnopencv/tree/master/FaceDetectionComparison/models | |
// - When a face is detected, the app will blur the face zone in the main window | |
// - When a face is detected, the app will show the original detected face in a separated window | |
// - Press [F] to enable / disable the face detection process | |
// - Press [Q] to quit the app | |
// | |
// The MIT License (MIT) | |
// | |
// Permission is hereby granted, free of charge, to any person obtaining a copy | |
// of this software and associated documentation files (the "Software"), to deal | |
// in the Software without restriction, including without limitation the rights | |
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
// copies of the Software, and to permit persons to whom the Software is | |
// furnished to do so, subject to the following conditions: | |
// | |
// The above copyright notice and this permission notice shall be included in | |
// all copies or substantial portions of the Software. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
// THE SOFTWARE. | |
using OpenCvSharp; | |
using OpenCvSharp.Dnn; | |
// download model and prototxt from https://github.com/spmallick/learnopencv/tree/master/FaceDetectionComparison/models | |
const string configFile = "deploy.prototxt"; | |
const string faceModel = "res10_300x300_ssd_iter_140000_fp16.caffemodel"; | |
using var faceNet = CvDnn.ReadNetFromCaffe(configFile, faceModel); | |
var image = new Mat(); | |
var detectFaces = true; | |
var run = true; | |
using var capture = new VideoCapture(0); | |
using var window = new Window("El Bruno - Face Detector DNN"); | |
using var windowFace = new Window("Face"); | |
while (run) | |
{ | |
var startTime = DateTime.Now; | |
capture.Read(image); | |
if (image.Empty()) | |
break; | |
var newSize = new Size(640, 480); | |
using var frame = new Mat(); | |
Cv2.Resize(image, frame, newSize); | |
if (detectFaces) | |
{ | |
int frameHeight = frame.Rows; | |
int frameWidth = frame.Cols; | |
using var blob = CvDnn.BlobFromImage(frame, 1.0, new Size(300, 300), | |
new Scalar(104, 117, 123), false, false); | |
faceNet.SetInput(blob, "data"); | |
using var detection = faceNet.Forward("detection_out"); | |
using var detectionMat = new Mat(detection.Size(2), detection.Size(3), MatType.CV_32F, | |
detection.Ptr(0)); | |
for (int i = 0; i < detectionMat.Rows; i++) | |
{ | |
float confidence = detectionMat.At<float>(i, 2); | |
if (confidence > 0.7) | |
{ | |
int x1 = (int)(detectionMat.At<float>(i, 3) * frameWidth); | |
int y1 = (int)(detectionMat.At<float>(i, 4) * frameHeight); | |
int x2 = (int)(detectionMat.At<float>(i, 5) * frameWidth); | |
int y2 = (int)(detectionMat.At<float>(i, 6) * frameHeight); | |
Cv2.Rectangle(frame, new Point(x1, y1), new Point(x2, y2), Scalar.Green); | |
// create a new Mat with the detected face | |
var faceImg = new Mat(frame, | |
new OpenCvSharp.Range(y1, y2), | |
new OpenCvSharp.Range(x1, x2)); | |
windowFace.Image = faceImg; | |
// blur the face area in the original frame | |
var faceBlur = new Mat(); | |
Cv2.GaussianBlur(faceImg, faceBlur, new Size(23, 23), 30); | |
frame[new OpenCvSharp.Range(y1, y2), new OpenCvSharp.Range(x1, x2)] = faceBlur; | |
} | |
} | |
} | |
var diff = DateTime.Now - startTime; | |
var fpsInfo = $"FPS: Nan"; | |
if (diff.Milliseconds > 0) | |
{ | |
var fpsVal = 1.0 / diff.Milliseconds * 1000; | |
fpsInfo = $"FPS: {fpsVal:00}"; | |
} | |
Cv2.PutText(frame, fpsInfo, new Point(10, 20), HersheyFonts.HersheyComplexSmall, 1, Scalar.White); | |
window.Image = frame; | |
switch ((char)Cv2.WaitKey(100)) | |
{ | |
case (char)27: // ESC | |
run = false; | |
break; | |
case 'f': | |
detectFaces = !detectFaces; | |
break; | |
} | |
} |
Happy coding!
Greetings
El Bruno
Top comments (0)