[openCV] Convolution & Mask (2)
openCV

[openCV] Convolution & Mask (2)

 

 

 

저번에 못다 한 정리를 마쳐보자

 

이번에는 Edge Detection을 조금 심화적으로 다룰 예정이다.

 

1. Sobel_Detection

 

Sobel Detection에 대해서 간단하게 알아보자

 

edge

openCV에서 Edge는 Pixel Value가 급격하게 변하는 순간입니다.

 

위와 같이 1차원 그래프로 표현하였을 때 갑자기

Pixel Value가 커지는 부분이 Edge로 형용이 가능합니다.

 

여기서의 Edge의 Pixel Vaule를 구하는 방법은 간단합니다.

 

저 Pixel Value를 나타낸 그래프를

미분을 하게 되면 Edge를 알 수 있습니다. 

 

미분한 그래프

미분을 한 그래프를 그리게 되면

픽셀 값이 급격하게 증가한 부분이 보이게 됩니다.

 

그러면 주변보다 1차 미분값이 큰 부분을 Edge로 검출하게 됩니다.

 

Sovel Mask (x)
Sovel Mask (y)

1차 미분의 근사값을 계산하기 위해 미리 정의한 Convolution Mask와

Input Image를 Convolution Operate 해주어 Edge를 검출해줍니다.

 

Sovel에서는 신기한 특징이 있습니다.

 

Sovel에서 X 방향 Edge 검출과 Y 방향 Edge 검출을 할 때에

쓰이는 Mask가 위의 사진처럼 다릅니다.

 

코드를 살펴보자

 

 

 

 

import cv2
import numpy as np
import imutils

img = cv2.imread("./test.png")

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

img_sobel_x = cv2.Sobel(img_gray, cv2.CV_64F, 1, 0, ksize=3)
img_sobel_x = cv2.convertScaleAbs(img_sobel_x)

img_sobel_x = imutils.resize(img_sobel_x, width=300)
cv2.imshow("Sobel", img_sobel_x)

cv2.waitKey(0)

cv2.destroyAllWindows()

 

Sovel Mask (x)

위 코드는 Sovel Mask (X)를 이용해서

Edge 중 수직 성분을 검출하는 코드이다

 

중요한 것만 살펴보자

 

img_sobel_x = cv2.Sobel(img_gray, cv2.CV_64F, 1, 0, ksize=3)

cv2.Sobel(src, ddepth, dx, dy [, dst [, ksize [, scale [, delta [, borderType]]]]])

 

src = Gray_Scale_Img

ddepth = output image의 depth, -1이면 input image와 동일.

 

CV_8U: 이미지 픽셀값을 uint8로 설정

CV_16U: 이미지 픽셀값을 uint16으로 설정

CV_32F: 이미지 픽셀값을 float32로 설정

CV_64F: 이미지 픽셀값을 float64로 설정

 

dx = x축 미분 차수

dy = y축 미분 지수

ksize = Kernel Size

 

우리는 GrayScale_Image를 1차 미분하도록 설정한 것과 다름없다.

 

img_sobel_x = cv2.convertScaleAbs(img_sobel_x)

cv2.convertScaleAbs

 

우리가 위 cv2.Sobel을 통해 미분한 값에 절대값을 씌워주고

 

값 범위를 8bit unsigned int형으로 바꿔준다.

 

[ Result ]

 

original Image

 

sobel Image

 

확실히 수직 성분만 검출된 것을 확인할 수 있다.

 

1-2. Sovel (Y) Edge Detection

 

중요한 부분은 위에서 설명했으니

코드와 결과만 간단하게 보자

 

import cv2
import numpy as np
import imutils

img = cv2.imread("./test.png")

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

img_sobel_y = cv2.Sobel(img_gray, cv2.CV_64F, 0, 1, ksize=3)
img_sobel_y = cv2.convertScaleAbs(img_sobel_x)

# img_sobel_x = imutils.resize(img_sobel_x, width=300)
# img = imutils.resize(img, width=300)

# merged = np.hstack((img, img_sobel_x))

while True:
    cv2.imshow("Original", img)
    cv2.imshow("Sobel", img_sobel_y)

    key = cv2.waitKey(1)

    if key == 27:
        break

cv2.destroyAllWindows()
img_sobel_x = cv2.Sobel(img_gray, cv2.CV_64F, 0, 1, ksize=3)

바뀐 곳은 한가지다

 

X축 미분 차수를 0으로 넣어주고

Y축 미분 차수를 1로 넣어주었다.

 

[ Result ]

 

Original Image
Soble Image

수평 방향 성분들이 잘 검출된 것을 확인할 수 있다.

 

 

1-3. Merged

 

위의 결과들을 합치는 방법을 알아보자

 

import cv2
import numpy as np
import imutils

img = cv2.imread("./test.png")

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

img_sobel_x = cv2.Sobel(img_gray, cv2.CV_64F, 1, 0, ksize=3)
img_sobel_y = cv2.Sobel(img_gray, cv2.CV_64F, 0, 1, ksize=3)

img_sobel_x = cv2.convertScaleAbs(img_sobel_x)
img_sobel_y = cv2.convertScaleAbs(img_sobel_y)

img_sobel = cv2.addWeighted(img_sobel_x, 1, img_sobel_y, 1, 0)

# img_sobel_x = imutils.resize(img_sobel_x, width=300)
# img = imutils.resize(img, width=300)

# merged = np.hstack((img, img_sobel_x))

while True:
    cv2.imshow("Merged", img_sobel)

    key = cv2.waitKey(1)

    if key == 27:
        break

cv2.destroyAllWindows()

 

cv2.addWeighted(src1, alpha, src2, beta, gamma [, dst [, dtype]])

 

src = Img1

alpha = Img1's weight

 

src2 = Img2

beta = Img2's weight

 

cv2.addWeighted를 이용하면 두 이미지를 합칠 수 있다.

 

[ Result ]

Merged

 

2. Canny Edge Detector

 

나는 Edge Detecting을 할 때 주로 Canny Edge Detector를 주로 사용했다

 

개인적인 생각이지만 Canny Edge Detector가 시중에 자료도 많이 있고

정확도도 높아 유명세를 얻지 않나 싶다.

 

이제 Canny Edge Detector에 대해서 자세히 알아보자

 


What Is Canny Edge Detector?

 

1986년 John.F.Canny에 의해 개발되었으며

Edge Detector시 다음 3가지를 만족시키는 것으로 목표를 한다.

 

1. Lower Error Percentage : 실제 Edge가 검출되어야 하며 Noise로 인해서 False Edge가 검출되면 안 됨

2. Accurate Edge Position : Canny Edge와 Input Image의 Edge Distance가 Minimalize 돼야 함

3. Minimize Response : Input Image상의 Edge에서 하나의 Edge만 Detection 되어야 함


 

이러한 조건을 목표로 개발된 Canny Edge Detector를

코드로 작성해보자

 

import cv2
import numpy as np
import imutils

img = cv2.imread("./apple.png")
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

img_gray = cv2.blur(img_gray, (3, 3))

img_canny = cv2.Canny(img_gray, 50, 150)

img_gray = imutils.resize(img_gray, width=500)
img_canny = imutils.resize(img_canny, width=500)

while True:
    cv2.imshow("GrayScale", img_gray)
    cv2.imshow("Canny", img_canny)
    key = cv2.waitKey(1)

    if key == 27:
        break

cv2.destroyAllWindows()

중요한 부분을 살펴보자

 

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

img_gray = cv2.blur(img_gray, (3, 3))

우선은 Canny_Edge 검출을 위해서

Input_Image를 GrayScale로 변환해줘야 한다.

 

그리고 Average_Blurring 기법으로 GrayScale Image의

Noise를 조금이나마 줄여준다.

 

img_canny = cv2.Canny(img_gray, 50, 150)

 

cv2.Canny( image, threshold1, threshold2, edges=None, apertureSize=None, L2 gradient=None )

 

image = GrayScale_Img

 

Threshold1 = Minimum Threshold

 

Threshold2 = Maximum Threshold

 

edges = Canny_Edge Image를 저장할 변수 (None이어도 상관 X)

 

apertureSize = 이미지 그레디언트를 구할 때 사용하는 소벨 커널 크기. 디폴트는 3이다.

 

L2 gradient = 만약 True라면 그레디언트 크기를 계산할 때 sqrt{(dI/dx)^2 + (dI/dy)^2}를 사용합니다.

False라면 근삿값인 |dI/dx|+|dI/dy|를 사용합니다.

 

[ Result ]

Original Image
Canny_Edge

 

 

2021/01/16 - [openCV] - [openCV] Graphic User Interface

 

[openCV] Graphic User Interface

제목에 쫄지 말자 그저 GUI의 Full Name일뿐😬 우선 오늘은 제목에 나와 있듯이 openCV에서 지원하는 GUI를 다뤄보면서 공부해보자 0. What Is Canny Edge? 코드를 보기 전에 Canny Edge가 뭔지 알아보자🤔 Cann

confidence-10211.tistory.com

윗글에서 Canny_Edge를 조금 더 세부적으로 정리를 해두었다

졸리다

오늘도 끄-읕🤗

'openCV' 카테고리의 다른 글

[openCV] Hough Transform  (0) 2021.03.28
[openCV] Morphology  (0) 2021.03.12
[openCV] Convolution & Mask (1)  (0) 2021.03.06
[openCV] Image Geometric Transformation (2)  (0) 2021.02.21
[openCV] Image Geometric Transformation (1)  (0) 2021.02.20