OpenCV에서 filter등의 함수에서 주로 등장하는 ddtype parameter는 결과 image의 data type을 의미한다.
desired data type이라고도 불리고 이를 줄여서 ddtype
라고 기재하는데, 일반적으로 input image와 같은 data type을 유지하도록 -1
을 사용하는 경우가 많다.
- 이 방식은 대부분 큰 문제가 없지만,
- gradient나 laplacian을 구하는 filter 연산의 경우, 음수값을 결과로 가질 수 있는데 OpenCV에서 image를 나타내기 위해 사용하는 기본 데이터 타입이
np.uint8
(orcv2.CV_8U
)이기 때문에 -1로 ddtype를 지정할 경우 문제가 발생한다. - 이는 음수를 고려하지 않은
cv2.CV_8U
는 음수값의 gradient등을 모두 0으로 처리해버리기 때문이다.
다음의 그림에서 왼쪽에서 2번째와 3번째 결과가 이를 잘 보여준다.
- Original에서 왼쪽의 negative value의 gradient 부분이 사라짐.
- 맨 왼쪽의 original image에 대한 gradient를 구하는 연산에서
ddtype
의 역할을 보여준다. - 맨 왼쪽에서 2번째 image는 forward difference 결과물로
ddtype
를-1
로 두어cv2.CV_8U
로 처리된 경우임. - 맨 왼쪽에서 3번째 image는 Soble filter를 x축으로 가한 결과물로
ddtype
를-1
로 두어cv2.CV_8U
로 처리된 경우임. - 맨 왼쪽에서 4번째 image는 Soble filter를 x축으로 가한 결과물로
ddtype
를cv2.CV_64F
로 바꾸어 처리한 경우임.
위의 결과는 forward difference 와 Sobel filter를 수행할 때, cv2.CV_8U
를 사용하면 안되는 이유를 잘 보여준다.
이에 대한 조각코드는 다음과 같으며, 맨 오른쪽 결과 이미지에 해당하는 코드 부분이 ddtype
를 어떻게 지정해야하는지를 보여주는 예이다.
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = np.full(shape=(512,512,3),fill_value=255,dtype=np.int32)
left_top = (100,100)
right_bottom = (400,400)
BGR_Black = (0,0,0)
cv2.rectangle(img,left_top,right_bottom,BGR_Black,-1)
cv2.imwrite('./data/rectangle.jpg',img) # It should return True
img = cv2.imread('./data/rectangle.jpg', cv2.IMREAD_GRAYSCALE)
assert img is not None, "file could not be read, check with os.path.exists()"
# Output dtype = cv2.CV_8U
gx_kernel = np.array([[-1,1]])
diffx8u = cv2.filter2D(img,-1,gx_kernel)
print(diffx8u.dtype)
# Output dtype = cv2.CV_8U
sobelx8u = cv2.Sobel(img,
#cv2.CV_8U,
-1,
1,0,
ksize=5)
print(sobelx8u.dtype)
# Output dtype = cv2.CV_64F. Then take its absolute and convert to cv.CV_8U
sobelx64f = cv2.Sobel(img,
#np.float64,
cv2.CV_64F,
1,0,
ksize=5)
print(sobelx64f.dtype)
abs_sobel64f = np.absolute(sobelx64f)
sobel_8u = np.uint8(abs_sobel64f)
plt.subplot(1,4,1),plt.imshow(img,cmap = 'gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(1,4,2),plt.imshow(diffx8u,cmap = 'gray')
plt.title('f-diff CV_8U'), plt.xticks([]), plt.yticks([])
plt.subplot(1,4,3),plt.imshow(sobelx8u,cmap = 'gray')
plt.title('Sobel CV_8U'), plt.xticks([]), plt.yticks([])
plt.subplot(1,4,4),plt.imshow(sobel_8u,cmap = 'gray')
plt.title('Sobel abs(CV_64F)'), plt.xticks([]), plt.yticks([])
plt.show()
OpenCV tutorial에서도 가급적 ddtype
를 negative를 포함하면서 보다 높은 정밀도의 data type로 사용하길 권하고 있다. 단 ddtype
가 가능한 combination이 있기 때문에 아무 타입으로 지정은 안된다.
다음 URL은 cv2.Laplacian
에서 ddtype
로 가능한 combination을 보여준다. input image의 dtype
에 따라 선택가능한 ddtype
가 기재되어 있다. 일반적으로는 cv2.CV_64F
나 cv2.CV_16S
등이 권해지는데, 개인적으로는 cv2.CV_64F
를 선호한다.
References
'Programming > DIP' 카테고리의 다른 글
[DIP] Basic Operations (on a binary image) for Morphological Operations (0) | 2023.05.11 |
---|---|
[OpenCV] imshow 창설정 및 종료 처리 (x버튼 처리) (0) | 2023.04.07 |
[DIP] opencv 에서 H264 encoding error (0) | 2023.02.15 |
[DIP] Kornia 소개 (0) | 2023.02.07 |
[DIP] Dithering (0) | 2023.01.17 |