파이썬 강의/openCV

파이썬 openCV 12. 엠보싱 기법(embossing)

마리사라 2020. 11. 25. 14:39
반응형

파이썬 openCV 12번째 강의는 엠보싱 기법(embossing)입니다. 이번 강의도 중첩 for문을 사용하는 방식과, 내장 함수를 사용해서 시간을 단축시키는 방법이 있습니다. 이번 강의부터는 최대한 중첩 for문을 지양하고, 내장 함수를 사용하는 방식으로 강의하도록 하겠습니다.


0. 엠보싱?

위키백과상의 엠보싱은

"엠보싱 (embossing) 은 직물, 종이, 금속 등의 표면에 돋을새김으로 무늬를 찍어내는 가공 방법."

으로 설명하고 있습니다. 사전적 정의로 파고들기에는 말이 어려우므로 예시로 설명하겠습니다.

 

엠보싱은 이처럼 무언가에 입체감이 느껴지게 만드는 방식입니다. 엠보싱은 위 사진처럼 주변에 비해 튀어나오게 하는 방식과(엠보싱), 주변에 비해 들어가게 하는 방식(디보싱)이 있습니다.

 

엠보싱과 디보싱

대부분의 문양과 글자는 튀어나오게 만든 엠보싱이라 할 수 있고, 위쪽과 아래쪽의 글자를 기준으로 보면 디보싱이라 할 수 있습니다.

 

또 다른 예시로, 凹凸이라는 한자가 있습니다. 凹(오목할 요), 凸(볼록할 철)이라는 한자는 이름대로 오목하게 들어갔음과 볼록하게 튀어나왔음을 나타내는 한자입니다. 엠보싱도 이처럼 주변에 비해서 들어간 모양으로 만들거나 튀어나온 모양으로 만드는 기법을 말합니다.


1. openCV에서의 엠보싱

img = cv2.imread("lenna.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

항상 그렇듯 이미지를 불러와줍니다. 엠보싱은 도드라지게 보이기 위해 그레이 스케일(흑백)로 진행합니다.

 

이제부터 엠보싱 기법의 원리를 알려드리겠습니다.

엠보싱은 3 x 3의 행렬을 만들어서, 그 행렬에 맞게 화소를 바꾸는 방식으로 사용됩니다. 이때 사용되는 행렬을 mask라고 하며, mask는 꼭 3x3일 필요는 없습니다.

 

mask를 적용하는 방법은, 다음과 같습니다.

1. mask를 적용할 화소를 선택한다

2. mask의 크기와 같은 양의 1번화소 주변의 화소들의 정보를 저장한다.

예) 3x3 mask를 적용하는 경우

주변 화소 주변 화소 주변 화소
주변 화소 mask를 적용할 화소 주변 화소
주변 화소 주변 화소 주변 화소

이때 주변에 화소가 없는 부분은 0으로 간주합니다.

예 2) 3x3 mask를 적용하는 경우 + 선택한 화소가 (0, 0)의 화소일 경우

0 0 0
0 mask를 적용할 화소 주변 화소
0 주변 화소 주변 화소

 

3. mask의 각 좌표에 있는 값을 2번에서 구한 정보에 적용한다

예) mask = ([1, 1, 1], [-1, -1, -1], [0, 0, 0])

주변 화소 * 1 주변 화소 * 1 주변 화소 * 1
주변 화소 * -1 mask를 적용할 화소 * -1 주변 화소 * -1
주변 화소 * 0 주변 화소 * 0 주변 화소 * 0

4. 3에서 나온 모든 값을 더해서 mask를 적용할 화소 값에 저장한다.

의 4개의 단계로 이루어 집니다.

 

mask1 = np.array([[-1, 0, 0], [0, 0, 0], [0, 0, 1]])
mask2 = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]])

엠보싱 기법을 적용할 mask를 생성해 줍니다. mask1은 음각, mask2는 양각입니다.

 

out1 = cv2.filter2D(gray, -1, mask1)
out2 = cv2.filter2D(gray, -1, mask2)

이제 위에서 나온 mask적용 방법이 들어있는 함수인 filter2D를 통해 gray에 적용해 줍니다. filter2D의 값으로는 (원본, 깊이, 적용할 마스크)가 되며, 깊이 값은 음수로 주게 되면 원래 이미지의 깊이와 같게 됩니다.

 

이제 이미지를 확인해 보겠습니다.

원본 이미지
mask1 적용 이미지
mask2 적용 이미지

이렇게 결과가 나오게 됩니다.


2. 마치며

엠보싱 기법은 나중에 배우게 될 가장자리 검출과 비슷하게 결과가 나오게 됩니다. 하지만 엠보싱과 가장자리 검출은 매우 다른 방식이니 엠보싱 기법도 알아두시는 게 좋을 것 같습니다.

 

import cv2
import numpy as np


img = cv2.imread("lenna.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

mask1 = np.array([[-1, 0, 0], [0, 0, 0], [0, 0, 1]])
mask2 = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]])

out1 = cv2.filter2D(gray, -1, mask1)
out2 = cv2.filter2D(gray, -1, mask2)

cv2.imshow("original", gray)
cv2.imshow('mask1', out1)
cv2.imshow('mask2', out2)

cv2.waitKey(0)
반응형