openCv page Dewarp 분석 -3

지난 포스트에서는 마스킹 이미지 생성을 알아보았습니다.

이번 포스트에서는 윤곽선 정보 검출에 대해서 알아보겠습니다.

윤곽선 검출

1
2
# 윤곽선 정보 검출
cinfo_list = get_contours(name, small, pagemask, 'text')

get_contours() 함수를 통해 윤곽선 정보를 취득합니다. 파라미터로는

  • name : 파일 이름
  • small : 이미지
  • pagemask : 마스킹을 위한 이미지(2번째 포스트에서 생성한)
  • ‘text’ : text 이미지를 검출하기 위한 설정. text가 아니라면 함수내에서 line으로 다시 검색합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
def get_contours(name, small, pagemask, masktype):

mask = get_mask(name, small, pagemask, masktype)

if DEBUG_LEVEL >= 3:
debug_show(name, 0.7, 'get_mask', mask)

contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

contours_out = []

for contour in contours:

rect = cv2.boundingRect(contour)
xmin, ymin, width, height = rect

if (width < TEXT_MIN_WIDTH or
height < TEXT_MIN_HEIGHT or
width < TEXT_MIN_ASPECT*height):
continue

tight_mask = make_tight_mask(contour, xmin, ymin, width, height)

if tight_mask.sum(axis=0).max() > TEXT_MAX_THICKNESS:
continue

contours_out.append(ContourInfo(contour, rect, tight_mask))

if DEBUG_LEVEL >= 2:
visualize_contours(name, small, contours_out)

return contours_out

get mask

mask = get_mask(name, small, pagemask, masktype)를 통해서 mask를 취득합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
def get_mask(name, small, pagemask, masktype):

sgray = cv2.cvtColor(small, cv2.COLOR_RGB2GRAY)

if masktype == 'text':

mask = cv2.adaptiveThreshold(sgray, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY_INV,
ADAPTIVE_WINSZ,
25)

if DEBUG_LEVEL >= 3:
debug_show(name, 0.1, 'thresholded', mask)

mask = cv2.dilate(mask, box(9, 1))

if DEBUG_LEVEL >= 3:
debug_show(name, 0.2, 'dilated', mask)

mask = cv2.erode(mask, box(1, 3))

if DEBUG_LEVEL >= 3:
debug_show(name, 0.3, 'eroded', mask)

else:

mask = cv2.adaptiveThreshold(sgray, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY_INV,
ADAPTIVE_WINSZ,
7)

if DEBUG_LEVEL >= 3:
debug_show(name, 0.4, 'thresholded', mask)

mask = cv2.erode(mask, box(3, 1), iterations=3)

if DEBUG_LEVEL >= 3:
debug_show(name, 0.5, 'eroded', mask)

mask = cv2.dilate(mask, box(8, 2))

if DEBUG_LEVEL >= 3:
debug_show(name, 0.6, 'dilated', mask)

return np.minimum(mask, pagemask)

이미지 색상 변환

첫번째로 이미지 전처리 과정으로 이미지를 흑백으로 변환합니다.

sgray = cv2.cvtColor(small, cv2.COLOR_RGB2GRAY)를 통해 흑백 이미지를 취득합니다.

cvtColor(src, code, dst=None, dstCn=None)는 이미지 색상을 변환하기 위한 함수입니다.

여기서는 cv2.COLOR_RGB2GRAY를 통해서 RGB를 GRAY로 변경하였습니다.

이미지 색상 변환

이미지 이진화

mask = cv2.adaptiveThreshold(sgray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, ADAPTIVE_WINSZ, 25)을 통해 이진화를 진행합니다.

기본형은 adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)입니다.

적응형 이진화 알고리즘 함수로서 입력 이미지에 따라 임곗값이 스스로 다른값을 할당할 수 있도록 구성된 이미지 알고리즘 이미지에 따라 어떠한 임곗값을 주더라도 이진화 처리가 어려운 이미지가 존재합니다. 예를 들어 조명의 변화나 반사가 심한 경우 이미지내 밝기 분포가 달라 국소적으로 임곗값을 적용해야 원하는 결과를 얻을 수 있습니다.

  • 임곗값(thresh) : 임곗값 보다 낮은 픽셀값은 0(검정), 높은 픽셀값은 최댓값(maxval 여기선 255 흰색)으로 변경(cv2.THRESH_BINARY의 경우)
  • cv2.ADAPTIVE_THRESH_MEAN_C : blockSize 영역의 모든 픽셀에 평균 가중치를 적용
  • cv2.THRESH_BINARY_INV : 반전 이진화 코드. 임곗값을 초과할 경우 0, 아닐경우 maxval(255)로 변경.
  • ADAPTIVE_WINSZ : block size 여기서는 55 -> 55x55 크기 내의 영역을 분석해 적절한 임곗값을 설정
  • 상수값 25 : 상수값이 크면(양수) 밝아지고 작으면(음수) 어두워짐

이미지 이진화

이미지 팽창

1
mask = cv2.dilate(mask, box(9, 1))

cv2.dilate는 이미지를 팽창시키는 함수입니다.

기본형은 dilate(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)입니다.

kernel에 설정된 값에 따라 팽창을 진행합니다. 여기서는 box(9,1)로 설정하였으므로 x축은 9, y축은 1만큼팽창합니다. x축을 팽창시켜서 가로줄을 만드는 것을 목적으로 합니다.

이미지 팽창

이미지 축소

1
mask = cv2.erode(mask, box(1, 3))

cv2.erode는 이미지를 침식시키는 함수입니다.

기본형은 rode(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)입니다.

이미지 팽창과 마찬가지로 kernel에 설정된 값을 통해 침식을 진행합니다. 여기서는 box(1,3)을 설정했기 때문에 y축을 축소시켜 블립을 제거할 목적으로 사용하고 있습니다.

이미지 침식

외곽 이미지 제거

1
return np.minimum(mask, pagemask)

np.minimum은 요소별 최소값을 돌려주는 함수입니다.

앞에서 말한것 처럼 pagemask는 마진만큼(x축 50, y축 20) 검정 테두리(0,0,0)이 둘러있다. 안에는 흰색 사각형(255,255,255)가 있다.

기존 그림(mask)와 pagemask의 최소값을 비교해서 돌려준다면 pagemask의 외곽선 검정 부분이 기존 부분에 덧칠해지는 효과를 볼 수 있다.

이미지 외곽 제거

공유하기