OpenCV Haar/cascade training 튜토리얼

영상처리 2013.05.31 13:51

OpenCV의 Haar classifier, Cascade classifier를 학습시키기 위한 샘플 데이터 생성법 및 training 방법에 대한 상세 메뉴얼입니다.


Haar training이나 cascade training에 대한 내용은 OpenCV 웹 매뉴얼이나 Naotoshi Seo의 튜토리얼 사이트 등도 있지만 일부 설명이 모호한 부분도 있고 또한 영어로 되어 있기 때문에 우리말로 된 좀더 명확한 사용법을 정리해 보았습니다.


제가 직접 해보니 사용법이 명확하지 않은 부분이 많아서 제대로 다 파악하기 위해서는 시간이 꽤 많이 필요한것 같습니다. 이 글의 내용을 참조하면 이러한 시간을 많이 단축시킬 수 있을 것이라 생각합니다.


0. 내용 목차


1. 관련 리소스

2. OpenCV Haar Training & Cascade Training에 대한 전반적인 내용

3. training 데이터 생성과 관련하여 기본적으로 알고 있어야 할 것

4. opencv_createsamples.exe은 어디에?

5. opencv_createsamples.exe 사용법

6. 멀티 샘플들로부터 확장된 training 데이터 생성하기

7. OpenCV Haar Training 방법

8. OpenCV Cascade Training 방법

9. 학습된 검출기를 이용해서 실제 물체 검출하기

10. Training 과정에서 발생할 수 있는 에러와 해결법

11. Training/샘플링 프로그램



1. 관련 리소스


이 글과 더불어 같이 참조하면 좋은 자료들:

  • OpenCV 웹 매뉴얼: Cascade Classifier Training
  • 대표적인 Haartraining 튜토리얼 사이트: http://note.sonots.com/SciSoftware/haartraining.html
  • Haar & Cascade 논문: [Viola2001] P. Viola and M. J. Jones, "Rapid Object Detection using a Boosted Cascade of Simple Features", CVPR 2001
  • HOG 논문: [Dalal2005] N. Dalal and B. Triggs, "Histograms of oriented gradients for human detection," CVPR 2005.
  • LBP 논문: [Liao2007] S. Liao, X. Zhu, Z. Lei, L. Zhang and S. Z. Li, "Learning Multi-scale Block Local Binary Patterns for Face Recognition," International Conference on Biometrics (ICB), 2007, pp. 828-837.



2. OpenCV Haar Training & Cascade Training에 대한 전반적인 내용


Haar classifier 또는 Cascade classifier는 영상에서 특정 형태의 물체를 찾고자 할 때 사용할 수 있는 대표적인 방법중 하나입니다. 이 방법에 대한 간단한 설명은 영상 보행자 검출 기술(Pedestrian Detection)의 글 내용중 [Viola2001] 논문 설명 부분을 참조하시기 바랍니다.


OpenCV에는 opencv_haartraining.exe를 이용해서 [Viola2001] 논문에 있는 Haar Classifier를 학습시킬 수 있는 방법을 제공합니다.


그런데 이와는 별도로, 기존 Haar Classifier의 cascade 학습 구조는 그대로 유지하되 영상 feature를 추출하는 부분을 독립시켜서 다양한 영상 feature에 대해서 cascade 학습이 가능한 구조로서 Cascade Training 방법을 제공하고 있습니다. OpenCV에서 새로 제공되는 Cascade Training에서는 기존의 Haar feature 뿐만 아니라 LBP feature와 HOG feature를 모두 지원합니다.


따라서, Cascade Training 방법을 사용하면 파라미터 설정만으로, Haar, LBP, HOG를 마음대로 선택해서 학습시킬 수 있기 때문에 굳이 기존의 Haar Training 방법을 사용할 필요는 없어 보입니다. 하지만, training 데이터는 공통으로 사용되기 때문에 학습 방법에 관계없이 opencv_createsamples.exe를 사용해 생성해야 합니다.


또한, OpenCV 웹 페이지 설명에 보면 LBP feature를 사용하는 것이 학습에 걸리는 시간, 검출 수행 시간 모두 Haar feature보다 훨씬 빠르면서 성능은 거의 비슷하기 때문에 Haar feature보다는 LBP feature를 사용하는 것이 좋다고 합니다.


HOG feature와 LBP feature의 비교는 응용에 따라 다를 것으로 생각됩니다. 일단은 HOG는 Haar나 LBP에 비해 속도가 느립니다. 그리고 성능적인 면에서는 HOG는 edge 정보를 이용하고, Haar, LBP는 영역과 영역의 밝기차를 이용하기 때문에 검출하고자 하는 대상의 특성에 따라 성능이 달라질 것으로 생각됩니다.



3. training 데이터 생성과 관련하여 기본적으로 알고 있어야 할 것


Haar/Cascade classifier를 학습시키기 위해서는 positive 샘플과 negative 샘플이 모두 필요합니다. positive 샘플이란 검출하고 하는 대상 물체에 대한 샘플 영상들이며, negative 샘플은 대상 물체가 포함되지 않은 일반 이미지들입니다. classifier 학습(training) 과정은 다양한 수많은 영상 feature들 중에서 positive 샘플과 negative 샘플들을 가장 잘 구분시킬 수 있는 영상 feature들을 찾고 이 feature들을 잘 조합하여 강력한 검출기를 얻는 과정을 말합니다.



4. opencv_createsamples.exe은 어디에?


OpenCV의 Haar training 또는 Cascade training에 필요한 training 데이터를 생성하기 위한 공통 유털러티입니다. OpenCV를 설치한 후, opencv/apps/haartraining/ 에 보면 관련 소스코드들이 존재합니다.


하지만, 기본적으로는 이 유틸러티의 소스코드만 존재할 뿐 실제 실행파일은 존재하지 않기 때문에 cmake를 이용해서 자신이 새로 opencv를 빌드(build)해야 합니다. 이 때, cmake의 옵션들 중에서 BUILD_opencv_apps를 체크해주고 빌드하면 유틸러티가 생성됩니다. 또는 자신이 직접 c++ 프로젝트를 만들어서 관련 소스들을 컴파일해도 됩니다.


opencv_haartraining.exe, opencv_traincascade.exe, opencv_performance.exe 파일들도 모두 마찬가지입니다.



5. opencv_createsamples.exe 사용법


Naotashi Seo 튜토리얼 사이트에도 나와 있지만 이 유틸러티의 사용법은 총 4가지입니다. 파라미터를 어떻게 주느냐에 따라서 전혀 다른 일을 수행합니다. 이러한 내용이 OpenCV 메뉴얼에는 나와 있지 않다는 점이 저 또한 유감입니다. 참고로, opencv/apps/haartraining/createsamples.cpp 파일을 보면 파라미터에 따라 어떻게 사용법이 달라지는지 대략적이나마 파악할 수 있습니다.


이 유틸러티의 파라미터 목록 및 각각의 파라미터에 대한 간략 설명은 다음과 같습니다.


Usage: opencv_createsamples

  [-info <description_file_name>] -> positive 샘플 이미지 목록 및 물체영역 정보를 저장한 파일

  [-img <image_file_name>] -> 단일 positive 샘플 이미지 (물체 영역만 crop한 이미지)

  [-vec <vec_file_name>] -> 생성된 training 데이터를 저장할 파일명 (확장자: vec)

  [-bg <background_file_name>] -> negative 샘플 이미지 목록 파일

  [-num <number_of_samples = 1000>] -> 생성할 training 데이터 개수

  [-bgcolor <background_color = 0>] -> positive 샘플에서 투명색(배경색)으로 처리할 기준 픽셀값

  [-bgthresh <background_color_threshold = 80>] -> [bgcolor-bgthresh, bgcolor+bgthresh] 범위의 색을 투명색(배경색)으로 처리

  [-inv] [-randinv] -> positive 샘플을 일괄적으로 반전 또는 랜덤하게 반전

  [-maxidev <max_intensity_deviation = 40>] -> positive 샘플의 밝기값 변형 범위

  [-maxxangle <max_x_rotation_angle = 1.100000>] -> roll 회전변형 범위

  [-maxyangle <max_y_rotation_angle = 1.100000>] -> yaw 회전변형 범위

  [-maxzangle <max_z_rotation_angle = 0.500000>] -> pitch 회전변형 범위

  [-show [<scale = 4.000000>]] -> 생성되는 training 데이터를 이미지로 보여줄지 여부

  [-w <sample_width = 24>] -> 생성할 training 데이터의 이미지 폭 (픽셀)

  [-h <sample_height = 24>] -> 생성할 training 데이터의 이미지 높이 (픽셀)


-info: info 파라미터에는 positive 샘플 이미지들의 경로명(path)과 이미지 내에서의 대상 물체의 경계사각형 위치정보 목록을 텍스트 파일로 저장하고 이 파일 이름을 파라미터로 입력. 파일내 데이터 포맷은 '이미지경로명 물체수 x y width height [x y width height]'임.

예) plist.txt

d:\positives\img1.jpg 1 140 100 45 45

d:\positives\img2.jpg 2 100 20 50 50 0 30 25 25

d:\positives\img3.jpg 1 0 0 20 20

...


-bg: negative 이미지 목록을 저장한 텍스트 파일 이름을 입력

예) nlist.txt

d:\negatives\img1.jpg

d:\negatives\img2.jpg

...


실행모드 종류


이 파라미터들을 어떻게 조합하느냐 따라서 다음과 같이 총 4가지의 모드로 동작합니다 (각 모드의 이름은 설명의 편의를 위해서 임의로 붙였습니다).

  • [모드1] 단일 확장 training 생성: 하나의 positive 샘플을 다양하게 변형시켜서 내부 training 데이터 포맷으로 저장
  • [모드2] 멀티 고정 training 생성: 입력된 positive 샘플들을 그대로 내부 training 데이터 포맷으로 변환만 해서 저장
  • [모드3] 테스트 이미지 생성: positive 샘플과 negative 이미지들을 결합하여 테스트 이미지들을 생성하고 jpg 파일로 저장
  • [모드4] training 데이터 출력: 내부 training 데이터 포맷으로 저장된 데이터들을 이미지로 보여줌


실행모드 결정 규칙


파라미터들 중 info, img, vec, bg의 명시 여부에 따라 모드가 달라집니다. img와 vec를 모두 명시할 경우에는 모드 1으로 동작하고, info와 vec을 명시하면 모드 2, info, img, bg를 명시하면 모드 3, vec만 명시하면 모드 4로 동작합니다.

createsamples -img p.jpg -vec tr.vec => mode 1

createsamples -info plist.txt -vec tr.vec => mode 2

createsamples -info plist.txt -img p.jpg -bg nlist.txt => mode 3

createsamples -vec tr.vec => mode 4


opencv_createsamples 유틸러티는 각 모드에 따라 사용되는 파라미터가 달라지고 또 동일한 파라미터라 할지라도 그 의미가 조금씩 달라집니다. 각 모드별로 사용되는 파라미터들을 표로 정리하면 다음과 같습니다.



[모드 1] 단일 확장 training 데이터 생성


-img로 입력받은 positive 샘플 이미지 하나를 랜덤하게 변형시켜서 -num 개수만큼의 positive training 데이터를 생성합니다. 생성된 training 데이터들은 -w, -h 크기를 가지며 -vec 파일명으로 저장됩니다.


-bg 파라미터는 선택사항인데, 만일 -bg를 입력하면 negative 이미지 목록에서 랜덤하게 배경영역을 추출한 후 그 위에 변형된 positive 샘플을 덮어 씌워서 training 데이터를 생성합니다. 이 때, positive 샘플에서 [bgcolor-bgthreshd, bgcolor+bgthresh] 범위에 있는 픽셀들은 투명색으로 간주되어 배경색으로 채워집니다. 만일 -bg를 입력하지 않으면 positive 샘플의 투명색 부분과 회전변형에 의한 빈 공간은 -bgcolor로 채워집니다.


입력된 샘플이 하나이기 때문에 이를 다양하게 변형시켜야 하는데, 밝기값 변형은 -maxidev 내에서, 회전 변형은 -maxxangle, -maxyangle, -maxzangle 내에서 랜덤하게 이루어집니다. 회전 변형의 단위는 라디안(radian)이며 기본값은 maxxangle = maxyangle = 1.1 (63도), maxzangle = 0.5 (28.6도) 입니다. 기본값이 크기 때문에, 차량 검출 등 회전 변형이 적은 응용에서는 이 파라미터들의 값을 낮춰져야 합니다.


-maxxangle: roll 회전 변형, 상하 방향으로 물체의 크기가 변화


-maxyangle: yaw 회전 변형, 좌우 방향으로 물체의 크기가 변화


-maxzangle: pitch 회전 변형, 이미지 평면에서의 회전 변화


테스트 삼아서, 이 모드를 사용해서 자신의 얼굴만 잘 검출할 수 있는 검출기를 한 번 구현해 보는 것도 좋을 것 같습니다.



[모드 2] 멀티 고정 training 데이터 생성


-info로 입력받은 positive 샘플 영역들을 그대로 크기만 -w, -h로 바꿔서(resize) -vec 파일로 저장합니다. 샘플수를 늘리기 위한 변형을 가하지 않기 때문에, 생성되는 training 데이터 개수는 max{-num, 실제 positive 샘플 개수} 입니다. 즉, -num을 positive 샘플수보다 작게 주면 -num 개수까지만 training 데이터를 생성하고, 더 크게 주면 실제 샘플수까지만 training 데이터가 생성됩니다.



모드 2 방법은 주어진 샘플들을 그대로 학습 데이터로 사용하기 때문에, 물체에 대한 가능한 다양한 변형을 모두 커버할 수 있을 정도로 충분한 수의 positive 샘플이 있는 경우에 사용해야 합니다.



[모드 3] 테스트 이미지 생성


-img로 입력받은 positive 샘플 이미지에 다양한 변형을 가한 후에, -bg로 입력받은 배경(negative) 이미지 위에 붙여서 테스트 이미지를 생성하고 jpg 파일로 저장합니다 (배경이미지는 목록중에서 랜덤하게 선택되며 -num 개수만큼의 테스트용 jpg 이미지 파일들이 생성됨).



주의할 점은 -info 파라미터를 어떻게 주느냐에 따라서 이 모드의 동작 방식이 약간 달라집니다. 만일 -info에 파일명을 주면 (예. -info testlist.txt), 파일명에 해당하는 텍스트 파일이 새로 생성되고 (주의. 실행 폴더에 동일 이름의 파일이 있었다면 데이터가 날라감) 테스트 이미지 파일몇 및 테스트 이미지 내의 물체 위치가 기록됩니다. 그리고 jpg 파일들은 현재 실행 폴더에 저장됩니다. 그런데, 만일 -info에 경로명을 주면 (예. -info testimages\), 해당 폴더가 생성되고 생성된 폴더 밑에 jpg 파일들이 저장됩니다. 이 경우 이미지 위치정보를 기록한 목록 파일은 생성되지 않습니다. 파일명인지 경로명인지를 구분하는 기준은 이름 끝에 '\' 또는 '/'가 붙었는지 여부입니다.


이 모드를 사용해서 테스트 이미지들을 생성하면 영상 내 물체 위치를 알 수 있다는 장점은 있지만 인위적인 영상이기 때문에 가급적이면 실제 테스트 영상을 이용하는게 좋을 것 같습니다.



[모드 4] training 데이터 보여주기


-vec 파일로 저장되어 있는 training 데이터를 불러와서 하나씩 이미지로 보여줍니다. -w, -h에는 vec 파일에 있는 training 데이터의 저장된 이미지 크기를 입력하고, -scale에는 이미지를 얼마나 확대해서 보여줄 지를 입력합니다.



6. 멀티 샘플들로부터 확장된 training 데이터 생성하기


OpenCV에는 아쉽게도 여러 positive 샘플들을 확장해서 training 데이터를 생성시켜주는 함수는 제공하지 않습니다. 모드 1의 방법으로 각각의 샘플들에 대해 확장된 training 데이터들을 생성한 후에 생성된 vec 파일들을 하나로 합치거나, 아니면 자신이 직접 이러한 기능을 수행하는 함수를 구현해야 합니다.


참고로 Naotashi Seo 튜토리얼 사이트에 보면 vec 파일들을 하나로 합쳐주는 코드(mergevec.cpp)와 모드 1을 positive 이미지 목록에 대해 반복 수행해주는 perl 스크립트(createtrainsamples.pl)가 제공됩니다.


☞ 이러한 기능을 제공하는 프로그램을 직접 구현해 보았습니다. [개발한 것들] - Haar/Cascade Training 프로그램 내용을 참조하기 바랍니다.




7. OpenCV Haar Training 방법


opencv_haartraining.exe 유틸러티를 사용해서 haar classifier를 훈련시키는 방법에 대한 설명입니다. 참고로, 앞서 2절에서 설명했듯이 이 방법 말고 cascade training을 이용해서도 haar classifier를 학습시킬 수 있습니다.


이 유틸러티의 파라미터 목록 및 기본값, 각각의 파라미터에 대한 간략 설명은 다음과 같습니다.

Usage: opencv_haartraining

  -data <dir_name>

  -vec <vec_file_name>

  -bg <background_file_name>

  [-bg-vecfile]

  [-npos <number_of_positive_samples = 2000>]

  [-nneg <number_of_negative_samples = 2000>]

  [-nstages <number_of_stages = 14>]

  [-nsplits <number_of_splits = 1>]

  [-mem <memory_in_MB = 200>]

  [-sym (default)] [-nonsym]

  [-minhitrate <min_hit_rate = 0.995>]

  [-maxfalsealarm <max_false_alarm_rate = 0.5>]

  [-weighttrimming <weight_trimming = 0.95>]

  [-eqw]

  [-mode <BASIC (default) | CORE | ALL>]

  [-w <sample_width = 24>]

  [-h <sample_height = 24>]

  [-bt <DAB | RAB | LB | GAB (default)>]

  [-err <misclass (default) | gini | entropy>]

  [-maxtreesplits <max_number_of_splits_in_tree_cascade = 0>]

  [-minpos <min_number_of_positive_samples_per_cluster = 500>]


사용예.

opencv_haartraining -data result -vec tr.vec -bg nlist.txt -npos 400 -nneg 5000


-data: 이 파라미터는 2가지 역할을 수행함. 하나는 각 cascade 단계(stage)별 classifier가 저장될 디렉토리명이고 다른 하나는 최종 검출기가 저장될 파일 이름임. 예를 들어, '-data result'로 입력하면 현재 실행폴더 밑에 result라는 폴더가 생성되고 result 밑에 cascade classifier들이 저장됨. 또한 현재 실행폴더에 result.xml이라는 이름으로 학습된 최종 검출기가 저장됨.


-vec: positive training 데이터 파일명. 앞서 opencv_createsamples.exe로 생성한 positive 데이터(확장자: vec) 파일을 입력


-bg: negative 이미지 목록이 저장된 파일명을 입력 (앞의 5절 설명 내용 참조). 또는 -bg 파라미터로 .vec 파일을 입력으로 줄 수도 있음(단, negative 이미지들로부터 생성한 vec 파일이어야 함). 만일 -bg에 .vec 파일을 입력할 경우에는 -bg-vecfile 파라미터를 명시해 주어야 함.


-nstages: 학습할 cascade 단계의 수. Cascade 검출기는 일련의 기본 검출기들로 구성되는데, Cascade 검출 방식은 먼저 1단계 classifier로 false들을 걸러내고, 나머지에 대해서는 2단계 classifier로 false들을 걸러내고, ... 이런식으로 해서 최종 단계까지 살아남으면 물체 검출에 성공한 것으로 간주함. -nstages는 이 단계수 즉, 기본 검출기들의 개수를 조절하는 것임. 학습된 각 단계별 기본 검출기들은 result\ 밑에 0, 1, 2, ... 밑에 텍스트 파일 형태로 저장됨.


-npos: 각 cascade 학습 단계(stage)에 사용되는 positive 샘플 개수를 설정. 주의할 점은 .vec 파일에 있는 실제 샘플수를 입력하면 안됨.  npos <= (vec파일에 있는 샘플수 - 100)/(1+(nstages-1)*(1-minhitrate))) 정도로 값을 주기 바람. 자세한 내용은 아래 10절 'training 에러 및 해결법'을 참조하기 바람.


-nneg: 각 cascade 학습 단계(stage)에 사용될 negative 샘플 개수를 설정. -bg로 입력한 negative 이미지들 중에서 랜덤한 위치와 크기로 다양한 위치 및 크기로 negative 샘플들을 뽑기 때문에 실제 negative 이미지 개수와 관계없이 원하는 값을 주면 됨.

=> 사실은 랜덤하게 샘플을 뽑는 것은 아니고 negative 이미지들을 차례대로 스캔(scan)하면서 샘플을 뽑습니다. 그 방식은 고정된 크기의 윈도우를 영상 내에서 일정 간격으로 이동시키면서 샘플을 뽑고 이미지 끝에 도달하면 윈도우의 크기를 변경한후 다시 이미지의 처음 위치부터 스캔, ..., 한 이미지에 대해 가능한 모든 윈도우 크기에 대해 스캔이 끝나면 다음 negative 이미지로 넘어가는 방식으로 샘플을 추출함. 여기서 중요한 점은 negative 이미지에 있는 후보 패치 영역들이 그대로 negative 샘플이 되는 것이 아니라 물체가 아닌데도 물체인 것으로 잘못 검출되는 영역들만 negative 학습 샘플로 활용됩니다. 즉, 이전 단계(stage)까지 학습된 classifier로 negative 이미지 영역들을 쭉 스캔하면서 오검출이 발생하면 해당 영역을 negative 학습 샘플에 추가하고, 이런 식으로 총 nneg 개의 negative 샘플이 확보될 때까지 스캔을 계속합니다. 따라서, 만일 이전 단계까지 학습된 classifier가 오검출율이 매우 낮다면 현재 단계의 negative 학습 샘플을 준비하는데 많은 시간이 소요되게 됩니다.


-minhitrate: 각 cascade 단계의 기본 classifier들에게 요구되는 최소 검출율. 최종 검출기의 검출율은 minhitrate^nstages가 됨. 예를 들어, 기본값을 그대로 사용하면 최소 0.995^14 = 0.932 정도의 검출율을 가지는 detector를 얻을 수 있게 됨. 하지만 이것은 어디까지나 .vec 파일로 입력한 training 데이터에 대한 검출율이기 때문에 실제 일반적인 입력에 대한 검출율은 훨씬 떨어질 수 있음.


-maxfalsealarm: 각 cascade 단계의 기본 classifier들에게 요구되는 오검출율의 상한. 최종 검출기에 대해 예상되는 오검출율은 maxfalsealarm^nstages 임. 기본값을 그대로 사용할 경우, 0.5^14 = 0.0000610 정도의 값이 나옴. 일견 매우 작아보이지만, 입력 영상의 모든 가능한 윈도우 영역에 대해서 이 정도 비율로 오검출이 나온다고 생각해 보면 그렇게 작은 값이 아닐 수 있음. 어쨌든, 각 단계에서 오검출율을 0.5로 한다는 의미는, 입력 후보들 중 50% 이상을 걸러 낼 수 있는 classifier를 찾겠다는 말임. 이러한 단계별 classifier들이 cascade 형태로 연결되면 최종적으로는 대부분의 배경을 걸러낼 수 있는 검출기를 얻게 됨.


☞ minhitrate, maxfalsealarm 파라미터에 대한 보다 상세한 의미에 대해서는 아래 댓글들에 대한 답변 내용을 참고하시면 도움이 되리라 생각됩니다(뚱캔 2013.8.20, neverabandon 2013.12.11).


-mode: BASIC=0, CORE=1, ALL=3의 3가지 값을 가질 수 있으며 기본값은 BASIC임. BASIC은 원래 [Viola2001] 논문에서 사용된 haar feature들로서 아래 그림에서 1a, 1b, 2a, 2c에 해당함. CORE를 선택하면 아래 그림중 1a, 1b, 2a, 2b, 2c, 2d, 3a를 사용하고, ALL을 선택하면 아래의 모든 feature들을 모두 사용해서 training을 수행함. 응용에 따라서, 찾고자 하는 대상 물체의 특성에 따라서 적절히 -mode를 선택해 주면 됨.


-w, -h: .vec 파일에 있는 샘플 데이터의 크기. 샘플 데이터들은 이미지 패치(patch)들인데 이 이미지 폭(w)과 높이(h)를 말함.


-nsplits: 각 단계의 weak classifier로 어떤 binary decision tree를 사용할 것인지를 선택하는 파라미터. -nsplits 1이면 1개의 분기만을 가진 depth 1의 가장 기본적인 이진 stump tree가 사용됨. 2 이상의 값을 주면 해당되는 분기점을 가진 CART(Classification And Regression Tree) classifier가 사용됨.


-mem: training 과정에 사용할 임시 메모리 크기. 자신의 컴퓨터 메모리 용량에 따라 여유가 되는 대로 적절히 조절


-sym, -nonsym: 대상 물체가 사람 얼굴처럼 좌우대칭인지 여부를 설정하는 파라미터. 기본값은 true로 설정되어 있기 때문에 만일 좌우 대칭이 아닌 경우에만 -nonsym을 입력



8. OpenCV Cascade Training 방법


opencv_traincascade.exe 유팉러티를 사용해서 cascade classifier를 훈련시키는 방법에 대한 설명입니다. 기존의 Haar Training 방법을 업그레이드 한 것으로서, Haar feature뿐만 아니라 LBP(Local Binary Patterns), HOG(histogram of oriented gradient) feature까지 사용할 수 있습니다.


또한 opencv_traincascade는 병렬처리 라이브러리인 tbb를 지원하기 때문에 예전 방식보다 훨씬 빠르게 training을 수행할 수 있습니다. 물론 tbb 지원을 위해서는 opencv를 tbb에 맞게 설정을 하고 rebuild해야 합니다.


이 유틸러티의 파라미터 목록 및 기본값, 각각의 파라미터에 대한 간략 설명은 다음과 같습니다.

Usage: opencv_traincascade

  -data <cascade_dir_name>

  -vec <vec_file_name>

  -bg <background_file_name>

  [-numPos <number_of_positive_samples = 2000>]

  [-numNeg <number_of_negative_samples = 1000>]

  [-numStages <number_of_stages = 20>]

  [-precalcValBufSize <precalculated_vals_buffer_size_in_Mb = 256>]

  [-precalcIdxBufSize <precalculated_idxs_buffer_size_in_Mb = 256>]

  [-baseFormatSave]

  [-stageType <BOOST(default)>]

  [-featureType <HAAR(default), LBP, HOG>]

  [-w <sampleWidth = 24>]

  [-h <sampleHeight = 24>]

  [-bt <DAB | RAB | LB | GAB (default)>]

  [-minHitRate <min_hit_rate = 0.995>]

  [-maxFalseAlarmRate <max_false_alarm_rate = 0.5>]

  [-weightTrimRate <weight_trim_rate = 0.95>]

  [-maxDepth <max_depth_of_weak_tree = 1>]

  [-maxWeakCount <max_weak_tree_count = 100>]

  [-mode <BASIC (default) | CORE | ALL>]


사용예.

opencv_traincascade -data result -vec tr.vec -bg nlist.txt -numPos 400 -numNeg 5000 -featureType HAAR -mode CORE


대부분의 파라미터는 7절에서 이미 설명하였기에 차이가 있는 부분이나 새로 추가된 몇 가지 주요 파라미터에 대해서만 설명토록 하겠습니다.


-data: 입력 경로명에 해당하는 폴더가 없을 경우 에러가 발생하기 때문에 미리 폴더를 생성한 후에 폴더 경로명을 입력해 주어야 함. 입력한 폴더에 각 cascade 단계별 classifier들과 최종 학습된 classifier가 저장됨. 저장되는 최종 classifier 이름은 cascade.xml임.


-featureType: HAAR, LBP, HOG 세가지 타입의 feature를 선택할 수 있음. 각 feature의 차이에 대해서는 2절의 내용을 참조하기 바람.


-baseFormatSave: -featureType이 HAAR일 경우에만 의미를 가지는 파라미터임. 이 파라미터를 명시해 주면 훈련 결과를 예전의 Haar training 방식의 데이터 포맷으로 저장해줌.



9. 학습된 검출기를 이용해서 실제 물체 검출하기


다른 포스팅 글인 영상 보행자 검출 기술(Pedestrian Detection) - 정보공유에 올려놓은 PedestrianOpenCV.zip 에 있는 코드를 참조하거나 OpenCV에서 제공하는 opencv\samples\c\facedetect.cpp 예제를 참조하시기 바랍니다.



10. Training 과정에서 발생할 수 있는 에러와 해결법


* OpenCV Error: Assertion failed (elements_read == 1) in unknown function


=> positive 샘플 수를 잘못 입력했기 때문에 발생하는 에러임. 파라미터중 -npos, -numPos는 전체 positive 샘플의 개수가 아니라 각 cascade 단계에서 사용할 positive 샘플 개수임. 아래 내용은 이 문제에 대해서 개발자가 답변한 내용임.


The problem is that your vec-file has exactly the same samples count that you passed in command line -numPos 979. Training application used all samples from the vec-file to train 0-stage and it can not get new positive samples for the next stage training because vec-file is over. The bug of traincascade is that it had assert() in such cases, but it has to throw an exception with error message for a user. It was fixed in r8913. -numPose is a samples count that is used to train each stage. Some already used samples can be filtered by each previous stage (ie recognized as background), but no more than (1 - minHitRate) * numPose on each stage. So vec-file has to contain >= (numPose + (numStages-1) * (1 - minHitRate) * numPose) + S, where S is a count of samples from vec-file that can be recognized as background right away. I hope it can help you to create vec-file of correct size and chose right numPos value


정리하면, npos <= (vec파일에 있는 샘플수 - S)/(1+(nstages-1)*(1-minhitrate)))가 되도록 -npos나 -numPos 값을 주라는 말임. S는 vec 파일에 있는 positive들 중에서 검출기로는 정말 찾기 힘들 것 같은 것들의 수임 (그래서 classifier가 negative라고 간주해 버릴 수 있는 것들). S가 좀 모호함;; 일단 S = 100 정도 줘 보고 혹시 에러나면 S를 좀 높이면 될 듯 함.


* training 도중 세그멘테이션 폴트(segmentation fault)가 날 경우


=> opencv_haartraining.exe를 병렬처리 기능인 OpenMP를 활성화시킨 상태에서 돌리면 이런 현상이 나타날 수 있다고 함. 그 이유는 opencv_haartraining 유틸러티가 워낙 낡아서(?) 요즘 opencv 컴퓨팅 환경과 맞지 않기 때문이라고 함. 이러한 경우에는 조금 느리더라도 OpenMP를 비활성화시킨 상태에서 opencv_haartraining.exe를 컴파일해서 사용하거나, 아니면 최신 버전의 유틸러티인 opencv_traincascade.exe를 사용해야 함.


* Cascade 학습 도중 무한루프에 빠지는 경우


=> opencv_traincascade.exe를 사용할 경우, int negCount = fillPassedSamples( posCount, proNumNeg, false, negConsumed ); 수행중 fillPassedSamples 함수 내부의 f(;;) 루프에서 무한 루프에 빠질 수 있습니다. negative 배경 이미지들로부터 if( predict( i ) == 1.0F )를 만족하는 negative 샘플을 negNum 만큼 확보하지 못하면 발생하는 것 같습니다. 한 해결법은 이곳을 참조하세요. 다른 해결법은 negative 이미지들을 모두 조사했는지를 체크하는 루틴을 삽입해서 모두 조사했는데도 불구하고 아직 샘플을 찾지 못한 경우에는 break로 for(;;) 문을 빠져나가도록 하면 됩니다.


=> 무한루프 해결에 관한 구체적인 방법을 별도 글로 포스팅하였습니다. OpenCV Haar/cascade training 무한루프 방지(http://darkpgmr.tistory.com/112) 글을 참조하세요.



11. Training/샘플링 프로그램


Training 샘플 데이터 생성 및 Haar Training, Cascade Training (Haar feature, LBP feature, HOG feature), 그리고 실제 영상에서의 물체인식 테스트까지 할 수 있는 통합 프로그램을 구현해 보았습니다. [개발한 것들] - Haar/Cascade Training 프로그램에서 다운로드 받을 수 있습니다.


또한, positive training 샘플을 만들 때 사용할 수 있는 프로그램으로 [개발한 것들] - Ground Truth 편집 프로그램을 활용하시면 좋습니다. 원래는 비디오 파일에서 물체의 경계사각형을 따기 위한 목적으로 개발한 것인데, 최근에 이미지 목록에서도 작업이 가능하도록 프로그램을 수정하였습니다.



by 다크 프로그래머


  • 이전 댓글 더보기
  • 윈윈 2016.11.14 13:16 신고 ADDR 수정/삭제 답글

    haar cascade 알고리즘을 사용한 방법. 예를 들면 얼굴을 추출한다고 가정했을 때, 여러개의 약분류기를 하나의 집합으로 강분류기를 만들어 얼굴영역을 추출하는 것으로 알고 있습니다. 위의 댓글에 보면 고정된 이미지나 영상에서 haar cascade가 적합하다고 하셨는데.. 유튜브와 같은 비디오에서 얼굴영역을 검출(detection)할 때는 이 방법이 선호되지 않나요? 영상에선 어떤 detection 방법이 사용되는지 여쭙고 싶습니다.

    • BlogIcon 다크pgmr 2016.11.14 18:21 신고 수정/삭제

      여러 가지 방법이 있겠지만 LBP가 많이 사용되는 것으로 알고 있습니다. 또한 얼굴은 형태가 크게 변하는 물체가 아니기 때문에 haar feature를 사용하는 것도 충분히 좋은 방법으로 생각됩니다. 꼭 어떤 문제에는 어떤 feature를 써야 한다기 보다는 각 feature의 원리와 특성을 이해하고 있으면 물체의 특성에 따라 적절한 feature를 선택하는데 도움이 되리라 생각합니다.

  • soaka94 2016.11.23 15:12 신고 ADDR 수정/삭제 답글

    안녕하세요, 데이터세트 만드는과정에서 질문이 있어서 댓글을 남깁니다!
    positive 데이터는 사진 원본에 인식하고자 물체의 위치 좌표만 txt파일에 기재하면 되는것인가요??
    아니면 제가 따로 원하는 물체만 잘라서 만들어야하는건가요??

    • BlogIcon 다크pgmr 2016.11.23 19:42 신고 수정/삭제

      자를 필요없이 원본 사진에서의 좌표만 적어주면 됩니다.

    • soaka94 2016.11.24 01:24 신고 수정/삭제

      죄송하지만 한가지 더 여쭙겠습니다!

      제가 haartraining을 하는 과정에서

      POS: 100 100 1.000000
      Invalid background description file.
      이런오류를 뱉어내고 stage가 1단계까지 진행하고 끝나버렸습니다.

      positive data는 objectmarker.exe라는 프로그램을 통하여 만들었습니다. 벡터파일까지 만드는데 전혀 지장이 없었고,

      제가 준 파라미터는 아래와 같습니다.
      opencv_haartraining -data cascade -vec positive/LPdata.vec -bg negative/negative.txt -npos 100 -nneg 100 -nstage 30 -mem 1300 -mode ALL -w 20 -h 20

      txt파일을 열어서 경로명을 확인해보았지만 틀린부분은 없었습니다 ㅠㅠ혹시 어떤 오류인지 짐작가시는 부분이 있으신가요? 혹시 negative데이터 세트가 부족해서 200개로 늘려도 같은 결과 였습니다

    • BlogIcon 다크pgmr 2016.11.24 03:02 신고 수정/삭제

      저도 그런 메시지는 본 적이 없는데 어떤 건지 모르겠네요. opencv에 있는 cascade app 소스코드에서 "Invalid background description file" 문자열을 검색해 보시면 어떨까 싶습니다.

  • .. 2016.12.29 21:09 신고 ADDR 수정/삭제 답글

    혹시 여기서 그레이스케일로 했는데 그냥 원본 컬러 이미지로도 해도 되나요?
    컬러이미지로 했을때 positive이미지의 백그라운드 값을 어떻게 줘야하는건가요?
    cctv영상에서 포시티브 200개(차량,자전거,사람) 네거티브 10개(도로 전체 1장, 부분샷 여러장)로
    학습시켜봤는데 자꾸 맨 도로만 인식하더라구요.
    포시티브 이미지에서 백그라운드 약간씩 포함되어잇어서 그런것같기도 해서.. 여기에 적어봅니다.

    • BlogIcon 다크pgmr 2016.12.30 08:35 신고 수정/삭제

      입력 이미지는 칼라나 그레이 관계없는 것으로 알고 있습니다. 그런데 백그라운드 값이라는건 어떤건지 잘 모르겠네요.. 프로그램에 그런 파라미터가 있나요?

    • .. 2016.12.30 14:39 신고 수정/삭제

      create samples 부분에서 bgcolor랑 threshold 부분이요.
      그레이스케일이여서 스칼라 값인것같은데
      rgb라면 벡터3값이 들어가야만 할 것 같아서요..
      그리고 positive 이미지 넣을때, 사각형으로 좌표를 잡다보니 대상 물체 바깥부분의 약간의 배경이 들어가게되는데여
      이건 상관없는건가여?
      bgcolor값이 있는 이유가 그런곳에 특정 값으로 칠해서 마스킹시켜준다던가 그런건가 싶어서여

    • BlogIcon 다크pgmr 2017.01.02 11:23 신고 수정/삭제

      칼라로 이미지를 입력해도 내부적으로는 grary로 변환되서 처리되는 것으로 알고 있습니다. bgcolor는 말씀하신대로 특정 범위의 색상을 백그라운드로 마스킹하기 위함입니다. 예를 들어 파란색 벽 앞에 물체들을 세워놓고 학습 샘플들을 취득했을 때 의미가 있는 파라미터입니다. 하지만 현실 세계에서 임의의 비디오나 사진에서 샘플을 취득했을 때에는 배경의 색이 임의의 색이 될 수 있기 때문에 사실상 의미가 없는 파라미터입니다.

  • .. 2016.12.30 16:24 신고 ADDR 수정/삭제 답글

    본문 내용에서 bgcolor에 대한 설명을 positive 샘플에서 투명색(배경색)으로 처리할 기준 픽셀값이라고 적어두셔서 저렇게 표현했습니다.
    cctv영상(rgb)에서 사람과 차량,자전거를 사각형으로 떼서 p샘플 200개 만들고
    사람,차량 아무도 없을때 장면에서
    도로를 화면에 잡히는 전체 크게 하나랑 인도부분 크게 하나랑 조금 더 작게 쪼갠 부분 몇개 해서
    n샘플 10개로 해서 create samples랑 haar 학습시켜봤는데
    ---------------------
    아.. 댓글 작성하면서 크리에읻 샘플된 데이터를 보니까..
    사람 데이터랑 차량 데이터 같이 넣어서 그런가
    샘플들이 이상하네여.. 사람,자전가 체크하는 부분이랑 차량 체크하는 부분을 따로둬서 두번 돌리던가 해야될 것 같네요..

    • BlogIcon 다크pgmr 2017.01.02 11:25 신고 수정/삭제

      여러 클래스의 물체들을 동시에 검출하는 것보다는 개별 클래스별로 검출기를 따로 따로 학습시키는 것이 좋겠습니다.

  • .. 2017.01.04 17:09 신고 ADDR 수정/삭제 답글

    지금 그냥 스샷 찍은 이미지에서 물체 나오는 부분 사각형으로 잘라서 positive list 넣고 아무것도 없는 배경 큼직하게 잘라서 negative list에 넣어서 주고 해봤는데,, positive 이미지에서 물체 색상이랑 배경 색상을 고려 안하고 넣어주니까 이상하게 나오는것 같아서, positive 이미지에서 배경색을 통일시키려고 이미지 상에 해당 물체 외의 배경은 흰색으로 따로 처리하려고 생각했습니다. 그런데 다시 생각해보니 물체의 색상이 그 색상이랑 같아버리면 또 이상하게 될 것 같은 의문점이 생겨서 여기에 물어보려고 합니다.

    positive list로 준 이미지(차량의 색깔이 흰색이고 배경이 흰색)에서
    bgcolor 0으로 주면 해당 이미지에서 create sample을 통해 나온 sample은
    그림자랑 외곽선 같은 부분을 제외하고 차체 부분은 뒤에 negative 이미지(도로는 회색)가 그대로 보이는 것 같은데
    이런건 어떻게 처리해야되는건가요?

    training 부분에서 이런부분을 알아서 처리해주는건가요?
    아니면 배경이랑 비슷한 색상의 물체는 검출을 미리 포기하고 positive list에서 제외시켜줘야되는건가요?

    • BlogIcon 다크pgmr 2017.01.04 21:53 신고 수정/삭제

      정말 죄송한 말씀입니다만 중요한 것은 룰(rule)을 정확히 파악하는 것이고 룰이 파악된 이후에 그 룰을 어떻게 활용할지는 자신의 몫입니다. 여기서 룰은 입력 샘플에서 gray 밝기값이 bgcolor-bgthresh ~ bgcolor+bgthresh 사이에 있는 픽셀은 배경픽셀로 처리된다는 점입니다. 룰에 따르면 물체색도 흰색이고 배경색도 흰색이면 당연히 물체도 배경으로 처리됩니다. 해결책은 bgcolor를 -1000 정도로 잡아서 해당 기능이 아에 동작하지 않도록 하거나 혹은 물체에 존재하지 않는 색을 배경색으로 설정하는 것입니다.

    • .. 2017.01.05 16:32 신고 수정/삭제

      넵..;
      답변 감사합니다.
      당연한 것이였군요.....

  • 초보운전 2017.01.04 18:01 신고 ADDR 수정/삭제 답글

    안녕하세요 Cascading을 하고 싶은 학사예비졸업생입니다.
    다크프로그래머님께서 올려주신 Cascade Trainer 프로그래을 사용하려고 합니다.
    샘플을 만드는 방법에 대해서는 숙지하였는데, 학습을 하는 과정에서 의문이 있습니다.
    현재 상황은 multi expand를 이용해 약 2000여장의 샘플을 만들었고, 900여장의 negative가 있습니다.
    질문1. 우선 위의 상황과는 관련이 없는 질문일 수 있지만, Cascade training(Haar)과 Haar Training의 차이점이 궁금합니다.
    질문2. 우선은 두개의 구분이 정확하지 않아 두개 다 돌려 보았지만, 어떤것도 14번의 스테이지를 채우고 종료되어 제대로된 .xml 파일을 만든 것이 없습니다. 특히 도중에 Required leaf false alarm rate achieved. Branch training terminated."라는 문구가 적히면서 트레이닝이 종료되는데 왜 그렇게 되는 것인지 궁금합니다.
    질문3. err type에 대해서 궁금합니다. 현재 3개의 타입이 있는것 같은데 각각의 차이점을 알려주실 수 있으실까요?
    질문4. Cascade Training에 대한 cpp파일은 Cmake를 통해서 찾았는데, Haar Training에 대한 헤더 및 cpp 파일은 어떻게 찾아야 하는 건가요?

    항상 올리신글 잘 읽고 있습니다.감사합니다.

    • BlogIcon 다크pgmr 2017.01.04 22:32 신고 수정/삭제

      안녕하세요. 질문하신대로 아는 범위에서 답변을 드립니다.
      1. 학습 알고리즘이 달라진 건 아니고 구현상의 소프트웨어 구조가 다른 것 뿐입니다. 기존 opencv에 들어있던 Haar 코드는 Haar feature에 종속적으로 구현되어 있었습니다. 그런데, feature와 학습 알고리즘을 분리시켜서 구현함으로써 Haar feature 외에도 LBP, HOG 등의 다른 feature를 이용해서도 학습이 가능하도록 소프트웨어 구조를 좀더 general하게 수정한 것이 cascade 코드입니다.
      2. 먼저 cascade 학습기법에 대한 이해가 선행되어야 할 것 같습니다. http://darkpgmr.tistory.com/53 글에서 [Viola2001] 논문 설명 부분을 보시기 바랍니다. "Required leaf false alarm rate achieved. Branch training terminated"는 목표로 설정한 성능이 이미 만족되었기 때문에 더 이상 학습을 진행하지 않고 종료한다는 의미입니다. 정상적으로 학습이 잘 완료된 것입니다.
      3. 저도 잘 모릅니다. misclass는 misclassification error이고 entropy는 무질서도이고 gini는... 알라딘 램프도 아니고 대체 뭘까요.. ??
      4. 앞서 1번 답변에서 적었듯이 알고리즘 상의 차이가 있는 것이 아니니 굳이 Haar에 특화되어 구현된 코드를 찾을 필요는 없습니다. Haar 코드는 아마도 아주 아주 먼 옛날 버전의 opencv에 포함되어 있을 것입니다.

    • 초보운전 2017.01.05 10:32 신고 수정/삭제

      말씀하신데로
      "Required leaf false alarm rate achieved. Branch training terminated" 이문구가 나오면 학습이 종료된다고 하셨는데, savename 폴더에 저장되어 있는 xml 파일과 Cascade Trainer내의 Test Classifier로 테스트를 진행하려 하는데, "Unspecified error (The node does not represent a user object(unknown type?)) in unknown function" 오류가 발생합니다. 혹시 이오류는 어떻게 해결할 수 있나요?

    • BlogIcon 다크pgmr 2017.01.05 12:05 신고 수정/삭제

      그건 저도 잘 모르겠습니다. 메시지로 봐서는 무언가 학습이 정상적으로 안 된 것으로 보입니다만.. 원인 파악을 위해 다양하게 테스트해 보시면 좋을 것 같습니다. 일단 간단하게는 학습이 종료된 stage보다 낮은 값으로 목표 stage를 설정한 후 학습된 결과를 테스트 해 보는 것이 있을 것입니다. 그리고 학습 종료가 되지 않도록 목표 성능을 높여서 학습시키는 방법도 있을 것입니다. 또한 학습 데이터를 조절해서 적은 학습 데이터로만 간단하게 학습시켜서 전체적으로 프로그램이 동작하는지 확인만 먼저 해 보는 것도 방법입니다. 그리고 제가 올린 프로그램은 opencv에 있는 코드를 그대로 포장해서 올린 것이기 때문에 기본적으로 동작은 opencv에 있는 내용과 거의 동일합니다. 에러 메시지 등에 대해서 opencv에 포함되어 있는 원본 소스코드를 확인해 보시면 좋을 것 같습니다.

    • BlogIcon 다크pgmr 2017.01.05 12:32 신고 수정/삭제

      거듭 말씀드리자면 이건 제가 개발한 프로그램이 아닙니다. opencv에서 제공하는 cascading 코드를 사람들이 사용하기 편하도록 인터페이스를 입힌 것 뿐입니다. 내부 동작은 opencv의 코드입니다.

    • 초보운전 2017.01.05 13:12 신고 수정/삭제

      답변 감사드립니다ㅎㅎ
      제가 정답을 찾으려하지 않고 다크프로그래머님게 정답을 듣으려고 했던것 같네요. 그점은 죄송합니다.
      앞으로도 좋은 글 부탁드릴께요ㅎㅎㅎ

  • 영상초보 2017.01.18 14:52 신고 ADDR 수정/삭제 답글

    안녕하세요 다크프로그래머님 일단 영상처리에 대해 좋은 블러그 덕분에 정말 많이 배우고 있습니다. 이번에 얼굴영역을 검출하는부분을 보다가 검출기를 만드는 부분을 해보고 있는데 Create Sample 에 멀티 확장형으로 선택하여 만들어보려 했으나 샘플이 생성이 되지 않습니다..
    postive_list 에 이미지의 경로와 함께 영역을 설정해주었습니다. (ex: d\PosImage\1.jpg 1 10 10 50 50 ) 이런식으로 이미지를 적어주고 negative 도 위와 비슷하게 하고 좌표값을 적어주지 않았습니다. 그런데 Create 를 누르게 되면 전혀 생성되지 않고 그냥 Done 이라며 종료가 되네요.. 혹시 제가 이해한 방법이 잘못된 부분이 있다면 지적 부탁드리겠습니다. 항상 좋은 블로그 감사드립니다.
    ps. 영역은 각기 다른 방향의 얼굴 영역을 표현해 놓았습니다.

    • BlogIcon 다크pgmr 2017.01.18 17:20 신고 수정/삭제

      안녕하세요. 제가 블로그에 올려놓은 프로그램으로 하신 것이 맞는지 궁금합니다. multi expand로 선택하고 create samples 버튼을 누르면 성공했을 경우에는 XX samples created라는 메시지가 나오고 done이라는 메시지는 출력하지 않습니다. 그리고 만일 샘플 생성 과정에서 이미지를 읽는데 문제가 생기면 Unable to open file이라는 메시지가 출력되고 이미지는 읽었지만 positive_list 파일의 포맷이 이상할 경우에는 parse error라는 메시지가 콘솔에 출력됩니다. "done"이라는 메시지가 출력된다고 하니 무언가 다른 프로그램 또는 다른 기능을 사용하신 것 같습니다.

    • BlogIcon 다크pgmr 2017.01.18 17:23 신고 수정/삭제

      그리고, 문제가 multi expand로 했을 때만 발생하는지 아니면 단일 확장 등 다른 모드에서도 발생하는지도 확인해 보시면 좋을 듯 싶습니다.

    • 영상초보 2017.01.19 12:29 신고 수정/삭제

      다시 확인해보니 parse error 라는 문구가 콘솔에 확인되었습니다... 그렇다면 파일의 포맷이 문제가 있는건가요?? 파일 포맷이라고 하는것은 이미지 파일을 말씀하시는건지 텍스트파일의 내용이 이상한건지 궁금합니다... 현재에는 텍스트 파일에 이미지 경로, 영역갯수, 영역의 x,y,width,hieght 만 표기 해두었는데 혹시 다른 추가적인 부분이 전부 필요한가요?

    • BlogIcon 다크pgmr 2017.01.19 13:10 신고 수정/삭제

      네, parse error는 positive_list.txt 파일의 내용을 읽어들이는 과정에서 발생하는 메시지입니다. 구체적으로 어떤 경로로 발생하는지는 opencv의 소스코드를 확인해 보시기 바랍니다(2.4.4 버전 opencv). 하지만 적어주신 예제에서 d\PosImage에서 d:\PosImage와 같이 콜론이 빠진 것 외에는 다른 이상한 점은 없습니다. 구체적으로 어떤 문제가 원인인지는 다른 사람이 알기 어렵습니다. 다양한 방식으로 테스트해 보시면 좋을 것 같습니다.

    • 영상초보 2017.01.19 17:18 신고 수정/삭제

      음... 확인해본결과 pos_list 에 : 콜론이 빠진 부분은 없는것 같습니다... D:\posImage\4.jpg 1 541,179,295,375
      이와 같이 여러개를 작성했는데 도무지 읽히지가 않네요... 단일확장 모드는 정상적으로 잘 구동되는데 멀티 확장에서 문제가 발생하네요... 혹시 권한문제인가 싶어서 관리자도로 시도해보고 경로 문제인가 싶어서 경로도 바꾸며 시도해봤지만 모두 실패했습니다.. 혹시 짐작가시는 부분이 있다면 조언 부탁드립니다...

    • BlogIcon 다크pgmr 2017.01.19 22:17 신고 수정/삭제

      저도 딱히 짐작가는 바는 없습니다.. 이미 해보셨을지도 모르겠지만 간단하게 2~3개의 이미지에 대해서만 pos_list 파일을 작성하고 영역도 4.pjg 1 0 0 10 10 이런 식으로 가장 단순화시켜서 동작 여부를 테스트해 보는 것도 좋겠습니다. 그리고 혹시 노파심인데 영역 구분할 때 ,가 들어가면 안됩니다. opencv 소스를 보면 fscanf("%d %d %d %d", ...) 이런식으로 구현되어 있기 때문에 541,179,295,375 -> 541 179 295 375와 같이 형식을 정확히 일치시켜 주어야 합니다.

    • 영상초보 2017.01.20 10:38 신고 수정/삭제

      하.... 그부분이 문제였네요.... 습관처럼 영역 정보에 , 를 추가했네요... 항상 이런 소소한 글에도 관심갖아주시고 성의 넘치는 답변 정말 감사드립니다.. 앞으로도 많이 배우도록 노력하겠습니다..! 감사합니다^^

    • BlogIcon 다크pgmr 2017.01.21 07:55 신고 수정/삭제

      ㅎㅎ...

  • 상큼진달래 2017.01.26 18:02 신고 ADDR 수정/삭제 답글

    안녕하세요. 정말 도움 많이 받고 갑니다.
    제가 궁금한 사항이 몇 가지가 있는데 답변해주시면 정말 감사하겠습니다.
    1. 제가 차에 달린 카메라로 드론을 detect 하려고 하는데 positive sample로 드론 정면,후면,측면,윗면,아랫면 이렇게 주면 정상적으로 cascade training을 했을 때 나온 하나의 xml파일로 드론 정면,후면,측면,윗면,아랫면에 대해 다 detect 가능한가요?
    아니면 정면에 대한 xml 파일, 후면에 대한 xml파일 등으로 따로따로 만들어서 검출을 해야하는건가요?
    만약 한 xml파일로 가능하다면, 날아다니는 드론을 detect 해야한다고 하면 다양한 각도에서의 드론 사진을 positive sample로 많이 주면 줄수록 검출률이 높아지는 것인가요?
    2. face detect 하는 코드에서 opencv에서 주어진 xml파일을 사용하면 정상적으로 작동하는데 제가 cascade training을 통해서 직접 만든 xml 파일을 사용하면 xml 파일 로드는 다 되고 videocam에서 검출을 하는 과정에서 에러가 뜹니다. 이런 경우에는 코드를 의심하는게 맞나요 아니면 제가 만든 xml파일을 의심하는게 맞나요?
    좋은 글 감사드립니다.

    • BlogIcon 다크pgmr 2017.01.28 22:20 신고 수정/삭제

      안녕하세요. 드론의 각 면마다 형태가 많이 다르면 부위별로 xml 파일을 만드는 게 좋을 것 같습니다. Haar feature의 특성과 cascading 방법의 특성을 살펴보시면 유추가 가능하리라 생각합니다. 그리고 error가 나는 부분은 저도 잘 모릅니다. 혹시 opencv 버전의 차이인가요? 참고로 블로그에 올린 프로그램은 opencv 2.4.4 입니다.

  • 북극곰괴력 2017.02.17 01:19 신고 ADDR 수정/삭제 답글

    안녕하세요 다크프로그래머님.

    몇가지 여쭈어 볼 것이 있는데 답변을 해주면 정말 은혜를 잊지않겠습니다.

    저는 대학생인데요, traincascade를 이용하여 학습을 시키려고하는데
    positive 100 negative 300과 같은 적은 수의 사진을 학습시키면 문제없이 동작하는데
    수백장 수천장을 하려면 메모리가 부족해서 못하고 있습니다. (insufficient memory 에러뜹니다.)

    컴퓨터의 메모리는 충분한데 1GB 이상 넘어가면 이렇게 되어버리는 것 같습니다.
    haartraining에는 -mem 파라메터가 있던데 traincascade로 해버리면 이런 파라메터가 없는 것 같습니다. precalc~~ 파라메터도 다 건드려봤는데 안되네요.

    어떻게 해야 할지 모르겠습니다. 하루종일 보고있는데 인터넷을 아무리 뒤져봐도 해결책이 나오지 않아서 이렇게 글 남겨봅니다. 제발 도와주세요 흑흑...

    • BlogIcon 다크pgmr 2017.02.17 07:38 신고 수정/삭제

      아마도 32비트 64비트 문제인것 같습니다. opencv의 traincascade app 모듈을 64비트 버전으로 다시 빌드해 보시기 바랍니다. 인터넷에 찾아보면 visual c++에서 64비트로 컴파일하는 방법이 있는 것 같습니다. 그리고 opencv를 다시 빌드하기 위해서는 cmake로 프로젝트를 생성한 후 빌드해야 하는데 이것도 인터넷에 관련 정보가 있을 겁니다. 단, cmake로 프로젝트를 생성할 때 application을 포함해서 opencv를 빌드하도록 설정을 해야 traincascade가 포함되어 빌드됩니다. 이렇게 빌드하면 실행파일 형태의 traincascade 파일이 생성되는데 이 파일을 이용해서 학습을 시키면 메모리 문제가 해결될 것으로 생각됩니다.

    • 북극곰괴력 2017.02.21 22:16 신고 수정/삭제

      감사합니다. 많은 도움이 되었습니다.

  • 북극곰괴력 2017.02.21 23:02 신고 ADDR 수정/삭제 답글

    안녕하세요 다크프로그래머님 저는 며칠전 질문을 드렸던 대학생입니다.

    또 다시 질문을 드릴것이 생겨서 이렇게 댓글을 남깁니다.

    traincascade를 이용하여 positive 이미지 1300장, negative 이미지 6500장을 20-stage로 돌리고 있는데 현재 15-stage를 시작하는 중이며 decision tree의 수와 HR, FA가 콘솔창에 뜨는 속도가 현저히 느려졌습니다. 시간이 좀 더 지나고나니 NEG current samples도 너무 느리게 올라가는 것이 보였습니다. NEG current samples가 의미하는 것은 무엇인가요?

    그리고 positive와 negative이미지 각각 100장, 500장과 같이 작은 샘플들에 대해서는 stage를 높게 돌려도 다크님 말씀대로 목표했던 수치에 도달해서인지 적은 stage에서 끝났습니다. (다크님의 댓글을 읽어보았는데, 여기서 목표했던 최종적인 수치가 minhitrate^nstage라는 뜻입니까?) 그리고나서는 20-stage로 positive 이미지 1300장, negative 이미지 6500장을 돌렸습니다. 저는 느려지는 것을 보면서 그래도 적당히 20-stage 전에 끝나겠구나 생각했지만 끝날 기미가 보이지 않습니다.

    왜 이런 문제가 발생하는 것인가요? minhitrate^nstage를 만족하지 못하는 것이라면 0.995^20은 대략 0.90인데 14-stage까지 학습을 마친 성능이 0.9에도 도달하지 못한 것인가요?? 처음 학습시킬때 nstage 파라메터를 낮게 잡고 다시 돌리는것이 유일한 방법인가요??

    답변 해주신다면 정말 감사하겠습니다... 절대 은혜를 잊지 않겠습니다.

    • BlogIcon 다크pgmr 2017.02.22 13:28 신고 수정/삭제

      글쎄요.. 저도 기억력에 한계가 있다보니 정확한 것은 opencv에서 구현된 코드를 다시 살펴봐야 할 것 같습니다..(opencv 소스코드를 직접 한번 검토해 보시면 도움이 되리라 생각합니다). 학습 단계(stage)가 올라갈수록 속도가 느려지는 이유는 갈수록 negative sample을 획득하기 어렵기 때문입니다. 현재까지 학습된 검출기로 주어진 negative 학습 이미지에 대해 검출을 시도해서 검출된 샘플들을 각 stage의 negative 샘플로 추가하게 되는데 갈수록 검출기의 성능이 좋아지기 때문에 negative 검출이 발생하지 않으면 속도가 매우 느려지거나 극단적인 경우 무한루프에 빠질 수도 있습니다.

  • 북극곰괴력 2017.02.22 00:03 신고 ADDR 수정/삭제 답글

    정말 죄송하지만, 마지막으로 한가지만 더 여쭙고 싶습니다.

    예를들어, 자동차를 검출하려고 할때 자동차의 옆면이나 자동차 범퍼 이런것들이 자동차로 오검출되는 경우가 있습니다.

    이것을 해결하기 위해 negative이미지에 자동차의 범퍼와 같이 positive이미지의 일부가 포함되는 이미지를 많이 넣으면 성능향상을 기대할 수 있나요? 아니면 positive 이미지의 일부가 들어가므로 오검출이 많아지게 되는것인가요?

    • BlogIcon 다크pgmr 2017.02.22 13:39 신고 수정/삭제

      제가 자동차를 학습시켜 본 적은 없지만 성능향상에 도움이 되리라 생각합니다. 직접 해보시는게 가장 확실한 방법입니다. 그리고 Haar 학습의 기본 원리/방식에 대해서 공부하시면 좀더 합리적인 유추가 가능하리라 생각합니다.

  • 초보에용 2017.03.06 10:57 신고 ADDR 수정/삭제 답글

    안녕하세요. 다크pgmr님
    최근 opencv관련 공부하면서, 들어와보게 되었습니다.
    LBP를 이용하여 표정 변화 프로그램을 만들고 있으나, 뜻대로 잘 되지 않아 이렇게 질문을 드립니다. 얼굴 표정 검출을 위해서는 어떤 트레이닝을 하는것이 가장 효과적인지 알고 싶습니다.
    또, 이 강의를 들으며 ( https://pythonprogramming.net/haar-cascade-object-detection-python-opencv-tutorial/ )얼굴 표정에 대한 cascade.xml을 만들었는데요. (5개) 혹시 이를 이용하여 잘 될지 테스트해보았으나 한번에 5개의 표정 모두가 검출되는 경의로운 얼굴이 되었네요.
    도움좀 받고싶습니다...

    • BlogIcon 다크pgmr 2017.03.06 17:47 신고 수정/삭제

      안녕하세요. 저는 표정인식을 해 본적 없습니다만 학습은 결국 학습데이터에 의해 성능이 좌우되지 않나 싶습니다. 그런데 표정인식을 LBP나 cascade 기법으로 하는게 좋은 방법인지는 잘 모르겠습니다. 최근 기술은 얼굴의 특징점(영상에서의 눈, 코, 입꼬리 등 주요 특징점 위치)을 꽤 안정적으로 뽑을 수 있는 것으로 알고 있습니다. 이미지를 그대로 입력으로 넣기 보다는 뽑힌 특징점의 위치에 대해 SVM 등으로 표정을 학습하는 것이 좀더 좋은 성능을 내지 않을까 추측해 봅니다..

    • 초보에용 2017.03.06 23:24 신고 수정/삭제

      다크pgmr님 답변 주셔서 감사합니다.
      혹시 SVM이 어떤것인지 조금 더 자세하게 알 수 있을까요?? 현재 텐서플로우를 고민하고는 있지만... 아이디어 혹은 조언을 얻고 싶습니다.

    • BlogIcon 다크pgmr 2017.03.07 00:10 신고 수정/삭제

      SVM은 Support Vector Machine의 약자로서 두 데이터셋 사이의 최적의 경계평면을 찾아주는 학습기법 중의 하나입니다. 최근의 딥러닝이 나오기 전까지는 가장 일반적으로 사용되던 학습기법입니다.

  • 안녕하세요 2017.05.13 15:09 신고 ADDR 수정/삭제 답글

    안녕하세요 cascade 공부 중인 학생입니다 혹시 한가지 사물을 찾는 것이 아닌 다양한 사물도 찾을 수 있는 방법이있나요? xml을 여러가지 만들어서 조건을 걸어주면 되는건가요?

    • BlogIcon 다크pgmr 2017.05.14 20:37 신고 수정/삭제

      굳이 여러 사물을 찾으려면 xml을 여러 개 만들어야 할 것 같습니다..

  • 안녕하세요 2017.05.29 18:51 신고 ADDR 수정/삭제 답글

    안녕하세요 답변감사합니다. 제가 트레이닝을 하고 웹캠으로 영상추적을 해봤는데 계단이더라도 많은곳이 인식이 되어서 질문드립니다. 혹시 이런 문제점을 해결하려면 positive이미지가 다 같은 사이즈여야 되는건가요?

  • markers2 2017.11.08 11:27 신고 ADDR 수정/삭제 답글

    안녕하세요 다크프로그래머님.. 여기서도 질문을 드리게 되네요..ㅎㅎ
    지금 계속 이미지 학습을 시도하고 있는데 opencv_traincascade 실행 후에 생기는 xml파일을
    그냥 opencv에 배포되어 있는 얼굴인식 xml 파일과 같은 방식으로 사용하면 되나요?

  • yj9903 2017.11.09 01:52 신고 ADDR 수정/삭제 답글

    안녕하세요. 지금 opencv_traincascade를 하고있는데요,
    negative sample은 (300,300) 크기 2400장
    postive sample은 (150,150) 크기이고,
    opencv_traincascade -data data -vec postives.vec -bg bg.txt numPos = 1800 -numNeg 900 -numStages 10 -w 80 -h 80 이렇게 명령을 주고 실행중인데, 시간이 엄청 오래걸립니다.
    혹시 train 시킬때 걸리는 시간을 좌우하는게 어떤 파라미터인지 알수 있을까요?

    • yj9903 2017.11.09 01:57 신고 수정/삭제

      +) 지금 얼굴인식을 하고있는데, postive에는 제사진을 넣고 negative 사진에는 다른사람들 사진들을 넣고 돌리고 있는데요, negative 이미지를 사람으로 설정해서 더 오래걸릴수도 있는건가요?

    • BlogIcon 다크pgmr 2017.11.09 07:05 신고 수정/삭제

      아마 가장 큰 원인은 -w 80, -h 80가 너무 큰 값이기 때문입니다. 20~30 사이의 값을 주면 좋을 것 같습니다. 그런데 Haar 특징을 이용해서 얼굴인식(recognition)을 하는 것은 무리라고 생각됩니다. 얼굴검출(detection)을 하는 것이라면 시도해 볼 수는 있겠습니다만.. 얼굴인식이 목적이라면 다른 접근법을 공부해보시는게 좋을 것 같습니다.

    • yj9903 2017.11.09 10:38 신고 수정/삭제

      감사합니다!

  • kjs123 2017.12.17 15:45 신고 ADDR 수정/삭제 답글

    안녕하세요 다크프로그래머님. 학교 연구과제로 꽃을 인식하는 프로그램을 만들어야 하는데 opencv_haar cascade trainer 로 xml파일을 만들고 싶습니다. 여러 사이트에서 트레이너를 받아 해봤는데 항상 오류가 뜨더라고요... 이번에는 학습단계 7단계까지 진행됬는데 거기서 2틀정도 놔두어도 진행이 안되서 사진을 여러장 준비해서 다시했더니 갑자기 sample-creation 단계부터 bad argument라는 에러가 떠서 진행이 안되고 있습니다. 뭐가 잘못된걸까요?

    • BlogIcon 다크pgmr 2017.12.17 17:22 신고 수정/삭제

      kjs123님, bad argument라는 것은 함수의 인자가 잘못됐다는 것인데, 메시지 만으로 어디가 잘못된 것인지는 알기 어렵습니다. 하나씩 원인을 찾아보는 수 밖에는 방법이 없을 것 같습니다.

  • daye 2017.12.19 16:48 신고 ADDR 수정/삭제 답글

    안녕하세요 올려주시는 글 항상 도움이되고 잘 보고있습니다!
    이번에 얼굴디텍팅 트레이닝을 해보려고하는데요.
    제가 가지고있는 동영상에서 원하는 부분을 캡쳐해서 이용하려는데, 혹시 이미지 크기가 모두 동일해야할까요 ? 작업을 시작하기에 앞서 해결하고 싶어 댓글 남깁니다.

    • BlogIcon 다크pgmr 2017.12.19 17:20 신고 수정/삭제

      아니요. 달라도 관계없습니다. 본문의 plist.txt 예제에 있듯이
      d:\positives\img1.jpg 1 140 100 45 45
      d:\positives\img2.jpg 2 100 20 50 50 0 30 25 25
      d:\positives\img3.jpg 1 0 0 20 20
      ...
      와 같이 이미지 내에서 물체 영역이 어디인지만 정확히 입력해 주면 됩니다.

    • daye 2017.12.19 17:26 신고 수정/삭제

      아 그렇군요, 감사합니다!!!

    • daye 2017.12.27 15:44 신고 수정/삭제

      안녕하세요 다크프래머님, 덕분에 트레이닝을 잘진행하고 있습니다 ! 제가 테스트하는 영상 특성 상, 사람체형을 먼저 확인한 후 얼굴 디텍팅을 진행해야 할 듯 한데요, 혹시 hog트레이닝으로 체형을 잡은 후 잡은 위치내에서 lbp로 얼굴 디텍팅이 가능할까요? 기본적으로 ROI는 프레임 전체로 알고있는데 디텍팅 된 체형만 ROI로 잡고 싶습니다 !!

    • BlogIcon 다크pgmr 2017.12.28 10:00 신고 수정/삭제

      네, 가능합니다. 영상에서 원하는 영역의 부분영상을 잘라내는 것은 어려운 일이 아닙니다. opencv에서는 Mat sub_image = image(roi_rc).clone(); 과 같은 식으로 부분 영상을 얻어낼 수 있습니다.

  • hyun2 2018.04.14 17:40 신고 ADDR 수정/삭제 답글

    안녕하세요 다크프로그래머님. 항상 게시글을 통해 도움받고 있는 대학생입니다.
    다름이 아니라 현재 xml을 생성하는데 opencv harr/cascade training을 이용하고 있는데, 그 과정에서 질문이 생겨 이렇게 댓글남깁니다.
    첫번째 과정인 create sample에서 테스트를 위해 multi preserve 모드, width=100, height=200으로 하여 샘플을 추출한 결과 결과 602장의 sample을 얻어냈다는 창까지 확인하였습니다.

    Q. 그 다음 과정인 Training 에서
    cascade training(haar)을 선택 , 맞는 파일 명들을 넣어주고 width=100, height=200, npositives=500(생성된 602보다 좀더 작게 하여 해보았습니다), nNegatives=1000 로 놓고 진행해보았는데 "Out of memory"라는 error가 발생합니다.
    혹시 어느 부분에 문제가 있는지 조언을 주실수 있을까요?

    감사합니다.

    • BlogIcon 다크pgmr 2018.04.17 21:38 신고 수정/삭제

      저도 error 원인은 잘 모릅니다. 제가 짠 코드가 아니고 opencv의 코드를 포장만 한 것이라서, 어떤 상황에서 그러한 error 메시지가 나오는지 잘 모릅니다.. 다만 width=100, height=200은 조금 큰 값으로 보입니다. 이렇게 object size가 크면 학습이 잘 안될 것으로 여겨집니다. 아주 복잡한 패턴의 물체가 아니라면 1/10 크기로 해도 괜찮지 않을까 싶습니다.

  • uu 2018.08.20 16:30 신고 ADDR 수정/삭제 답글

    안녕하세요 ! 문서 잘 봤습니다!
    질문을 하나 드려도 될까요?
    보통 단일 이미지로 트레이닝 셋을 만들 때 여러 트레이닝 셋을 병합해서 실제 학습에 사용하나요?
    주어진 이미지가 별로 없어서 각도 변형을 통해서 트레이닝 셋을 만들려고 하는데 맞는 방법인지 모르겠네요 ㅠㅠ
    예로 서로다른 타겟 이미지에 대해서 opencv_createsamples -img 이미지파일, 각도 변형 옵션으로 생성된 .vec파일 여러개를 병합하여 training에 사용하나요?

    • BlogIcon 다크pgmr 2018.08.20 23:17 신고 수정/삭제

      본문에서 '6. 멀티 샘플들로부터 확장된 training 데이터 생성하기' 부분을 읽어보시면 좋겠습니다. 그리고 단지 테스트 목적이라면 관계없지만 정말 검출기를 만들어볼 생각이라면 Haar classifier를 적용하는 것은 정말 말리고 싶습니다. CNN 등의 딥네트워크를 이용하면 훨씬 성능이 좋을 것으로 생각됩니다.