[OpenCV 3.2] Canny Edge Detector - 가장자리 검출 알고리즘

영상에서 사각형 혹은 숫자 등의 물체를 인식할 때 형상의 테두리로 알 수 있다.

이미지를 그레이 이미지로 변환한 후 가장자리 검출 알고리즘을 이용하여 이미지를 이진화 하는 방법에 대해 정리한다.


1. Canny Edge Detector란?

Canny 에지 검출 알고리즘은 1986년도에 John F. Canny에 의해 고안되어 대중적으로 많이 사용되고 있다.

Canny 알고리즘은 에지 검출 알고리즘에 있어서 다음 세가지의 기준을 내놓는다.

낮은 에러율 : 실제 에지만을 탐지하는 능력

낮은 오차율 : 실제 에지와 탐지된 에지의 픽실 거리 차이를 최소화

최소한의 응답성 : 각 에지에 대해서는 한 번만의 검출


2. 소스 코드

1) canny 함수

void Canny(InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize=3, bool L2gradient=false )

image : 그레이 이미지

edges : 변환한 에지 이미지

threshold1 : 에지 임계값

threshold2 : threshold1 * ratio

apetureSize : 커널 사이즈


2) MFC에 Canny Edge 슬라이더 컨트롤 변수 추가하기

MFC 관련 소스 코드 참조 : http://poorman.tistory.com/157


3) Canny 함수 추가

3. 실행 결과

다음은 ...




컴퓨터 비전과 영상 처리에 대해 독학을 하면서 정리한 걸 적고 있습니다.

전공과 무관하며 전문적인 지식이 아니므로 개인적인 의견과 부족하고 틀린 점이 많습니다.

추가 지식 및 잘못된 점을 지적해주시면 공부하는데 많은 도움이 되겠습니다. 감사합니다^^

- 푸어맨


[Reference]

(OpenCV Canny 함수) http://www.docs.opencv.org/2.4.10/doc/tutorials/imgproc/imgtrans/canny_detector/canny_detector.html

(캐니 알고리즘) http://iskim3068.tistory.com/60

(숫자 인식) http://egloos.zum.com/skaria/v/1083349

(번호판 인식) http://mind3002.blogspot.kr/2016/01/cc-opencv-license-plates-recognition.html

[OpenCV 3.2] Histograms - 4 : Histogram Equalization (평활화)

이번 정리에서는 히스토그램 평활화로 명암대비를 개선시킨 이미지로 변환시킨다.


6. 히스토그램 평활화하기

1) 히스토그램 스트레칭과 히스토그램 평활화

 히스토그램 스트레칭은 이미지의 가장 밝은 픽셀값과 어두운 픽셀값을 기준으로 늘린 것 뿐이라면, 히스토그램 평활화는 이미지의 전체 픽셀 값을 균등하게 재배치한다. 그러므로 히스토그램 평활화는 밝기 값의 차이들이 적어서 명암대비가 세밀하게 이루어진다.

 다음은 위키 페디아에 실린 원본 이미지와 히스토그램 평활화가 이루어진 이미지의 누적 히스토그램을 보여준다.


2) 소스 코드

void cv::equalizeHist ( InputArray src, OutputArray dst )

src : gray image

dst : equalization histogram image

그레이 이미지를 equalizeHist를 한 후 히스토그램을 그려준다. 


3) 실행 결과

원본 이미지와 히스토그램

히스토그램 평활화 후 이미지와 히스토그램

지금까지 1차원 히스토그램을 표시했는데, 2차원 이상의 다차원 히스토그램도 존재한다.

다차원 히스토그램에 대해서는 추후 정리하도록 하고 다음은 Canny를 이용한 Edge(가장자리) 검출 알고리즘에 대해 정리한다.




컴퓨터 비전과 영상 처리에 대해 독학을 하면서 정리한 걸 적고 있습니다.

전공과 무관하며 전문적인 지식이 아니므로 개인적인 의견과 부족하고 틀린 점이 많습니다.

추가 지식 및 잘못된 점을 지적해주시면 공부하는데 많은 도움이 되겠습니다. 감사합니다^^

- 푸어맨


[Reference]

(OpenCV HistogramEqualization) http://docs.opencv.org/3.2.0/d4/d1b/tutorial_histogram_equalization.html

(equalizeHist) http://docs.opencv.org/3.2.0/d6/dc7/group__imgproc__hist.html#ga7e54091f0c937d49bf84152a16f76d6e

(위키 페디아) https://en.wikipedia.org/wiki/Histogram_equalization

(히스토그램 프로세싱) http://blog.naver.com/PostView.nhn?blogId=neverabandon&logNo=100053397929&parentCategoryNo=&categoryNo=&viewDate=&isShowPopularPosts=false&from=postView

(히스토그램 스트레칭) http://m.blog.naver.com/dlwjddns5/220687524811

[OpenCV 3.2] Histograms - 3 : Histogram Equalization (평활화)

이미지의 히스토그램을 그리는데 너무 밝은 이미지나 어두운 이미지의 경우 픽셀 값이 한쪽으로 치우치는 걸 볼 수 있다.

치우쳐 있는 픽셀 값들을 전체적으로 골고루 분산시켜 명암대비를 개선시키는 작업을 히스토그램 평활화라고 한다.


5. 누적 히스토그램 표시하기

누적 히스토그램을 표시함으로써 픽셀값의 분포 값을 시각화할 수 있다.

1) 소스 코드

이전 히스토그램 그리기 코드에 누적 히스토그램 코드를 추가한다.


2) 실행 결과

누적 히스토그램을 빨간 선으로 표시한다.


3) 이미지 분석

위의 렌나양 이미지는 누적 히스토그램을 보면 아다시피 픽셀값들이 골고루 분포되어 있다.

픽셀값이 한쪽으로 치우쳐 있는 이미지를 분석해보겠다.

다음은 히스토그램 평활화에 관한 위키페디아 출처 이미지이다.

이미지의 픽셀값 분포가 밝은 쪽으로 치우쳐 있는 걸 알 수 있다.

다음 정리에서 히스토그램 평활화를 이용하여 픽셀값이 고루 분포된 이미지로 변환한다.




컴퓨터 비전과 영상 처리에 대해 독학을 하면서 정리한 걸 적고 있습니다.

전공과 무관하며 전문적인 지식이 아니므로 개인적인 의견과 부족하고 틀린 점이 많습니다.

추가 지식 및 잘못된 점을 지적해주시면 공부하는데 많은 도움이 되겠습니다. 감사합니다^^

- 푸어맨


[Reference]

(히스토그램 평활화) http://webnautes.tistory.com/1043

(Wikipedia 이미지 출처) https://en.wikipedia.org/wiki/Histogram_equalization

(opencv documents) http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_imgproc/py_histograms/py_histogram_equalization/py_histogram_equalization.html#py-histogram-equalization

(히스토그램 평활화) http://m.blog.naver.com/dlwjddns5/220687524811

[OpenCV 3.2] Histograms - 2 : Find, Plot, Analyze

지난 정리에서 그렸던 히스토그램 이미지에 임계값(threshold)을 표시하고 임계값의 변화를 실시간으로 출력하도록 수정한다.


4. 히스토그램 이미지에 임계값 불러와서 선 긋기

1) 슬라이더 컨트롤에서 임계값 불러오기

참고 : http://poorman.tistory.com/157


2) 히스토그램 이미지에 선 긋기

- 먼저 선을 그을 히스토그램 이미지를 생성한다

Mat histImage(hist_height, hist_width, CV_8UC3, Scalar(0, 0, 0));

hist_height : 이미지 높이

hist_width : 이미지 너비

CV_8UC3 : 3채널 unsigned char (RGB색상)

Scalar(0, 0, 0) : Scalar( Blue, Green, Red )


- cv:line을 이용하여 히스토그램 이미지에 선 긋기

cv::line (InputOutputArray img, Point pt1, Point pt2, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)

img : 선을 그을 이미지 배경

pt1 : 선 좌표 Point(x1, y1)

pt2 : 선 좌표 Point(x2, y2)

&color : Scalar( Blue, Green, Red)

thickness : 굵기

type : 라인 타입

shift : 좌표 내의 fractional bits 수(?)


3) 소스 코드

[OpenCV 3.2] Histograms - 1 : Find, Plot, Analyze 에서 히스토그램을 그린 코드에 다음을 추가한다.

*여기서 선을 그을 때 주의해야할 건 좌표 값인데 Mat로 만든 이미지의 좌표는 다음과 같다.


4) 실행 결과






컴퓨터 비전과 영상 처리에 대해 독학을 하면서 정리한 걸 적고 있습니다.

전공과 무관하며 전문적인 지식이 아니므로 개인적인 의견과 부족하고 틀린 점이 많습니다.

추가 지식 및 잘못된 점을 지적해주시면 공부하는데 많은 도움이 되겠습니다. 감사합니다^^

- 푸어맨


[Reference]

(OpenCV 핸드북) http://darkpgmr.tistory.com/46

(cv:line) http://docs.opencv.org/3.2.0/d6/d6e/group__imgproc__draw.html#ga7078a9fae8c7e7d13d24dac2520ae4a2

[OpenCV 3.2] Histograms - 1 : Find, Plot, Analyze

히스토그램에 대한 지식과 OpenCV 라이브러리의 사용법에 대해 정리한다.


1. 히스토그램은 왜 필요한가?

영상 이진화의 적절한 임계값을 결정하기 위해서는 원본 영상의 픽셀값의 분포를 알고 분석해야한다.

300 x 300 사이즈의 작은 이미지 1장에만 픽셀수는 9만개이고, 한 픽셀이 갖을 수 있는 값은 0~255이므로 경우의 수는 9만x256 가지이다.

이러한 분포값을 알아보기 쉽게 그래프로 변환하여 시각화한 것을 히스토그램(Histogram)이라고 한다.

x축은 0~255 사이의 픽셀 값, y축은 해당하는 픽셀 값을 갖은 픽셀 수를 나타낸다.

2. OpenCV 라이브러리를 이용하여 히스토그램 계산하기

1) 히스토그램을 찾는 함수

void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false )

_1 images : 소스 이미지 배열, 히스토그램을 계산할 이미지들

_2 nimages : 소스 이미지 갯수, 소스 이미지 배열에 포함된 이미지들

_3 channels : 채널 번호 배열, 히스토그램을 계산할 채널 번호

 아래 그림과 같이 BGR 이미지 2장에 대해, 첫번째 이미지는 B 채널, 두번째 이미지는 G 채널에 대해서 히스토그램을 구하고자 한다면 {0, 4}를 배열에 넣어서 전달해야 한다. 

이미지 출처 - http://swprog.tistory.com/entry/OpenCV-histogram

_4 mask : 계산 영역, 옵션사항으로 Mat()를 전달하면 무시됨

_5 hist : 히스토그램 계산결과를 저장, 1차원 또는 다차원 배열

_6 dims : 히스토그램 계산결과를 저장한 _5 hist의 차원수, 32(CV_MAX_DIMS)보다 작은 자연수의 입력 필요

_7 histSize : 각 차원의 bin 개수, 빈도수를 분류할 칸의 개수

_8 ranges : 각 차원의 bin의 최소값과 최대값, 빈도수의 최소값과 최대값


2) 소스 코드


3. 계산한 히스토그램을 시각화

계산결과를 저장한 히스토그램 배열을 표시할 이미지의 너비값으로 normalize한 후에, line함수를 이용하여 빈도수를 세로로 선을 긋는다.

1) 소스 코드


4. 실행 결과




컴퓨터 비전과 영상 처리에 대해 독학을 하면서 정리한 걸 적고 있습니다.

전공과 무관하며 전문적인 지식이 아니므로 개인적인 의견과 부족하고 틀린 점이 많습니다.

추가 지식 및 잘못된 점을 지적해주시면 공부하는데 많은 도움이 되겠습니다. 감사합니다^^

- 푸어맨


[Reference]

[OpenCV 3.0.0-dev documentation] http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_imgproc/py_histograms/py_histogram_begins/py_histogram_begins.html#histograms-getting-started

[Histogram 그리기] http://swprog.tistory.com/entry/OpenCV-histogram

[히스토그램 평활화] http://webnautes.tistory.com/1043

[OpenCV 3.2] Image Binarization, Thresholding (영상 이진화, 임계값) - 6

threshold 변수 값의 변화에 따라 실시간으로 이진화 이미지를 출력해주도록 코드를 수정한다.


10. 변수 값에 따라 실시간으로 이진화 이미지 출력

1) 이미지 파일 경로 변수와 이진화 이미지 출력 함수의 클래스화

 이미지 파일 경로 변수와 이진화 이미지 출력 함수를 class COpenCVDlg : public CDialogEx 에 추가


2) 이미지 파일 경로 변수와 이진화 이미지 출력 함수의 정의


3) Type 콤보 박스 더블 클릭 -> 콤보 박스 변경 시 함수 내에 이진화 이미지 출력 함수 추가


4) 임계값, 변환값 슬라이더 변경 시 함수 내에 각각 이진화 이미지 출력 함수 추가


5) 실행 결과




컴퓨터 비전과 영상 처리에 대해 독학을 하면서 정리한 걸 적고 있습니다.

전공과 무관하며 전문적인 지식이 아니므로 개인적인 의견과 부족하고 틀린 점이 많습니다.

추가 지식 및 잘못된 점을 지적해주시면 공부하는데 많은 도움이 되겠습니다. 감사합니다^^

- 푸어맨


[Reference]

(꿀캠 움직이는 gif 이미지 만들기) https://www.bandisoft.co.kr/honeycam/buy/

[OpenCV 3.2] Image Binarization, Thresholding (영상 이진화, 임계값) - 5

threshold 함수의 thresh, maxval, type 세개의 변수 값을 변경하며 얻어진 이진화 이미지를 살펴보겠다.


9. MFC를 이용한 threshold 함수 분석 - MFC 프로젝트 수정

 - 이전에 생성한 이미지 파일을 불러와 이진화 이미지로 변환하는 프로젝트에 thresh, maxval, type 변수 설정 오브젝트를 추가한다.

 - thresh, maxval 은 0~255 범위의 슬라이더 컨트롤을, type 는 0~4 값의 콤보박스를 생성한다.


1) 다이얼로그 꾸미기

 다이얼로그에 이진화 타입을 보여줄 콤보박스, 임계값과 변환값을 표시해 줄 에디트 컨트롤과 슬라이더 컨트롤을 추가한다.


2) 이진화 타입의 콤보박스에 변수를 추가

 - 콤보박스 속성 -> Type를 Drop List로, Sort 를 False로 설정


 - 콤보박스 마우스 우측 클릭 -> Add Variable -> 컨트롤 변수(m_combo_thresh_type) 추가


 - BOOL COpenCVDlg::OnInitDialog() 함수 내에 콤보 박스 초기화 값 설정


- 실행 화면


3) 임계값의 에디트 컨트롤과 슬라이더 컨트롤에 변수 추가

 - 에디트 컨트롤 마우스 우측 클릭 -> Add Variable -> 컨트롤 변수(m_edit_thresh_value) 추가


- 슬라이드 컨트롤 마우스 우측 클릭 -> Add Variable -> 컨트롤 변수(m_slider_thresh_value) 추가 


 -  BOOL COpenCVDlg::OnInitDialog() 함수 내에 슬라이더 컨트롤 초기화 값 설정


 - 슬라이더 컨트롤 더블 클릭 -> 슬라이더 컨트롤 변경 시 함수에 슬라이더 값을 에디트 컨트롤에 표시하는 코드 추가


 - 에디트 컨트롤 더블 클릭 -> 에디트 컨트롤 값 변경 시 함수에 에디트 컨트롤 값을 슬라이더에 표시하는 코드 추가


- 실행 화면


4) 변환값의 에디트 컨트롤과 슬라이더 컨트롤도 3)과 같은 방법으로 변수 추가


5) threshold함수 변수에 설정 값 불러오는 코드 추가

 이전에 생성한 void COpenCVDlg::OnBnClickedButtonImgLoad() 함수 내 소스 코드를 수정


6) 실행 결과

 - Type [ Binary ], Threshold Value [ 100 ], Max Value [ 255 ]

 - Type [ Binary Inverted ], Threshold Value [ 100 ], Max Value [ 255 ]

- Type [ Truncate ], Threshold Value [ 100 ], Max Value [ 255 ]

- Type [ Threshold to Zero ], Threshold Value [ 100 ], Max Value [ 255 ]

- Type [ Threshold to Zero Inverted ], Threshold Value [ 100 ], Max Value [ 255 ]


여기까지 만든 툴은 컨트롤 값을 변경하고 매번 이미지를 로드해야하는 불편함이 있다.

다음은 threshold 컨트롤 값을 변경할 때 실시간으로 변경된 이미지를 출력하도록 해보겟다.




컴퓨터 비전과 영상 처리에 대해 독학을 하면서 정리한 걸 적고 있습니다.

전공과 무관하며 전문적인 지식이 아니므로 개인적인 의견과 부족하고 틀린 점이 많습니다.

추가 지식 및 잘못된 점을 지적해주시면 공부하는데 많은 도움이 되겠습니다. 감사합니다^^

- 푸어맨


[Reference]


[OpenCV 3.2] Image Binarization, Thresholding (영상 이진화, 임계값) - 4

OpenCV 라이브러리의 .이진화 함수인 threshold 함수에 대해서 더 알아보려고 한다.


8. threshold 함수에 대해서

 threshold (InputArray src, OutputArray dst, double thresh, double maxval, int type, Stream& stream=Stream::Null())

함수에서 우리는 thresh, maxval, type 세가지의 값을 조정하여 원하는 이진화 이미지를 얻을 수 있다.

1) thresh

 thresh는 이분화의 기준 값이다. Gray Image에서 thresh 값을 기준으로 thresh 초과 값과 이하의 값으로 나누어 이미지를 변환한다.

2) maxval

 maxval은 type가 Binary, Binary Inverted의 경우에 사용되는 변환 값을 나타낸다.

3) type

 type는 5종류로 Binary, Binary Inverted, Threshold Truncated, Threshold to Zero, Threshold to Zero Inverted 로 나누어진다.

가로는 픽셀의 좌표, 세로는 픽셀의 값, 파란색은 thresh 값을 나타낸다.

 - Binary ( type = 0 )

 Binary는 thresh 값을 기준으로 초과 값은 maxval, 이하는 0으로 변환한다.

 - Binary Inverted ( type = 1 )

 Binary Inverted는 thresh 값을 기준으로 초과 값은 0, 이하는 maxval로 변환한다.

 - Truncate ( type = 2 )

 Truncate는 thresh 값을 기준으로 초과 값은 thresh 값으로, 이하는 원래 값 그대로 변환한다.

 - Threshold to Zero ( type = 3 )

 Threshold to Zero는 thresh 값을 기준으로 초과 값은 원래 값 그대로, 이하는 0으로 변환한다.

 - Threshold to Zero Inverted ( type = 4 )

 Threshold to Zero Inverted는 thresh 값을 기준으로 초과 값은 0, 이하는 원래 값 그대로 변환한다.


다음은 MFC를 이용하여 세가지의 값을 자유조절하면서 변환하는 이미지를 살펴보겠다.




컴퓨터 비전과 영상 처리에 대해 독학을 하면서 정리한 걸 적고 있습니다.

전공과 무관하며 전문적인 지식이 아니므로 개인적인 의견과 부족하고 틀린 점이 많습니다.

추가 지식 및 잘못된 점을 지적해주시면 공부하는데 많은 도움이 되겠습니다. 감사합니다^^

- 푸어맨


[Reference]

(threshold) http://docs.opencv.org/3.0-beta/modules/cudaarithm/doc/element_operations.html#double cuda::threshold(InputArray src, OutputArray dst, double thresh, double maxval, int type, Stream& stream)

[OpenCV 3.2] Image Binarization, Thresholding (영상 이진화, 임계값) - 3

OpenCV 라이브러리를 이용해서 이전 소스 코드에서 불러오는 이미지의 이진화를 해보겠다.


7. 이미지 이진화하기

1) 소스 코드

2) 실행 결과


다음은 threshold 함수에 대해서 자세히 알아보겠다.




컴퓨터 비전과 영상 처리에 대해 독학을 하면서 정리한 걸 적고 있습니다.

전공과 무관하며 전문적인 지식이 아니므로 개인적인 의견과 부족하고 틀린 점이 많습니다.

추가 지식 및 잘못된 점을 지적해주시면 공부하는데 많은 도움이 되겠습니다. 감사합니다^^

- 푸어맨


[Reference]

(threshold) http://docs.opencv.org/3.0-beta/modules/cudaarithm/doc/element_operations.html#double cuda::threshold(InputArray src, OutputArray dst, double thresh, double maxval, int type, Stream& stream)

+ Recent posts