[Droid Knights 2018]
유명한 신용카드 인식 오픈소스인 card.io는 양각된 숫자만 인식하고 인쇄된 숫자를 인식하지 못하는 한계가 있습니다. Google Mobile Vision과 OpenCV를 활용하여 범용으로 카드 번호와 바코드를 인식하는 라이브러리를 개발한 경험을 나누고자 합니다.
Google Mobile Vision과 OpenCV로 card.io를 확장한 범용 카드번호인식 개발
1.
2. 이 일을 한 사람은...
2
장혁재
LINE Plus, Client-side 신기능 R&D
https://scholar.google.com/citations?user=2kUrahwAAAAJ&hl=en
https://www.linkedin.com/in/hyukjae-jang
김종민
LINE Plus, Square Android 개발
2017 하계 인턴, 7주만에 핵심부분 완성!
https://github.com/devetude
3. 할 이야기는...
• 왜 해야 하는 가?
• 뭘 만들건가?
• 어떻게 만들었나?
• card.io 는 어떻게 동작하나?
• Google Mobile Vision으로 해결되나?
• OpenCV로 어떻게 안될까?
3
10. 잘 모르겠고, Google님께서 다 해주실거야!
1. 카드내의 모든 문자를 동시에 인식
2. 한글, 일본어, 한자를 영문 내지 숫자로 오인식 카드 번호만 추출하기 어려움
3. 숫자를 영문자로 오인식
11. 진정하고 문제를 쪼개 보자
11
외곽선 찾기 ISO표준
비율로 변환
수직 분할
수평 분할
숫자인식 전처리
8
카드 영역 추출
card.io 재활용
카드 번호
위치 찾기
번호 인식
Google Mobile Vision
12. 선조들의 삽질의 역사를 뒤져보자
OpenCV를 활용한 자동차 번호판 인식
• "복수개"의 문자열 인식
• 신용카드를 포함하여 멤버쉽 카드
같은 범용 카드 인식을 위해 필요
비슷한 크기의 문자가 일정 개수 이상 수평으로 나열
13. OpenCV를 활용한 복수개의 문자열 위치 검출법
OpenCV의
Canny, Contour, Poly 적용
사각 영역 크기로 필터링 수평으로 연속된 영역 그룹으로 묶기
원본 이미지
14. OpenCV를 활용한 복수개의 문자열 위치 검출법
• 숫자 위치 인식에서 숫자의 앞/뒤가 짤리는 오류
• 문자 인식에서 후보정하기 위해 수평으로만 crop
15. 이야! 다 해결했다!!
15
외곽선 찾기 ISO표준
비율로 변환
수직 분할
수평 분할
숫자인식 전처리
8
카드 영역 추출
card.io 재활용 카드 번호
위치 찾기
OpenCV
숫자 위치
검출번호 인식
Google Mobile Vision
16. 이야! 다 해결했다!!
16
외곽선 찾기 ISO표준
비율로 변환
수직 분할
수평 분할
숫자인식 전처리
8
카드 영역 추출
card.io 재활용 카드 번호
위치 찾기
OpenCV
숫자 위치
검출번호 인식
Google Mobile Vision
17. 하늘에서 버그가 빗발친다
• Google Mobile Vision 문제
• 문자인식에 쓰이는 Crop된 카드 이미지가 해상도가 낮아서 바코드 인식이 안됌
• Camera preview 이미지 입력 데이터 포맷을 맞춰줘야 함
• Camera preview에 찍혔지만 카드 외부에 있는 바코드가 인식되는 오류
• 문자인식시 입력 이미지의 최소 사이즈 제한있음
• 문자인식시 입력 이미지의 여백 부분을 투명 처리하면 인식 못함
• 문자인식시 입력 이미지의 외곽 부분은 인식하지 못함
• 문자인식시 뒤집어진 글자는 인식하지 못함
• card.io 내부의 숫자 인식과 충돌해서 카드 이미지가 뒤집혀서 처리됌
• 입력 이미지의 초점 문제
• card.io 자체 focus 값으로 filtering할 때 (OpenCV 의 sharpness 계산) 카드에 따라서 심각하게 점수가 낮은 카드가 존재
• card.io 자체 focus 값이 너무 낮으면 카드 테두리 인식조차 되지 않아서 이후 인식이 전부 안됨
• 입력 이미지가 선명하지 못하면 문자인식 성능이 심각하게 떨어짐
• card.io 자체 focus 값으로 실제 이미지가 선명한지 번진 상태인지 알아낼 수가 없음
• 신용카드 숫자 검증
• Luhn check 결과만 믿으면 안됨. (2개 이상의 숫자를 오인식시 false-positive 확률 증가)
• Issuer Identification Number (IIN)은 인식결과를 검증하는데 쓰기는 어려움
• 세상에 존재하는 모든 카드사의 카드들을 지원하는 것은 불가능
• Android camera spec 다양성
• 기기마다 지원하는 camera preview 사이즈가 완전히 제각각
• Camera preview의 가로 세로 비도 제각각이어서 동적으로 계산해서 UI를 재배치해야함
• Nexus, Pixel 계열의 screen rotation event 버그가 있어서 UI가 제 위치에 놓이지 못함
• iOS 지원 문제
• Google Mobile Vision이 iOS에서 문자인식을 지원하지 않음
17
19. 전체 구조도
Filtering &
Error Control
Texts
Barcodes
Camera
Preview
Pre-processing with
OpenCV for multiple
numeric region detection
Barcodes
recognition
Texts
recognition
Texts
post-
processing
Barcodes
post-
processing
Result UI
Existing embossed
number detection
20. 바코드 인식
20
카드 영역이 인식되어 편집된 이미지
270px
428px
바코드 인식을 하기엔 이미지 해상도가 너무 낮음 (preview: 640x480)
Camera
Preview
Pre-processing with
OpenCV for multiple
numeric region
detection
Barcodes
recognition
Texts
recognition
21. 1440px
1080px
바코드 인식
Camera
Preview
Pre-processing with
OpenCV for multiple
numeric region
detection
Barcodes
recognition
Texts
recognition
Camera preview data로 직접 인식 시도 (preview 해상도: 480p 최소 720p)
Side-effects
• 기기마다 천차만별인 preview 크기, 가로세로비율
• Camera preview format (e.g. NV21, NV16, YUV12)
• 카드 외부 영역의 바코드 인식
22. 문자 인식
• 너무 작은 이미지에서는 문자 인식 불가능 (35X428 pixels)
• 투명색은 이미지로 인식 안함
• 입력 이미지의 외곽 부분은 인식하지 못함 (최소 40 pixels)
• 숫자를 영문자로 오인식
• 뒤집어진 글자는 인식 불가능
• card.io 내부 처리와 충돌해서 카드 이미지가 멋대로 뒤집혀서
처리됌
Texts recognition
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
8 4 0 4 1 4 0 7 5 4 4 4
a b c d e f g h i j k l m n o p q r s t u v w x y z
6 2 1 4
? &
7 6
23. 이미지 선명도와 인식 정확도
• 카드에 따라 카드 테두리 조차도 인식 못함
• card.io내의 focus 값을 임의의 threshold로 검사
• focus값: OpenCV의 Laplacian, meanStdDev (Sharpness 계산)
• 선명도와 상관없이 심각하게 점수가 낮은 카드가 존재
• focus 값 무시. 매번 테두리 인식 (Nexus 5 기준 50ms 소요)
• adaptive threshold
• 카드 번호 위치를 찾으면 threshold 감소
• 너무 느린 인식 속도(대략 1초)와 낮은 정확도
• 초기 설계는 3회 인식결과를 활용해서 최종 결정
• 1회 인식 속도 Nexus 5 기준 대략 200 ~ 400 ms
• 문자인식 정확도는 선명도에 크게 영향 받음
• 흔들린 10장보다 선명한 1장
• card.io의 focus값은 보조자료로만 사용
• Camera hardware focus callback + 2초 timeout 사용
• Camera.AutoFocusCallback#onAutoFocus (deprecated from 21)
• CaptureResult.FOCUSED_LOCKED
24. 직관적인 결과수정 UI
• 신용카드와 달리 일반 카드는 Luhn check 불가능 사용자 최종 확인 필요
• DragShadow를 사용한 Drag & Drop 수정UI
Hidden buttons
Touch location
DragShadow
8 5 2 1 2 1 0 1 4 0 9 6 7 8 2
27. 그외의 잡다한 이야기...
• Google Mobile Vision 학습데이터
• AndroidManifest.xml에 등록하면 앱 설치시 자동으로 관련 학습 데이터 설치
• 학습 데이터는 NPE 발생없음. 인식결과만 영향.
• 사전에 학습데이터 설치상태 파악가능
• 학습 데이터 앱 외부에 설치
• card.io 코드 재활용
• jar 배포를 염두에 둔 오래된 코드
• resource 전무. byte string만든 vector 이미지. layout도 전부 programatic
• NDK build기반 (CMake아니고 Android.mk, Application.mk 사용)
• 판도라의 상자 "Refactoring" (희망이라쓰고 야근이라 읽는다)
• Java vs NDK간의 속도차이는 압도적!
• Java bitamp과 C++ OpenCV간의 image 변환 귀찮지만 어쩔수 없음
• Machine Learning? Deep learning? MNIST?
• 네, 시간이 없었습니다.
• 카드 이미지 수집도 어렵습니다. (QA도 안줘요)
28. 결론
• 양각카드와 더불어 프린트된 신용카드 인식
• 멤버쉽카드를 포함한 범용카드 인식
• 숫자만이 아니라 바코드, QR코드 인식
• 쉽고 직관적인 오류교정 UI 제공
• card.io재활용 및 Re-packaging (jar+*.so: 5039KB aar: 3027KB)
• 빠른 개발기간 (Jul. 2017~ Oct. 2017)
• 2017년 11월 Android 릴리즈
• 2018년 2월 iOS 릴리즈
28
29. 참고자료
• https://www.card.io/
• Google Mobile Vision
• https://developers.google.com/vision/
• SINFO Conf 2015 - Josh Snyder (PayPal)
• https://www.youtube.com/watch?v=T9TkkZg1L7s
• OSCON 2015, Practical mobile computer vision: How card.io works
• https://conferences.oreilly.com/oscon/open-source-
2015/public/schedule/detail/42675
• [C/C++] OpenCV 라이브러리로, 윤곽에 기반한 자동차 번호판 영역 추출
• http://mind3002.blogspot.kr/2016/01/cc-opencv-license-plates-
recognition.html
• 그림왕양치기 '약치기 그림
• https://www.facebook.com/yakchikii/
• 김보통 '내 멋대로 고민상담'
• https://www.lezhin.com/ko/comic/botong_clinic
• Shad Plays 'Justice Rains From Above'
• https://www.facebook.com/shadplays
• https://playoverwatch.com/en-us/
29