edge = cv2.Canny(src, 50, 150)
입력 영상으로 사용한 영수증의 외곽선은 크기가 가장 큰 4개의 외곽선으로 이루어져 있다는 점을 이용해 외곽선을 크기순으로 정렬
contours = cv2.findContours(edge.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[0]
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:5] # 외곽선 크기순으로 정렬
for i in contours:
length = cv2.arcLength(i, True)
approx = cv2.approxPolyDP(i, 0.02 * length, True)
if len(approx) == 4:
contourCnt = approx
break
# 투시변환
src_pts = np.array([[approx[0][0][0], approx[0][0][1]],
[approx[1][0][0], approx[1][0][1]],
[approx[2][0][0], approx[2][0][1]],
[approx[3][0][0], approx[3][0][1]]]).astype(np.float32)
w = 300
h = 400
dst_pts = np.array([[0, 0],
[0, h - 1],
[w - 1, h - 1],
[w - 1, 0]]).astype(np.float32)
pers_mat = cv2.getPerspectiveTransform(src_pts, dst_pts)
src_transform = cv2.warpPerspective(src, pers_mat, (w, h))
_, src_binary = cv2.threshold(src_transform, 0, 255, cv2.THRESH_OTSU)
에지 정보를 유지하며 잡음을 효과적으로 제거하기 위해 양방향 필터 수행
src_filtering = cv2.bilateralFilter(src_binary, -1, 10, 5)
kernel = np.ones((3, 1), np.uint8)
src_morphology = cv2.morphologyEx(src_filtering, cv2.MORPH_OPEN, kernel)