C# OpenCV 강좌 : 제 29강 - 얼굴 검출

   

얼굴 검출 (Haar Classifier Cascade)


1 영상이나 이미지에서 얼굴이 존재하는 위치를 알려주는 알고리즘입니다. 얼굴 인식이 아닌 얼굴 형태의 패턴을 찾아 얼굴을 검출해주는 알고리즘(Face Detection)입니다.


Haar Classifier Cascade 다운로드 : 다운로드

위의 파일을 다운로드합니다. 압축 해제 후 xml파일을 프로젝트 경로에 저장합니다.


절대경로, 상대경로란? : 22강 바로가기


원본(Source, src)를 영상이나 이미지를 사용하면 됩니다.

영상 사용하기 : 3강 바로가기
이미지 사용하기 : 4강 바로가기


Class


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;

namespace test
{
    class OpenCV : IDisposable
    {  
        IplImage haarface;
         
        public IplImage FaceDetection(IplImage src)
        {
            haarface = new IplImage(src.Size, BitDepth.U8, 3);
            Cv.Copy(src, haarface);

            const double scale = 0.9;
            const double scaleFactor = 1.139;
            const int minNeighbors = 1;

            using (IplImage Detected_image = new IplImage(new CvSize(Cv.Round(src.Width / scale), Cv.Round(src.Height / scale)), BitDepth.U8, 1))
            {
                using (IplImage gray = new IplImage(src.Size, BitDepth.U8, 1))
                {
                    Cv.CvtColor(src, gray, ColorConversion.BgrToGray);
                    Cv.Resize(gray, Detected_image, Interpolation.Linear);
                    Cv.EqualizeHist(Detected_image, Detected_image);
                }
                
                using (CvHaarClassifierCascade cascade = CvHaarClassifierCascade.FromFile("../../haarcascade_frontalface_alt.xml"))
                using (CvMemStorage storage = new CvMemStorage())
                {
                    CvSeq<CvAvgComp> faces = Cv.HaarDetectObjects(Detected_image, cascade, storage, scaleFactor, minNeighbors, HaarDetectionType.ScaleImage, new CvSize(90, 90), new CvSize(0, 0));

                    for (int i = 0; i < faces.Total; i++)
                    {
                        CvRect r = faces[i].Value.Rect;
                        CvPoint center = new CvPoint
                        {
                            X = Cv.Round((r.X + r.Width * 0.5) * scale),
                            Y = Cv.Round((r.Y + r.Height * 0.5) * scale)
                        };
                        int radius = Cv.Round((r.Width + r.Height) * 0.25 * scale);
                        haarface.Circle(center, radius, CvColor.Black, 3, LineType.AntiAlias, 0);
                    }
                }
                return haarface;
            }
        }
       
        public void Dispose()
        {
            if (haarface != null) Cv.ReleaseImage(haarface);
        }
    }
}


Class Code


haarface = new IplImage(src.Size, BitDepth.U8, 3);
Cv.Copy(src, haarface);

haarface는 원본을 복사한 이미지입니다.


const double scale = 0.9;
const double scaleFactor = 1.139;
const int minNeighbors = 1;

scale은 검출되는 이미지의 비율입니다. scaleFactorminNeighbors의 값은 얼굴 검출시에 사용되는 상수입니다.

scaleFactor1 이상의 값을 사용합니다. minNeighbors 또한 1 이상의 값을 사용합니다.


using (IplImage Detected_image = new IplImage(new CvSize(Cv.Round(haarface.Width / scale), Cv.Round(haarface.Height / scale)), BitDepth.U8, 1))
{
    ...
}

검출되는 이미지인 Detected_imagescale의 비율에 맞게 재조정합니다.


using (IplImage gray = new IplImage(haarface.Size, BitDepth.U8, 1))
{
    Cv.CvtColor(haarface, gray, ColorConversion.BgrToGray);
    Cv.Resize(gray, Detected_image, Interpolation.Linear);
    Cv.EqualizeHist(Detected_image, Detected_image);
}
    

Cv.CvtColorCv.Resize를 통하여 이미지의 크기를 조정합니다.

Cv.EqualizeHist(원본, 결과)를 통하여 GrayScale 이미지의 화상을 평탄화 시킵니다. 이 작업을 통하여 매우 어둡거나 매우 밝은 부분들이 일정하게 조정됩니다.


using (CvHaarClassifierCascade cascade = CvHaarClassifierCascade.FromFile("../../haarcascade_frontalface_alt.xml"))
using (CvMemStorage storage = new CvMemStorage())

cascadehaarcascade_frontalface_alt.xml 파일의 경로를 입력합니다. storage를 선언하여 메모리 저장소를 생성합니다.


CvSeq<CvAvgComp> faces = Cv.HaarDetectObjects(Detected_image, cascade, storage, scaleFactor, minNeighbors, HaarDetectionType.ScaleImage, new CvSize(90, 90), new CvSize(0, 0));

Cv.HaarDetectObjects()를 이용하여 faces에 검출된 얼굴의 좌표를 저장합니다. Cv.HaarDetectObjects(탐지이미지, 객체 감지 파일, 메모리 저장소, 스케일팩터, 이웃수, 작동 모드, 최소 크기, 최대 크기)입니다.

  • Detected_image : 탐지할 이미지입니다.
  • cascade : 객체를 감지할 파일의 경로가 저장된 HaarClassifierCascade입니다.
  • storage : 매모리가 저장될 저장소입니다.
  • scaleFactor : 이미지 크기가 감소되는 양입니다.
  • minNeighbors : 검출 시 유지해야하는 인접한 얼굴의 수입니다. 0일 경우 중복해서 찾거나, 너무 높을 경우 가까운 얼굴은 찾지 못합니다.
  • HaarDetectionType.* : 작동 모드입니다.

    • HaarDetectionType.Zero : 최적화를 수행하지 않습니다.
    • HaarDetectionType.DoCannyPruning : Canny Edge detector를 사용하여 가장자리가 너무 적거나 많은 경우 탐색하지 않습니다.
    • HaarDetectionType.ScaleImage : 확대/축소를 하지 않고 downscale을 통하여 cascade에서 수행합니다.
    • HaarDetectionType.FindBiggestObject : 가장 큰 객체 1명만 검출합니다.
    • HaarDetectionType.DoRoughSearch : 객체를 충분히 찾으면 작은 크기의 객체는 검출하지 않습니다.
  • MinSize : 검출할 얼굴의 최소 크기를 설정합니다.
  • MaxSize : 검출할 얼굴의 최대 크기를 설정합니다.


  • Tip : CvSize(0, 0)으로 설정 시 제한 크기를 설정하지 않고 찾습니다.


for (int i = 0; i < faces.Total; i++)
{
    CvRect r = faces[i].Value.Rect;
    CvPoint center = new CvPoint
    {
        X = Cv.Round((r.X + r.Width * 0.5) * scale),
        Y = Cv.Round((r.Y + r.Height * 0.5) * scale)
    };
    int radius = Cv.Round((r.Width + r.Height) * 0.25 * scale);
    haarface.Circle(center, radius, CvColor.Black, 3, LineType.AntiAlias, 0);
}

for문을 이용하여 검출된 얼굴의 위치에 Circle을 그립니다.


Result


2



도움이 되셨다면 광고 클릭 부탁드립니다.

⤧  Next post C# 강좌 : 제 28강 - 쓰레드 (1) ⤧  Previous post C# 강좌 : 제 27강 - 난수