Fogeaters, Light The World.

12

2016-Mar

[OpenCV] 마커 추출

작성자: title: MoonBlonix IP ADRESS: *.148.87.98 조회 수: 1406

마찬가지로 아래 문자인식, 레이블링 글과 동일한 블로그.


출처 :: http://martinblog.net/827


예제파일

http://fogeaters.cafe24.com/xe/board11/13777


OpenCV 강좌 06. 마커 추출 (1) - 잡영 제거

K. Martin 2009.07.02 23:57
본 장에서는 마커 추출을 위해 레이블의 크기정보를 토대로 잡영여부를 판단하고 이를 제거하는 방법을 소개한다.


1. 레이블링 클래스에 잡영제거 루틴 추가

K-20160312-520006.png

BlobSmallSizeConstraint(int nWidth, int nHeight)는 지정한 값 보다 작은 레이블들을 제거하고,
BlobBigSizeConstraint(int nWidth, int nHeight)는 지정한 값 보다 큰 레이블들을 제거한다.
각각의 함수는 클래스 내부에서 각각 _BlobSmallSizeConstraint()와 _BlobBigSizeConstraint()를 호출한다.



2. 제거 알고리즘의 작성(작은 레이블을 제거하는 루틴)


K-20160312-520169.png



각각의 레이블들을 지정한 width와 height 값과 비교하여,
큰 값들은 temp에 저장하고, 작은값(잡영으로 판단한 값)을 가지는 레이블은 과감히 제낀다 -_-a
이후 temp의 내용을 원래 레이블 크기정보가 들어있던 rect에 옮겨 담음으로써 마무리된다.


3. 잡영 제거
- 영상의 80% 이상, 30px 이하의 레이블들은 모두 제거한다.


K-20160312-520283.png


강좌가 금방이라도 다 끝나버릴 것 처럼 빠르게 진행되고 있지만,
실제로는 사이사이 엄청나게 많은 고민과 변화가 필요하다.

예를들어, 지금은 단순히 OTSU의 이진화 방법을 이용하고 있지만,
조명의 영향을 덜 받기 위해 배경평면을 만들어 낸다던지,
이진화 기법을 개선하기 위해 Kmeans 알고리즘 등을 이용하여 추출률을 높힐 수 있다.
(실제로 번호판 문자의 추출에 본 알고리즘을 적용하여 사용하고 있다.)

또한, 레이블링 이후 검증 방법에서 가로세로 비율을 이용하여 잡영을 제거 한다던지,
적당한 크기를 미리 정하여 휴리스틱하게 맞춰가는 방법 등도 고려할 수 있다.

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

OpenCV 강좌 07. 마커 추출 (2) - 마커 검증

K. Martin 2009.07.07 00:05
앞서 구한 '잡영이 제거된 영상'으로부터 이야기는 진행된다.


이번 장은 앞서 검출된 마커 후보영역들 중에서,
실제 마커영역이 가지는 특징을 가지는 것을 최종적으로 남기는 검증단계를 구현한다.

검증의 방법은 간단하다.
레이블의 내부에 홀이 있는지 없는지 파악한 뒤,
그 홀의 위치와 크기를 외부 레이블의 그것과 비교해 보고,
현재 레이블이 마커인지 아닌지 구분해 내는 것이다.

1. 검증 알고리즘의 구현
- 만들어둔 레이블링 알고리즘 사용의 적극 권장!

K-20160312-523141.png 

이전에 작성하였던 프로그램에서, 각 레이블에 빨간색을 칠하는 부분에 검증 알고리즘을 넣으면 되겠다.
보다시피 몇 줄 안되면서도 동족방뇨스럽기 그지없는 코드이지만, 결과는 꽤나 만족할 만 하다. (자화자찬-_-)

홀을 찾는다는 것은 반전된 이미지의 개체(레이블)를 찾는 것과 같은 의미이다. (쉽게가자)
각 레이블들의 가로세로 정보를 토대로 각 레이블을 담을 새로운 이미지(sub_gray)를 생성한 뒤,
여기에 각각의 레이블 이미지를 반전(CV_THRESH_BINARY_INV)하여 담는다.

반전된 이미지를 레이블링 한 뒤,
그것의 크기가 테두리 레이블 크기의 40% 이상, 80% 이하인 것들만을 남기고 제거한다.
적절한 수치는 마커의 크기에 따라 테스트를 계속 하면서 바꿔줄 수 있을 것 같다.

이후, 
반전된 이미지의 레이블(홀)이 테두리 레이블의 가장자리에 있다는 것은,
이 테두리 레이블이 닫힌 형태가 아닌라는 것, 즉. 홀이 존재하는 것이 아니라는 말이므로 과감하게 제낀다.

홀은 녹색으로 칠해준다.


이후 작업 예고 >
먼저, 추출된 마커의 외부/내부 사각형의 네 꼭지점을 구한다.
이때, 마커 내부 사각형의 꼭지점 정보는, 
사각형 내부 영상을 정규화하고 어떤 문자를 담고 있는지 파악하는데 사용 할 것이고,
외부 사각형의 꼭지점 정보는,
뮤직비디오의 영상을 마커의 모양과 동일하게 와핑하여 출력시키는데 사용 할 것이다.


와핑 관련 예습 자료 : cvWarpPerspective() 사용 방법


ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ


OpenCV 강좌 08. 마커 추출 (3) - 마커 꼭지점 구하기

K. Martin 2009.07.15 21:37
마커의 영역이 추출되면 그 마커의 윤곽선만을 추출해 낼 수 있으며,
이를 위해 OpenCV에서는 cvFindContours() 함수를 제공하고 있다.

/* Retrieves outer and optionally inner boundaries of white (non-zero) connected
   components in the black (zero) background */

CVAPI(int)  cvFindContours( CvArr* image, CvMemStorage* storage, CvSeq** first_contour,
                            int header_size CV_DEFAULT(sizeof(CvContour)),
                            int mode CV_DEFAULT(CV_RETR_LIST),
                            int method CV_DEFAULT(CV_CHAIN_APPROX_SIMPLE),
                            CvPoint offset CV_DEFAULT(cvPoint(0,0)));
CvArr* image는 0을 배경으로 0이 아닌 값(백색)을 개체로 하는 영상이며,
CvSeq** first_contour에 윤곽선 정보가 들어간다.

이를 이용하여 윤곽선을 추출한 뒤, 이를 이용하여 마커의 네 꼭지점을 구한다.

1. 윤곽선 검출

CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* contours   = 0;


K-20160312-524541.png


마커의 이미지가 들어갈 영상을 생성한 뒤 윤곽선을 추출한다.
다섯 번째 인수인 윤곽 추출 모드는 CV_RETR_TREE로 지정한다. 이는 영상 내의 모든 윤곽을 추출해 분기된 윤곽 모두를 계층구조로 나타낸다. 여섯 번째 인수는 윤곽점 중 특징점(두 점을 잇는 직선으로 표현 안되는 점)들만 배열에 정렬하기 위해 CV_CHAIN_APPROX_SIMPLE로 둔다.
cvDrawContours()를 이용하면 영상 위에 간단하게 윤곽선을 출력할 수 있다.


2. 꼭지점 추출
- 임의의 점에서 가장 먼 점을 첫 번째 꼭지점으로 설정한다.


K-20160312-524676.png


CvSeq* 형의 contours 변수에서 CvPoint* 형의 실제 좌표를 가져올 수 있다.
CvPoint *st  = (CvPoint *)cvGetSeqElem( contours, 0 );
시퀀스의 첫 점을 초기위치로 하여 모든 특징점들과의 거리를 계산한다.

첫 번째 점은 corner[0]에 저장한다.


- 같은 방법으로 두 번째 꼭지점을 구할 수 있다.
직사각형의 경우 당연히 대각점이 가장 먼 점이 되지만, 
사각형은 경우에 따라 아래와 같이 여러 방향에서 두 번째 꼭지점이 나타난다.
두 번째 점은 corner[1]에 저장한다.

- 세 번째 꼭지점은 첫 번째, 두 번째 점에서 가장 먼 점을 구한다.
세 번째 점은 corner[2]에 저장한다.


K-20160312-524935.png



- 이렇게 하면 어떻게든 세 개의 꼭지점을 구해낼 수 있다.
이제 네 번째 꼭지점이 눈앞이다.

- 그런데 문제가 있다.
같은 방법으로 네 번째 꼭지점을 구하는 일이 항상 가능한 일이 아니라는 점은 아래에서 확인할 수 있다.


K-20160312-525122.png



첫 번째 점은 좌측 하단의 점 (136,381)이고, 두 번째 점은 우측 하단의 점 (418,340)이다.
첫 번째, 두 번째 점에서 거리가 가장 먼 점은 좌측 상단의 점 (153,255)이다.
세 개의 점에서 가장 먼 점이 우측상단의 점이 되어야 하지만, 애석하게도 그 점은 우측 하단의 점 (481, 336)이다.


- 이런 이유로 거리정보만으로 네 꼭지점 모두를 구하는 것은 무리가 있다고 하겠다.
이 시점에서는 사각형의 넓이정보를 이용한다.


K-20160312-525340.png


- 알고리즘에서는 이미 구해둔 세 개의 꼭지점과 나머지 한 점. 즉, 윤곽선 상의 모든 점 (x, y)을 세 개의 삼각형으로 나눈 뒤 그 넓이의 합이 최대가 되는 점 (x, y)를 네 번째 꼭지점으로 정한다.


K-20160312-525527.png


3. 추출된 꼭지점과 좌표 출력
- 글자는 안겹치게 5픽셀씩 오른쪽으로 밀어주는 센스! ^^*


K-20160312-525608.png


List of Articles
번호 제목 글쓴이 날짜 조회 수
공지 [Web] 클라우드 IDE + 2 title: MoonBlonix 2017-06-25 15128
72 [VS] 다중 프로젝트 dll로 연결하기 title: MoonBlonix 2016-11-13 1627
71 [VS] DllMain 에서 DLL 호출하기 title: MoonBlonix 2016-11-13 1593
70 [Win API] 유니코드, 멀티바이트, TCHAR 문자열함수 title: MoonBlonix 2016-11-08 1459
69 [AVR] LED 입출력을 제어해보자 - 1 file title: Zwei츠바이 2016-09-16 1603
68 [알고리즘] 문자열 검색 title: MoonBlonix 2016-04-17 1701
67 [AVR] ATTiny13A 그리고 ADC에 대해 + 2 title: MoonBlonix 2016-04-01 1546
66 [OpenCV] 32bit(x86) 빌드 및 초기설정(GPU, TBB, IPP 등) title: MoonBlonix 2016-03-29 1545
65 [OpenCV] Mat 픽셀 접근방법 title: MoonBlonix 2016-03-26 1678
64 [OpenCV] Mat 구조를 Tesseract 에서 쓸 수 있게 title: MoonBlonix 2016-03-24 1454
63 [영상처리] Bitmap 구조 분석 title: MoonBlonix 2016-03-24 1706
62 [OpenCV] 3.x - 캠 사용 & 얼굴 인식 title: MoonBlonix 2016-03-24 1683
61 [tesseract] (3.0.4) vs2013으로 빌드하기 title: MoonBlonix 2016-03-23 1607
60 [OpenCV] 3.1 설치하기 file title: MoonBlonix 2016-03-17 1426
59 AVR / ARM / DSP 비교 file + 2 title: MoonBlonix 2016-03-12 1738
58 (작성중)[OpenCV/ARM/DSP] 임베디드 환경에서의 OpenCV 사용 title: MoonBlonix 2016-03-12 1604
57 [OpenCV] 예제 코드 모음 file title: MoonBlonix 2016-03-12 1793
» [OpenCV] 마커 추출 file title: MoonBlonix 2016-03-12 1406
55 [OpenCV] 영상 이진화 & 레이블링(Blob Labeling) file + 3 title: MoonBlonix 2016-03-12 1537
54 [OpenCV] 문자 인식 file + 1 title: MoonBlonix 2016-03-12 1468
53 [AVR] ATTiny13A 에 대한 숨겨진 사실들 title: MoonBlonix 2016-03-10 1630