AI/OpenCV

목표

이 튜토리얼에서는

  • Haar 캐스케이드 객체 감지가 작동하는 방식을 배웁니다.

  • Haar 기능 기반 캐스케이드 분류기를 사용하여 얼굴 감지 및 눈 감지의 기본 사항을 살펴 보겠습니다.

  • cv :: CascadeClassifier 클래스를 사용하여 비디오 스트림에서 객체를 감지합니다. 특히 다음 기능을 사용합니다.

이론

Haar 기능 기반 캐스케이드 분류기를 사용한 객체 감지는 Paul Viola와 Michael Jones가 2001 년 논문 "단순 기능의 부스트 된 캐스케이드를 사용하는 빠른 객체 감지"에서 제안한 효과적인 객체 감지 방법입니다. 캐스케이드 기능은 많은 양의 이미지와 음의 이미지에서 훈련됩니다. 그런 다음 다른 이미지에서 물체를 감지하는 데 사용됩니다.

여기에서는 얼굴 인식을 사용합니다. 처음에 알고리즘은 분류기를 훈련하기 위해 많은 양의 이미지 (얼굴 이미지)와 네거티브 이미지 (얼굴이없는 이미지)가 필요합니다. 그런 다음 여기에서 기능을 추출해야합니다. 이를 위해 아래 이미지에 표시된 Haar 기능이 사용됩니다. 그것들은 우리의 컨볼 루션 커널과 같습니다. 각 특성은 검정색 사각형 아래의 픽셀 합계에서 흰색 사각형 아래의 픽셀 합계를 뺀 단일 값입니다.


이제 각 커널의 가능한 모든 크기와 위치를 사용하여 많은 기능을 계산합니다. (얼마나 많은 계산이 필요한지 상상해보십시오. 24x24 창에서도 160000 개 이상의 기능이 생성됩니다.) 각 특성 계산에 대해 흰색 및 검은 색 직사각형 아래의 픽셀 합계를 찾아야합니다. 이를 해결하기 위해 통합 이미지를 도입했습니다. 이미지가 크더라도 주어진 픽셀에 대한 계산을 단 4 픽셀 만 포함하는 작업으로 줄입니다. 멋지지 않나요? 그것은 일을 매우 빠르게 만듭니다.


그러나 우리가 계산 한 이러한 모든 기능 중에서 대부분은 관련이 없습니다. 예를 들어, 아래 이미지를 고려하십시오. 맨 위 행은 두 가지 좋은 기능을 보여줍니다. 선택된 첫 번째 특징은 눈의 영역이 종종 코와 볼의 영역보다 더 어둡다는 속성에 초점을 맞춘 것 같습니다. 두 번째로 선택된 특징은 눈이 콧대보다 어둡다는 속성에 의존합니다. 그러나 뺨이나 다른 곳에 적용된 동일한 창은 관련이 없습니다. 그렇다면 160000 개 이상의 기능 중에서 최상의 기능을 어떻게 선택합니까? 그것은 Adaboost에 의해 달성됩니다 .


이를 위해 모든 훈련 이미지에 모든 기능을 적용합니다. 각 기능에 대해 얼굴을 양수와 음수로 분류하는 최상의 임계 값을 찾습니다. 분명히 오류나 오 분류가있을 것입니다. 오류율이 최소 인 기능을 선택합니다. 즉, 얼굴 이미지와 얼굴이 아닌 이미지를 가장 정확하게 분류하는 기능입니다. (프로세스는 이처럼 간단하지 않습니다. 처음에는 각 이미지에 동일한 가중치가 부여됩니다. 각 분류 후 잘못 분류 된 이미지의 가중치가 증가합니다. 그런 다음 동일한 프로세스가 수행됩니다. 새로운 오류율이 계산됩니다. 또한 새로운 가중치도 적용됩니다. 프로세스는 필요한 정확도 또는 오류율에 도달하거나 필요한 기능 수를 찾을 때까지 계속됩니다.

최종 분류기는 이러한 약한 분류기의 가중 합계입니다. 그것은 단독으로 이미지를 분류 할 수 없기 때문에 약하다고 불리지 만 다른 사람들과 함께 강력한 분류기를 형성합니다. 이 논문은 200 개의 기능도 95 %의 정확도로 감지를 제공한다고 말합니다. 최종 설정에는 약 6000 개의 기능이 있습니다. (160000 개 이상의 기능에서 6000 개의 기능으로 감소했다고 상상해보십시오. 이는 큰 이득입니다).

이제 이미지를 찍습니다. 각 24x24 창을 가져옵니다. 그것에 6000 개의 기능을 적용하십시오. 얼굴인지 아닌지 확인하십시오. 와우 .. 조금 비효율적이고 시간이 많이 걸리지 않나요? 네, 그렇습니다. 저자는 이에 대한 좋은 해결책을 가지고 있습니다.

이미지에서 대부분의 이미지는 얼굴이 아닌 영역입니다. 따라서 창이 얼굴 영역이 아닌지 확인하는 간단한 방법을 사용하는 것이 좋습니다. 그렇지 않은 경우 한 번에 버리고 다시 처리하지 마십시오. 대신 얼굴이있을 수있는 영역에 집중하십시오. 이렇게하면 가능한 얼굴 영역을 확인하는 데 더 많은 시간을 할애합니다.

이를 위해 Cascade of Classifiers 개념을 도입했습니다 . 한 창에 모든 6000 개의 기능을 적용하는 대신 기능이 여러 단계의 분류기로 그룹화되고 하나씩 적용됩니다. (일반적으로 처음 몇 단계에는 훨씬 적은 기능이 포함됩니다.) 창이 첫 번째 단계에서 실패하면 버립니다. 나머지 기능은 고려하지 않습니다. 통과하면 기능의 두 번째 단계를 적용하고 프로세스를 계속합니다. 모든 단계를 통과하는 창이 얼굴 영역입니다. 그 계획은 어때!

저자의 탐지기는 처음 5 개 단계에서 1, 10, 25, 25 및 50 개의 기능과 함께 38 개의 단계로 구성된 6000 개 이상의 기능을 가졌습니다. (위 이미지의 두 기능은 실제로 Adaboost에서 가장 좋은 두 기능으로 얻은 것입니다.) 저자에 따르면 6000 개 이상의 기능 중 평균 10 개의 기능이 하위 창당 평가됩니다.

그래서 이것은 Viola-Jones 얼굴 감지가 어떻게 작동하는지에 대한 간단하고 직관적 인 설명입니다. 자세한 내용은 문서를 읽거나 추가 리소스 섹션에서 참조를 확인하십시오.

OpenCV에서 Haar- 캐스케이드 감지

OpenCV는 cv :: CascadeClassifier :: load 메서드를 사용하여 읽을 수 있는 훈련 방법 ( Cascade Classifier Training 참조 ) 또는 사전 훈련 된 모델을 제공합니다 . 사전 훈련 된 모델은 OpenCV 설치의 데이터 폴더에 있거나 여기 에서 찾을 수 있습니다 .

다음 코드 예제에서는 사전 훈련 된 Haar 캐스케이드 모델을 사용하여 이미지에서 얼굴과 눈을 감지합니다. 먼저 cv :: CascadeClassifier 가 생성되고 필요한 XML 파일이 cv :: CascadeClassifier :: load 메소드를 사용하여 로드 됩니다. 이후 감지는 감지 된 얼굴이나 눈에 대한 경계 사각형을 반환 하는 cv :: CascadeClassifier :: detectMultiScale 메서드를 사용하여 수행됩니다 .

이 튜토리얼 코드는 아래에 나와 있습니다. 여기 에서 다운로드 할 수도 있습니다.

from __future__ import print_function

import cv2 as cv

import argparse

def detectAndDisplay(frame):

frame_gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)

frame_gray = cv.equalizeHist(frame_gray)

#-- Detect faces

faces = face_cascade.detectMultiScale(frame_gray)

for (x,y,w,h) in faces:

center = (x + w//2, y + h//2)

frame = cv.ellipse(frame, center, (w//2, h//2), 0, 0, 360, (255, 0, 255), 4)

faceROI = frame_gray[y:y+h,x:x+w]

#-- In each face, detect eyes

eyes = eyes_cascade.detectMultiScale(faceROI)

for (x2,y2,w2,h2) in eyes:

eye_center = (x + x2 + w2//2, y + y2 + h2//2)

radius = int(round((w2 + h2)*0.25))

frame = cv.circle(frame, eye_center, radius, (255, 0, 0 ), 4)

cv.imshow('Capture - Face detection', frame)

parser = argparse.ArgumentParser(description='Code for Cascade Classifier tutorial.')

parser.add_argument('--face_cascade', help='Path to face cascade.', default='data/haarcascades/haarcascade_frontalface_alt.xml')

parser.add_argument('--eyes_cascade', help='Path to eyes cascade.', default='data/haarcascades/haarcascade_eye_tree_eyeglasses.xml')

parser.add_argument('--camera', help='Camera divide number.', type=int, default=0)

args = parser.parse_args()

face_cascade_name = args.face_cascade

eyes_cascade_name = args.eyes_cascade

face_cascade = cv.CascadeClassifier()

eyes_cascade = cv.CascadeClassifier()

#-- 1. Load the cascades

if not face_cascade.load(cv.samples.findFile(face_cascade_name)):

print('--(!)Error loading face cascade')

exit(0)

if ​not eyes_cascade.load(cv.samples.findFile(eyes_cascade_name))

print('--(!)Error loading eyes cascade')

exit(0)

camera_device = args.camera

#-- 2. Read the video stream

cap = cv.VideoCapture(camera_device)

if ​not cap.isOpened

print('--(!)Error opening video capture')

exit(0)

while ​True

ret, frame = cap.read()

if frame is None:

print('--(!) No captured frame -- Break!')

break

detectAndDisplay(frame)

if cv.waitKey(10) == 27:

break


결과

  1. 다음은 위 코드를 실행하고 내장 웹캠의 비디오 스트림을 입력으로 사용한 결과입니다.

프로그램이 haarcascade_frontalface_alt.xmlhaarcascade_eye_tree_eyeglasses.xml 파일의 경로를 찾을 수 있는지 확인하십시오 . 이들은 opencv / data / haarcascades에 있습니다.

2. 얼굴 감지를 위해 lbpcascade_frontalface.xml (LBP 훈련 됨) 파일을 사용한 결과입니다 . 눈을 위해 우리는 튜토리얼에서 사용 된 파일을 계속 사용합니다.


추가 자료

  1. 폴 비올라와 마이클 J. 존스. 강력한 실시간 얼굴 감지. International Journal of Computer Vision, 57 (2) : 137–154, 2004. [246]

  2. Rainer Lienhart와 Jochen Maydt. 신속한 물체 감지를위한 확장 된 haar 유사 기능 세트. 이미지 처리에서. 2002. 절차. 2002 년 국제 회의, 1 권, I–900 페이지. IEEE, 2002. [140]

  3. 얼굴 감지 및 추적 에 대한 비디오 강의

  4. Adam Harvey의 얼굴 인식에 대한 흥미로운 인터뷰

  5. OpenCV 얼굴 감지 : Adam Harvey의 Vimeo에서 시각화