1、Emgu CV使用opencv人臉檢測,C#使用代碼(轉載於Emgu CV Example):
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using Emgu.CV;
using Emgu.CV.Structure;
#if !IOS
using Emgu.CV.Cuda;
#endif
namespace FaceDetection
{
public static class DetectFace
{
public static void Detect(
Mat image, String faceFileName, String eyeFileName,
List<Rectangle> faces, List<Rectangle> eyes,
bool tryUseCuda, bool tryUseOpenCL,
out long detectionTime)
{
Stopwatch watch;
#if !IOS
if (tryUseCuda && CudaInvoke.HasCuda)
{
using (CudaCascadeClassifier face = new CudaCascadeClassifier(faceFileName))
using (CudaCascadeClassifier eye = new CudaCascadeClassifier(eyeFileName))
{
watch = Stopwatch.StartNew();
using (CudaImage<Bgr, Byte> gpuImage = new CudaImage<Bgr, byte>(image))
using (CudaImage<Gray, Byte> gpuGray = gpuImage.Convert<Gray, Byte>())
{
Rectangle[] faceRegion = face.DetectMultiScale(gpuGray, 1.1, 10, Size.Empty);
faces.AddRange(faceRegion);
foreach (Rectangle f in faceRegion)
{
using (CudaImage<Gray, Byte> faceImg = gpuGray.GetSubRect(f))
{
//For some reason a clone is required.
//Might be a bug of CudaCascadeClassifier in opencv
using (CudaImage<Gray, Byte> clone = faceImg.Clone(null))
{
Rectangle[] eyeRegion = eye.DetectMultiScale(clone, 1.1, 10, Size.Empty);
foreach (Rectangle e in eyeRegion)
{
Rectangle eyeRect = e;
eyeRect.Offset(f.X, f.Y);
eyes.Add(eyeRect);
}
}
}
}
}
watch.Stop();
}
}
else
#endif
{
//Many opencl functions require opencl compatible gpu devices.
//As of opencv 3.0-alpha, opencv will crash if opencl is enable and only opencv compatible cpu device is presented
//So we need to call CvInvoke.HaveOpenCLCompatibleGpuDevice instead of CvInvoke.HaveOpenCL (which also returns true on a system that only have cpu opencl devices).
CvInvoke.UseOpenCL = tryUseOpenCL && CvInvoke.HaveOpenCLCompatibleGpuDevice;
//Read the HaarCascade objects
using (CascadeClassifier face = new CascadeClassifier(faceFileName))
using (CascadeClassifier eye = new CascadeClassifier(eyeFileName))
{
watch = Stopwatch.StartNew();
using (UMat ugray = new UMat())
{
CvInvoke.CvtColor(image, ugray, Emgu.CV.CvEnum.ColorConversion.Bgr2Gray);
//normalizes brightness and increases contrast of the image
CvInvoke.EqualizeHist(ugray, ugray);
//Detect the faces from the gray scale image and store the locations as rectangle
//The first dimensional is the channel
//The second dimension is the index of the rectangle in the specific channel
Rectangle[] facesDetected = face.DetectMultiScale(
ugray,
1.1,
10,
new Size(20, 20));
faces.AddRange(facesDetected);
foreach (Rectangle f in facesDetected)
{
//Get the region of interest on the faces
using (UMat faceRegion = new UMat(ugray, f))
{
Rectangle[] eyesDetected = eye.DetectMultiScale(
faceRegion,
1.1,
10,
new Size(20, 20));
foreach (Rectangle e in eyesDetected)
{
Rectangle eyeRect = e;
eyeRect.Offset(f.X, f.Y);
eyes.Add(eyeRect);
}
}
}
}
watch.Stop();
}
}
detectionTime = watch.ElapsedMilliseconds;
}
}
}
2、參數說明,人臉檢測耗時影響,精度影響
Rectangle[] facesDetected = face.DetectMultiScale(
ugray, //灰度圖像,單通道圖片
1.1, //scaleFactor 1.1~1.5 越大耗時越低、檢測精度越低
10, //minNeighbors 3~15 越高耗時越低
new Size(20, 20)); //最小臉部大小? //最大臉部大小, 越大耗時越低
DetectMultiScale支持多線程,
加載人臉識別模型可以全局初始化,減小耗時。
using (CudaCascadeClassifier face = new CudaCascadeClassifier(faceFileName))
using (CudaCascadeClassifier eye = new CudaCascadeClassifier(eyeFileName))