13장 객체 검출
13.1 템플릿 매칭
입력 영상에서 작은 크기의 부분 영상 위치를 찾아내고 싶은 경우 사용함
템플릿 : 찾고자 하는 대상이 되는 작은 크기의 영상
템플링 매칭 : 작은 크기의 템플릿 영상을 입력 영상 전체 영역에 대해 이동하면서 가장 비슷한 위치를 수직적으로 찾아내는 방식
// 템플릿 매칭
void template_matching()
{
Mat img = imread("circuit.bmp", IMREAD_COLOR);
Mat templ = imread("crystal.bmp", IMREAD_COLOR);
if (img.empty() || templ.empty())
{
return;
}
img = img + Scalar(50, 50, 50);
Mat noise(img.size(), CV_32SC3);
randn(noise, 0, 10);
add(img, noise, img, Mat(), CV_8UC3);
Mat res, res_norm;
matchTemplate(img, templ, res, TM_CCOEFF_NORMED);
normalize(res, res_norm, 0, 255, NORM_MINMAX, CV_8U);
double maxv;
Point maxloc;
minMaxLoc(res, 0, &maxv, 0, &maxloc);
cout << "maxv: " << maxv << endl;
rectangle(img, Rect(maxloc.x, maxloc.y, templ.cols, templ.rows), Scalar(0, 0, 255), 2);
imshow("templ", templ);
imshow("res_norm", res_norm);
imshow("img", img);
waitKey();
destroyAllWindows();
}
13.2 캐스케이드 분류기와 얼굴 검출
비올라-존스 얼굴 검추 알고리즘 : 영상을 24x24 크기로 정규화한 후, 유사-하르 필터 집합으로부터 특징 정보를 추출하여 얼굴 여부를 반별
유사-하르 필터 : 흑백 사각형이 서로 붙어 있는 형태로 구성된 필터
흰색 영역 픽셀 값은 모두 더하고, 검은색 영역 픽셀 값은 모두 빼서 하나의 특징 값을 얻을 수 있음.
(사람의 정면 얼굴 형태가 전형적으로 밝은 영역(이마, 볼, 미간 등)과 어두운 영역(눈썹, 입술 등)이 정해져 있음.)
그러나 다양한 크기의 유사-하르 필터를 대략 18만 개 생성할 수 있고, 픽셀 갓의 합과 차를 계산하는 것이 복잡하지는 않지만 시간이 오래 걸리는 것이 문제됨
이에 대해 에이다부스트 알고리즘과 적분 영상을 이용하여 해결함
에이다부스트 알고리즘은 수많은 유사-하르 필터 중에 얼굴 검출에 효과적인 필터를 선별하는 역할을 수행
캐스케이드 구조라는 새로운 방식을 도입하여 얼굴이 아닌 영역을 빠르게 걸러 내는 방식을 사용함
캐스케이드 구조 1단계에서 얼굴 검출에 가장 유용한 유사-하르 필터 하나를 사용하여, 얼굴이 아니라고 판단되면 이후의 유사-하르 필터 계산은 수행하지 않음
2단계에서 유사=하르 필터 다섯 개를 사용하여 얼굴이 아닌지를 검사하고, 얼굴이 아니라고 판단되면 이후 단계의 검사는 수행하지 않음. 이러한 방식으로 얼굴이 아닌 영역을 빠르게 제거함으로써 약 15배 빠르게 동작하는 성능을 보여줌
// 얼굴 검출
void detect_face()
{
Mat src = imread("kids.png");
if (src.empty())
{
return;
}
CascadeClassifier classifier("haarcascade_frontalface_default.xml");
if (classifier.empty())
{
return;
}
vector<Rect> faces;
classifier.detectMultiScale(src, faces);
for (Rect rc : faces)
{
rectangle(src, rc, Scalar(255, 0, 255), 2);
}
imshow("src", src);
waitKey();
destroyAllWindows();
}
// 눈 검출
void detect_eyes()
{
Mat src = imread("kids.png");
if (src.empty())
{
return;
}
CascadeClassifier face_classifier("haarcascade_frontalface_default.xml");
CascadeClassifier eye_classifier("haarcascade_eye.xml");
if (face_classifier.empty() || eye_classifier.empty())
{
return;
}
vector<Rect> faces;
face_classifier.detectMultiScale(src, faces);
for (Rect face : faces)
{
rectangle(src, face, Scalar(255, 0, 255), 2);
Mat faceROI = src(face);
vector<Rect> eyes;
eye_classifier.detectMultiScale(faceROI, eyes);
for (Rect eye : eyes)
{
Point center(eye.x + eye.width / 2, eye.y + eye.height / 2);
circle(faceROI, center, eye.width / 2, Scalar(255, 0, 0), 2, LINE_AA);
}
}
imshow("src", src);
waitKey();
destroyAllWindows();
}
13.3 HOG 알고리즘과 보행자 검출
HOG : 그래디언트 방향 히스토그램
사람이 서 있는 영상에서 그래디언트를 구하고, 그래디언트의 크기와 방향 성분을 이용하여 사람이 서 있는 형태에 대한 특징 벡터를 정의함
머신 러닝의 일종인 SVM(서포트 벡터 머신) 알고리즘을 이용하여 입력 영상에서 보행자 위치를 검출하는 방법
HOG는 일반적으로 64x128 크기의 영상에서 계산
그래디언트 : 크기와 방향 성분으로 계산하며, 방향 성분은 0도부터 180도까지로 설정함
HOG 알고리즘 : 입력 영상으로부터 그래디언트를 계산
그다음은 입력 영상을 8x8 크기 단위로 분할하는데, 각각의 8x8 부분 영상을 셀이라고 부름
각각의 셀로부터 그래디언트 방향 성분에 대한 히스토그램을 구하며, 이때 방향 성분이 20도 단위로 구분하면 총 아홉 개의 빈으로 구성된 방향 히스토그램이 만들어짐 그리고 인접한 네 개의 셀을 합쳐서 블록이라고 정의함
수천 장의 보행자 영상과 보행자가 아닌 영상에서 HOG 특징 벡터를 추출하고, 이 두 특징 벡터를 구분하기 위해 SVM 알고리즘을 사용함
SVM은 두 개의 클래스를 효과적으로 분리하는 능력을 가진 머신 러닝 알고리즘
// 보행자 검출
int main()
{
VideoCapture cap("vtest.avi");
if (!cap.isOpened())
{
return -1;
}
HOGDescriptor hog;
hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());
Mat frame;
while (true)
{
cap >> frame;
if (frame.empty())
break;
vector<Rect> detected;
hog.detectMultiScale(frame, detected);
for (Rect r : detected)
{
Scalar c = Scalar(rand() % 256, rand() % 256, rand() % 256);
rectangle(frame, r, c, 3);
}
imshow("frame", frame);
if (waitKey(10) == 27)
break;
}
return 0;
}
13.4 QR 코드 검출
QR 코드 : 흑백 격자 무늬 모양의 2차원 바코드 일종으로 숫자, 영문자, 8비트 문자, 한자 등의 정보를 저장
입력 영상에서 QR 코드를 인식하려면 먼저 QR 코드 세 모서리에 포함된 흑백 정사각형 패턴을 찾아 QR 코드 전체 영역 위치를 알아내야 함
검출된 QR 코드를 정사각형 형태로 투시 변환한 후, QR 코드 내부에 포함된 흑백 격자 무늬를 해석하여 문자열을 추출해야 함
QR 코드를 검출하고 해석하는 기능은 QRCodeDetector 클래스에 구현
// QR 코드 검출 및 해석
void decode_qrcode()
{
VideoCapture cap(0);
if(!cap.isOpened())
{
return;
}
QRCodeDetector detector;
Mat frame;
while (true)
{
cap >> frame;
if (frame.empty())
{
break;
}
vector<Point> points;
String info = detector.detectAndDecode(frame, points);
if (!info.empty())
{
polylines(frame, points, true, Scalar(0, 0, 255), 2);
putText(frame, info, Point(10, 30), FONT_HERSHEY_DUPLEX, 1, Scalar(0, 0, 255));
}
imshow("frame", frame);
if (waitKey(1) == 27)
break;
}
}
#OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝 - 20 (0) | 2022.08.03 |
---|---|
#OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝 - 19 (0) | 2022.08.02 |
#OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝 - 17 (0) | 2022.07.21 |
#OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝 - 16 (0) | 2022.07.19 |
#OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝 - 15 (0) | 2022.07.15 |