윤곽선 검출 Edge Detection은 물체에 경계선을 추출하기 위한 기술 입니다. 우리가 알고자 하는 물체의 모양, 크기, 위치 등 정보를 확인하고자 할 때 사용되는 기술로 알고리즘의 전처리 과정에서 이용됩니다. 요즘 기술개발이 활발히 진행되고 있는 Machine Learning의 한 분야인 딥러닝 Deep Learning에서 영상의 특징점 Feature 을 정의하는데도 사용되는 전처리 기술 입니다.

Edge Detection 기술이 사용 된지는 오래됐으며 현재까지도 폭넓게 사용되고 있고, 수학적 접근방식에 따라 다양한 방법들이 존재합니다. 현 이야기에서는 OpenCV에서 제공되는 윤곽선 검출 도구 중 Sobel Edge Detection Canny Edge Detection 기술 사용법에 대한 설명입니다. Edge Detection에 앞에 붙어 있는 Sobel Canny는 개발자에 이름이며 WIKIPEDIA에 의하면Sobel Filter 1968년과 Canny Edge Detector 1986년에 개발되었습니다. 정말 오래된 기술 입니다만 현재도 상당히 많이 사용되고 있고, 이러한 윤곽선 검출 기술에 기본 원리는 미분 연산자 Differentiation Operator에 의한 밝기 변화 탐색 입니다. 다시 말해, 물체의 가장자리에서 밝기 변화가 크므로 Pixel 값에 차이를 통해 윤곽선 유무를 판단할 수 있다는 의미이기도 합니다.

위에서처럼 OpenCV에서 제공되는 Edge Detection 함수인 Sobel Canny를 볼 수 있습니다. 먼저 cvSobel 함수를 살펴보면 앞에서 설명한 기본 함수들에서처럼 입력영상인 “src”와 결과영상을 담기위한 “dst”가 보입니다. “aperture_size” Sobel Mask의 크기를 나타내고 “3”이면 3X3을 의미합니다. “xorder”“yorder” Sobel Mask 연산 시 결과값의 위치를 나타내는데 3X3의 경우 중심인 xorder = 1 yorder = 1 이 되며, Mask의 시작점은 (0, 0)이니 2가 아닌 1이 됩니다.

 

Sobel 사용 예)

cvSobel( Input_Image, Result_Image, 1, 1, 3)

cvConvertScaleAbs(Result_Image, Convert_Result_Image, 1, 0)

 

cvSobel 함수 사용은 위에 예처럼 사용하면 되는데 cvConvertScaleAbs()라는 함수가 더 있죠? cvSobel 함수 사용 시 주의할 점이 있습니다. 앞에서 언급했듯이 Edge Detection의 원리가 Pixel의 차이를 이용하기 때문에 결과에서는 마이너스 “-“ 값이 존재하고 Result_Image Depth는 보통 Input_Image Depthunsigned 8-bit 이니 signed 16-bit 으로 구성되어야 합니다. 따라서 최총 결과를 확인하기 위해서는 절대값을 이용하여 다시 unsigned 8-bit 으로 변환해 줘야 하고, 이때 사용되는 함수가 cvConvertScaleAbs() 입니다.

 

cvCanny 함수의 경우 입력영상인 “image”와 결과영상인 “edges”가 보이고 “apertureSize = 3” Sobel Mask   3X3을 의미합니다. 여기서 cvSobel 함수와 다르게 “threshold1”“threshold2”를 입력하게 되어 있는데, “threshold1” 이하는 외곽선이 아닌 영역으로 “threshold2” 이상은 외곽선인 영역, 그리고 “threshold1”“threshold2”의 사이는 Canny Procedure에 의해 외곽선 유무를 판단하게 됩니다.

 

Canny 사용 예)

cvCanny( Input_Image, Result_Image, 100, 200, 3 )

 

cvCanny 사용 예에서 threshold1threshold2 100 2000 ~ 255의 범위를 갖는 8-bit 영상 기준으로 설정된 값을 의미하고, Result_Image Input_Image와 동일한 속성으로 설정하면 됩니다. 앞에 설명과 그림 결과와 같이 8-bit Input_Image 기준으로 cvSobel 함수의 최종 Result_Image 8-bit 그레이 Gray 영상이며, cvCanny 함수의 경우 8-bit 바이너리 Binary 영상이니 이것만 주의해서 활용하면 됩니다. Sobel Canny의 수학적 또는 알고리즘 접근에 대해서는 영상처리기술에서 추가적으로 다뤄보도록 하겠습니다.

영상처리 도구에 설명된 OpenCV Template Matching 활용 시 선택할 수 있는 “Method”에 대한 추가 설명입니다. 아래 그림에서처럼 총 6가지 수식 중 하나를 사용할 수 있게 되어 있고, “Method” 중에 _NORMED 표시는 정규화 Normalization에 약자 정도로 보면 됩니다. 수학적 접근에 기반하여 각 수식들은 두 영상 간 같은지 또는 다른지 정도를 거리 Distance로 정의하고 있고 간단한 수식(1)에서부터 복잡한(6) 수식으로 표현하고 있습니다.

 

 

 

위 수식들에서 T Template, ISource Image로 보고, 실제 동작으로 I를 기준으로 T를 움직이면서 픽셀 Pixel 간 처리를 통해 Matching 정도를 분석하게 됩니다.

 

Method 1. CV_TM_SQDIFF은 차이값의 제곱합 Square Sum of Difference을 의미하고 수식에서처럼 픽셀 간 차이가 거리가 되며 결론적으로 가장 작은 값을 갖는 위치가 Matching 위치로 볼 수 있습니다.

Method 3. CV_TM_CCORR은 상관관계 Cross Correlation을 의미하고 픽셀 간 곱의 전체 합으로 Template 간 거리 정도를 나타내며 최종 가장 큰 값을 갖는 위치가 Matching 위치가 됩니다.

Method 5. CV_TM_CCOEFF는 상관계수 Cross Correlation Coefficient로 표현되고 위 방법들과 다르게 Template Source 에 픽셀 평균 Mean값을 제외한 곱에 전체 합을 거리로 나타내며 특징지도 Feature Map에 가장 큰 값을 갖는 위치가 Matching 위치가 됩니다.

 

Method 1 2와 다르게 수식(5)는 평균값이 추가되어 조금 복잡해졌죠. 일반적으로 수식이 복잡해지면 조금 더 외부요인에 강건해지는 효과가 있습니다. 실무에서 영상정합 시 잡음이나 밝기 변화 등에 외부요인을 고려해야 하고 수식(5) 상관계수는 영상 간 선형적 밝기 변화에 수식(1) (2)보다 강건한 효과가 있습니다. 더 나아가 _NORMED이 붙는 정규화 함수가 추가되면 Matching 성능이 더욱 향상됩니다.

 

정규화 관련해서는 위 수식에서처럼 Pearson correlation coefficient를 통해 통계학 Statistics적으로 유도해 볼 수 있습니다. 실무에서 패턴 정합은 많은 외부요인들을 고려해야 하며 OpenCV에 제공되는 방법 외에도 다양한 방법들이 존재합니다. 위 방법들에 기본 원리를 잘 이해하면 실무에서 응용하는데 상당한 도움이 될 수 있습니다.

물체 추적 Object Tracking 분야에서 주요하게 사용되는 기술이 Pattern Matching 기술 입니다. 물체 추적이라는 단어에서 느껴지는 것처럼 실시간 영상처리에 한 분야 입니다. 보안 및 감시 카메라에서 출력되는 연속 영상 또는 동영상 처리 정도로 이해하면 됩니다. 알고리즘 구현에서는 크게 물체 탐색과 추적으로 나뉘고, 예를 들어 물체가 자동차라면 첫 영상에서 자동차를 추출하고 자동차 영역을 이용하여 다음 영상에 차량 위치를 탐색하고자 할 때 사용되는 기술이 Pattern Matching에 응용 입니다.

OpenCV 라이브러리에서는 Pattern Matching 함수를 제공하고 있습니다. 아래 그림에서처럼 Pattern(Template) 영상과 원본영상 Input Image 만 있으면 테스트를 해 볼 수 있고 이를 통해 다양한 실무 응용분야를 찾을 수 있습니다. 결과에서 Feature Map을 볼 수 있는데 Matching에 최종 결과로 볼 수 있고, Feature Map에 가장 높은 Pixel 값에 위치가 Template과 가장 유사한 영역으로 생각할 수 있습니다.

 

 

위 함수를 보면 C/C++ Python 언어로도 사용할 수 있게 제공되고 있습니다. 함수 사용시 입력 변수들 중 “Method” Matching에 사용되는 수식이라고 보면 되며 실제 다양한 수학적 접근 방법들이 사용되고 있습니다. OpenCV에서는 여섯 가지 방법들을 제공하고 있습니다. 그 중에 하나가 아래 사용 예에 “CV_TM_SQDIFF”가 있는데 Pixel 간 차이 제곱에 총합 Sum of Square Difference을 의미합니다. 수학적 방법에 상세한 내용은 영상처리기술에서 기술하도록 하겠습니다.

 

Template Matching 사용 예)

C: void cvMatchTemplate( Input_Image, Template, Feature_Map, CV_TM_SQDIFF )

 

cvMatchTemplate 함수 수행 후에 최종 결과인 Feature Map에서 최대값에 위치를 찾을 때 손수 코딩을 통해 찾을 수 있지만 OpenCV 함수에 하나인 cvMinMaxLoc을 사용할 수 있습니다. 이 함수를 이용하면 최대 및 최소값과 영상에서 그 위치를 추출할 수 있습니다.

실무에서는 Pattern Matching 기술 개발 시 OpenCV에서 사용되는 General Method도 사용할 수 있지만 물체에 특성에 맞게 Feature를 정의해서 직접 알고리즘을 구현하여 적용할 때도 있습니다. 하지만 기존 방법들의 답습을 통해 장단점을 파악하는 것도 자신만에 기술을 고도화 시킬 수 있는 방법이기도 하겠죠.

 

영상에 타원 형태에 물체를 찾고자 할 때 영상처리를 통해 외곽선을 추출하게 됩니다. 보통 에지탐색(Edge Detection) 기법들을 통해 외곽선을 탐색하게 되는데 주변 PixelIntensity 차이를 이용하는 (수학적으로 미분/Differential Equation 이라고 합니다.) 이러한 기법들은 영상의 화질 특성에 의해 완전한 외곽선이 아닌 끊겨 있거나 파편적인 선으로 추출되는 경우가 많습니다. 이 때 끊겨 있는 선들의 정보를 활용하여 타원을 추정할 때, OpenCV Ellipse Fitting 함수를 이용할 수 있습니다.

 

 

그림에서와 같이 fitEllipse 함수에 입력인 “points”은 영상에서 외곽선에 좌표를 의미합니다. C/C++ 함수의 출력인 “RotatedRect/CvBox2D”는 구조체로 중심좌표 Center, 크기 Size, 기울어진 각도 Angle 정보를 담고 있습니다. 타원 추정 결과를 확인 할 때는 앞에서 기술한 기본 그리기 함수인 아래 cvEllipse를 이용하면 됩니다. 입력 변수 중 “start_angle/end_angle”은 그려줄 각도를 나타내고 전체를 표시하고 싶으면 “start_angle = 0/end_angle = 360”으로 설정할 수 있습니다. 0~180으로 설정하면 타원에 반만 그려 주겠죠.

 

타원 그리기 함수 예)

C: void cvEllipse(CvArr* img, CvPoint center, CvSize axes, double angle,

     double start_angle, double end_angle,

     CvScalar color, int thickness=1, int line_type=8, int shift=0 )

 

실제 산업분야에서 타원이나 원을 추출할 때 다양하게 응용되고 있고 활용범위가 넓습니다. 타원 추정 이론과 함께 알아 두시면 많은 도움이 될 수 있습니다. OpenCV에 구현된 함수는 “A Buyer’s Guide to Conic Fitting”을 기반으로 하고 있습니다.

영상처리 오픈 라이브러리인 OpenCV를 사용하려면 기본적인 구조와 이용 방법을 알아야 합니다. 이번 이야기에서는 OpenCV 활용을 위해 가장 기본 함수 중 하나인 Line’에 대해 알아 보겠습니다. 단어에서처럼 한 점에서 다른 한 점까지 선을 긋는 함수이고 OpenCV 홈페이지에도 설명이 잘 되어 있습니다. 초기에는 C/C++ 언어만 제공되었는데 현재에는 Python에서도 활용될 수 있게 기능을 제공하고 있네요.

 

 

함수에 첫 번째 “img”는 선을 그릴 영상, “pt1 / pt2”는 선에 시작 점과 끝나는 점을, “color”는 선에 색깔을 나타냅니다. “thickness”는 선의 두께, “line type” 4, 8, CV_AA 중 하나를 선택할 수 있는데 선을 표현하는 거칠기 정도로 이해하면 됩니다. C 또는 C++ 함수를 사용 시 “img” 앞에 구조체 형이 다르기 때문에 주의해서 사용해야 되고 C 함수에서는 보통 “IplImage” 구조체를 사용합니다.

 

사용 예)

cvLine( Input_Image, cvPoint(10,10), cvPoint(100,100), CV_RGB(255, 255, 255), 1, CV_AA, 0);

 

C 함수 이용 시 위 예에서 처럼 활용할 수 있습니다. 설명했듯이 “Input_Image” IplImage 구조체이며 “pt1 / pt2” cvPoint(x, y)“color” CV_RGB(red, green, blue)로 대입 할 수 있습니다. CvPointOpenCV 사용에 맞게 정의된 구조체로 볼 수 있습니다. 몇 번 실습을 해보면 쉽게 익힐 수 있고, Line 함수를 활용할 수 있으면 Circle, Rectangle, Ellipse OpenCV에서 제공되는 기본 함수들을 쉽게 이용할 수 있게 됩니다.

경험 상 함수에 사용법은 개인 블로그 등을 참조하는 것보다 그 라이브러리 설명서를 이용하여 익히는 것이 가장 정확한 방법인 듯 합니다. 기본 함수를 잘 익히면 유사한 함수들은 쉽게 익힐 수 있고 응용이 가능해 질 수 있습니다.

+ Recent posts