일반적인 명함사진의 조건
- 명함은 흰색이고, 배경은 충분히 어둡다.
- 명함은 각진 사각형 모양이고, 가로, 세로비율 9:5 이다.
- 명함은 충분히 크게 촬영되었다.
- 수행과정: 이진화 > 외곽선 검출 & 다각형 근사화 > 투명 변환 > OCR
1) 그레이 스케일화
컬러영상을 그레이 스케일 영상으로 변환하여 사용
- 컬러 정보가 크게 중요하지 않은경우, 그레이 스케일 영상으로 변환하여 처리하는 것이 메모리 사용량, 연산시간 측면에서 유리함
- OpenCV의
cv2.imread()
함수에서 그레이 스케일형식으로 영상을 불러오거나 또는 cv2.cvtColor()
함수를 사용하여 그레이 스케일 형식으로 변경가능
2) 이진화
영상의 이진화(binarization)
- 영상의 픽셀값을 0 또는1(255)로 만드는 연산
- 배경(background) vs. 객체(object)
- 관심영역 vs. 비관심영역
그레이 스케일의 이진화
자동 임계 값 결정 방법: 오츠(Otsu)방법
- 입력 영상이 배경(background)과 객체(object) 두 개로 구성되어 있다고 가정
- 두 픽셀 분포의 분산의 합이 최소가 되는 임계 값을 선택
- 효과적인 수식 전개와 재귀식을 이용하여 빠르게 임계 값을 결정
OpenCV 이진화(임계값)함수
cv2.threshold(src, thresh, maxval, type, dst=None) -> retval,dst
- src: 입력영상(다채널, 8비트또는32비트실수형)
- thresh: 임계값
- maxval: 결과 이진 영상에서 최대 픽셀값(보통255를지정)
- type: 임계값에 의한 변환함수 지정 또는 자동 임계값 설정방법
- cv2.THRESH_BINARY: 이진화
- cv2.THRESH_BINARY_INV: 이진화 후 반전
- cv2.THRESH_BINARY | cv2.THRESH_OTSU: 자동 이진화
- retval:사용된 임계값
- dst: (출력) 입계값 영상(src와동일크기, 동일타입)
3) 객체 단위 분석
- 레이블링
- 영역기반 모양 분석
- 레이블맵, 바운딩박스,픽셀개수, 무게 중심좌표를 반환
- 외곽선 검출
- 외곽선 기반 모양 분석
- 외곽선 점들의 좌표와 계층구조를 반환
- 다양한 외곽선 처리함수에서 활용가능(면적계산, 근사화등)
객체의외곽선검출
- 외곽선 검출이란?
- 객체의 외곽선 좌표를 모두 추출하는 작업. Boundary tracking. Contour tracing.
- 바깥쪽& 안쪽(홀) 외곽선 → 외곽선의 계층구조도 표현가능
- 외곽선 객체 하나의 표현방법
- numpy.ndarray
- shape=(K, 1, 2) (K는외곽선좌표개수)
- dtype=numpy.int32
- 여러 객체의 전체 외곽선 표현방법
- "객체 하나의 외곽선(numpy.ndarray)"을 원소로 갖는 리스트
- len(리스트)= 전체외곽선개수(N)
외곽선 검출
cv2.findContours(image, mode, method, contours=None, hierarchy=None,
offset=None) -> contours, hierarchy
- image: 입력영상. non-zero 픽셀을객체로간주함.
- mode: 외곽선 검출모드. cv2.RETR_ 로 시작하는상수.
- cv2.RETR_EXTERNAL: 바깥쪽외곽선만검출
- cv2.RETR_LIST: 모든외곽선검출
- cv2.RETR_CCOMP: 2-레벨계층구조로검출
- cv2.RETR_TREE: 전체계층구조로검출
- method: 외곽선 근사화 방법. 근사화가 필요하지 않으면 cv2.CHAIN_APPROX_NONE 지정.
- contours: 검출된 외곽선 좌표. numpy.ndarray로 구성된 리스트.len(contours)=전체외곽선개수(N).
contours[i].shape=(K, 1, 2).
contours[i].dtype=numpy.int32.
- hierarchy: 외곽선 계층 정보. 자세한내용은 OpenCV 도움말참고.
- offset: 좌표값 이동옵셋. 기본값은(0, 0).
외곽선 그리기
cv2.drawContours(image, contours, contourIdx, color, thickness=None,
lineType=None, hierarchy=None, maxLevel=None, offset=None)
-> image
- image:입출력 영상
- contours:(cv2.findContours() 함수로구한) 외곽선 좌표정보
- contourIdx:외곽선인덱스. 음수(-1)를 지정하면 모든 외곽선을 그림.
- color:외곽선 색상
- thickness: 외곽선 두께. thinkness< 0이면 내부를 채운다.
- lineType: LINE_4, LINE_8, LINE_AA 중 하나 지정
- hierarchy: 외곽선 계층 정보.
- maxLevel: 그리기를 수행 할 최대 외곽선 레벨
주요 외곽선 관련 함수
cv2.arcLength(curve, closed) -> retval
- curve:외곽선 좌표. numpy.ndarray. shape=(K, 1, 2).
- closed: True이면 폐곡선으로 간주
- retval: 외곽선 길이
cv2.contourArea(contour, oriented=None) -> retval
- contour: 외곽선 좌표. numpy.ndarray. shape=(K, 1, 2).
- oriented: True이면 외곽선 진행 방향에 따라 부호 있는 면적을 반환. 기본값은 False.
- retval: 외곽선으로 구성된 면적
cv2.boundingRect()
: 주어진 점을 감싸는 최소 크기 사각형(바운딩박스) 반환
cv2.minEnclosingCircle()
: 주어진 점을 감싸는 최소 크기 원을 반환
cv2.minAreaRect()
: 주어진 점을 감싸는 최소 크기 회전된 사각형을 반환
cv2.minEnclosingTriangle()
: 주어진 점을 감싸는 최소 크기 삼각형을 반환
cv2.approxPolyDP(curve, epsilon, closed, approxCurve=None) -> approxCurve
- curve: 입력 곡선 좌표. numpy.ndarray. shape=(K, 1, 2).
- epsilon: 근사화 정밀도 조절. 입력곡선과 근사화 곡선 간의 최대거리.
e.g)(외곽선전체길이)* 0.02
- closed: True를 전달하면 폐곡선으로 간주
- approxCurve: 근사화된 곡선 좌표. numpy.ndarray. shape=(k, 1, 2).
영상의 기하학적 변환
- 영상의 기하학적 변환(geometric transformation)이란?
- 영상을 구성하는 픽셀의 배치 구조를 변경함으로써 전체영상의 모양을 바꾸는 작업
- 영상의 크기변환, 대칭변환, 회전변환 등
투시 변환 행렬 구하기
cv2.getPerspectiveTransform(src, dst, solveMethod=None) -> retval
- src: 4개의 원본 좌표점. numpy.ndarray. shape=(4, 2).
e.g) np.array([[x1, y1], [x2, y2], [x3, y3], [x4, y4]], np.float32)
- dst: 4개의 결과 좌표점. numpy.ndarray. shape=(4, 2).
- 반환값: 3x3 크기의 투시 변환 행렬
영상의투시변환
cv2.warpPerspective(src, M, dsize, dst=None, flags=None,
borderMode=None, borderValue=None) -> dst
- src: 입력 영상
- M: 3x3 변환행렬. numpy.ndarray.
- dsize: 결과영상의크기. (0, 0)을 지정하면 src와 같은크기.
- dst: 출력영상
- flags: 보간법. 기본값은cv2.INTER_LINEAR
- borderMode: 가장자리 픽셀 확장방식.
- borderValue: cv2.BORDER_CONSTANT일 때 사용할 상수값.기본값은 0.
Reference
1) 제로베이스 데이터스쿨 강의자료