
이번 내용은 바운딩 박스와 글자 윤곽선(Contour) 따는 내용입니다.

거두절미 하고 바로 본론으로 들어가겠습니다.
만약에, 주차장 내 차량 번호를 인식해야 한다고 해서
CCTV에 찍힌 이미지를 갖고 보면,
번호판이 기울어져 보이는 경우가 많습니다.
이와 같이,
OCR을 할 때, 물체 내 글씨의 기울어짐 정도가 워낙 다채롭기 때문에
보통은 Bounding box를 활용하여 이 기울기를 맞춰주고는 합니다.
서비스를 상용화 해서 계속 영수증 데이터를 받다 보면,
분명 꾸깃한 영수증 사진도 섞여서 글자도 중구난방 일텐데,
일단 이런 경우는 배제 하고,
영수증 주위 배경 삭제에 이 바운딩 박스를 활용했습니다.
mean_bin = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 51, 15)
mean_bin_inv = 255 - mean_bin
먼저 바운딩 박스 검출을 편하게 하려면 흑백 변환이 필요합니다.
영수증 사진을 떠올려 보면, 배경이 흰색(255값), 글자는 검은색(0값)으로 구성되어 있습니다.
윤곽선을 검출할 때, 흰색값(255값)을 찾아서 하게 되는데,
이 때문에 흑백 변환을 거쳐줘야 합니다.
혹시 모르니 노이즈 제거 효과와 findContours 함수에서 요구하는 대로
적응형 이진화를 거쳤고,
흑백 변환을 위해 255값에서 빼주는 방식으로 적용했습니다.
contours, _ = cv2.findContours(mean_bin_inv, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
largest_contour = max(contours, key=cv2.contourArea)
x, y, w, h = cv2.boundingRect(largest_contour)
filtered_image = np.zeros_like(image)
filtered_image[y:y+h, x:x+w] = image[y:y+h, x:x+w]
이제 윤곽선 코드 입니다.
OpenCV 라이브러리에 findContours 함수가 존재합니다.
이걸로 윤곽선을 찾을 수 있으며,
배경과 물체의 경계를 찾으려면 결국 가장 큰 윤곽선을 찾아야 하는데
이는 max 함수를 통해 구할 수 있습니다.
이제 0값(검은색)으로 채워주고,
윤곽선 찾은 부분을 덮어쓰기 느낌으로 가주면,

이렇게,
손쉽게 제거된 것을 확인할 수 있습니다.
이제 글자 윤곽선을 따도록 하겠습니다.
text_contours, _ = cv2.findContours(filtered_bin_inv, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contour_image = np.zeros_like(filtered_image)
cv2.drawContours(contour_image, text_contours, -1, (255, 255, 255), 1)
OpenCV 라이브러리의 findContours를 쓰는 것은 동일합니다.
전체적으로는 위와 동일한데, drawContours 함수를 써서 출력하는 것만 추가되었습니다.

출력 이미지는 이와 같은데,
이미지만 봤을 때는, Edge detection과 큰 차이가 없어 보입니다.
Edge detection은 이미지에서 픽셀값 변화 심한 것을 찾는 것이라면,
윤곽선 검출은 연결된 흰색(255값) 영역의 외곽선을 찾는 것 입니다.
이와 같이, 차이가 분명 존재합니다.
노이즈가 더 많이 껴있는 것을 보면, 흐릿한 이미지에서는
윤곽선 찾는게 좀 더 도움이 될 것 같습니다.
다음 포스팅에서는 여태까지 적용했던거
OCR 결과로 비교해보도록 하겠습니다.
감사합니당 ~ 🦾