C# OpenCV 강좌 : 제 29강 - 얼굴 검출
얼굴 검출(Haar Classifier Cascade)
영상이나 이미지에서 얼굴이 존재하는 위치를 알려주는 알고리즘
입니다.
얼굴 인식이 아닌 얼굴 형태의 패턴을 찾아 얼굴을 검출해주는 알고리즘(Face Detection)입니다.
Haar Classifier Cascade 다운로드
: 다운로드
위의 파일을 다운로드합니다. 압축 해제 후 xml파일을 프로젝트 경로에 저장합니다.
원본(Source, src)
은 영상이나 이미지를 사용합니다.
클래스 코드
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;
namespace Project
{
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);
}
}
}
세부 코드
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
은 검출되는 이미지의 비율입니다.
scaleFactor
와 minNeighbors
의 값은 얼굴 검출시에 사용되는 상수입니다.
scaleFactor
는 1
이상의 값을 사용합니다. minNeighbors
또한 1
이상의 값을 사용합니다.
using (IplImage Detected_image = new IplImage(new CvSize(Cv.Round(haarface.Width / scale), Cv.Round(haarface.Height / scale)), BitDepth.U8, 1))
{
...
}
검출되는 이미지인 Detected_image
를 scale
의 비율에 맞게 재조정합니다.
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.CvtColor
와 Cv.Resize
를 통하여 이미지의 크기를 조정합니다.
Cv.EqualizeHist(원본, 결과)
를 통하여 GrayScale
이미지의 화상을 평탄화 시킵니다.
이 작업을 통하여 매우 어둡거나 매우 밝은 부분들이 일정하게 조정됩니다.
using (CvHaarClassifierCascade cascade = CvHaarClassifierCascade.FromFile("../../haarcascade_frontalface_alt.xml"))
using (CvMemStorage storage = new CvMemStorage())
cascade
에 haarcascade_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
을 그립니다.
출력 결과
공유하기


댓글 남기기