개발아 담하자

[iOS] MLKit 를 사용한 사진 속 텍스트 인식하기 본문

📱 iOS

[iOS] MLKit 를 사용한 사진 속 텍스트 인식하기

choidam 2021. 11. 5. 10:27

최근 티켓 사진 속 텍스트를 인식해야하는 사이드 프로젝트를 시작했습니다.

텍스트 인식 방법으로 구글에서 제공하는 MLKit를 사용하기로 했습니다.

 

인식해야 하는 뮤지컬 티켓의 사진 입니다.

사진 출처 : https://www.google.com/url?sa=i&url=https%3A%2F%2Fwww.daangn.com%2Farticles%2F3914115&psig=AOvVaw14Kj5KVvP8UQQxVC17IN4l&ust=1635902727281000&source=images&cd=vfe&ved=0CAsQjRxqFwoTCPDEq9vC-PMCFQAAAAAdAAAAABAD

 

공식 문서를 참고해 작성했습니다.

https://developers.google.com/ml-kit/vision/text-recognition

 

Text Recognition  |  ML Kit  |  Google Developers

Text Recognition The ML Kit Text Recognition API can recognize text in any Latin-based character set. It can also be used to automate data-entry tasks such as processing credit cards, receipts, and business cards. iOS Android Key capabilities Recognize tex

developers.google.com

 

라이브러리 설치

영어가 아닌 한글을 인식해야 하므로 한글 인식이 지원되는 베타 버전을 사용했습니다.

(베타 버전은 한글 외에도 라틴어, 중국어, 일본어 등을 지원합니다.)

pod 'GoogleMLKit/TextRecognitionKorean', '2.3.0'

Podfile 에 입력한 후 install 합니다.

 

 

TextRecognizer 생성

import MLKitTextRecognitionKorean
let koreanOptions = KoreanTextRecognizerOptions()
let koreanTextRecognizer = TextRecognizer.textRecognizer(options: koreanOptions)

 

이미지 준비

먼저 텍스트 인식을 원하는 이미지를 미리 에셋 파일에 넣어둡니다. 

import MLKitVision
let image = VisionImage(image: UIImage(named: "ticket")!)
image.orientation = imageOrientation(deviceOrientation: UIDevice.current.orientation, cameraPosition: .back) // 아직 작성 안 했음!

 

VisionImage 에 에셋에 넣어 둔 UIImage 파일을 넣습니다. (공식 문서를 살펴보니 UIImage 말고 CMSampleBuffer 를 사용해도 된다고 하니 참고해주세용)

이제 VisionImage 의 oreintation 을 설정할 imgaeOrientation 함수를 작성해야 합니다.

 

import AVFoundation
func imageOrientation(
  deviceOrientation: UIDeviceOrientation,
  cameraPosition: AVCaptureDevice.Position
) -> UIImage.Orientation {
  switch deviceOrientation {
  case .portrait:
    return cameraPosition == .front ? .leftMirrored : .right
  case .landscapeLeft:
    return cameraPosition == .front ? .downMirrored : .up
  case .portraitUpsideDown:
    return cameraPosition == .front ? .rightMirrored : .left
  case .landscapeRight:
    return cameraPosition == .front ? .upMirrored : .down
  case .faceDown, .faceUp, .unknown:
    return .up
  }
}

 

imageOrientation 은 UIDeviceOreintation 과 AVCaptureDevice.Position 을 매개변수로 받고 있습니다. 

 

koreanTextRecognizer.process(image) { result, error in
	guard error == nil, let result = result else {
		// Error handling
		print("error")
		return
	}
	let resultText = result.text
	print("resultText: \(resultText)")
}

이제 이미지를 처리합니다!

 

INFO: Initialized TensorFlow Lite runtime.
resultText: <핑크퐁과 상어가족의 겨을나라> 초대현장교환권
롯데마트
R석 (1인1매)
소: KT&G 상상마당 대치아트홀
장
관람일자: 2017-12-28[목] 14:00
관람연령: 20개월 이상 관람가능
롯데마트
R석 (1인1 매D
어린이 뮤지컬 <핑크퐁과
상어가족의 겨울나라>
본 교환권은 공연당일 매표소 교환권 창구에서 좌석권으로 교환가능합니다.
공연 당일 공연시간 1시간전에서 30분전까지 교환권을 제출하셔야만 교환가능 합니다.
본 교환권 현장교환시 좌석 지정이 불가하며, 차액지불을 통한 좌석등급 변경이 불가 합니다.
2017-12-28[목] 14:00
T&G 상상마당 대치아트홀
교환권 분실이나 미소지시 교환이 불가능(관람불가)하며 재 발행되자 않습니다.
*문의전화: 클립서비스 1577-3363 *판매/때매 불가

 

코드를 실행시키면 위와 같은 내용이 출력됩니다. 아주 완벽한 인식은 아니지만 생각보다 정확도가 높습니다.

 

 

텍스트 추출하기

 

TextRecognizer 는 Block, Line, Element 단위로 추출이 가능합니다. (사진 참조)

잘 사용한다면 특정 텍스트를 추출하기에 용이할 것 같습니다.

 

for block in result.blocks {
	let blockText = block.text
		print("block: \(blockText)")
                
		for line in block.lines {
			let lineText = line.text
			print("line: \(lineText)")
                    
				for element in line.elements {
					let elementText = element.text
					print("element: \(elementText)")
        		}
	   	}
}

 

result 블락에 위와 같이 block, line, elemet 단위로 추출하고 출력해봤습니다.

 

block: <핑크퐁과 상어가족의 겨을나라> 초대현장교환권
line: <핑크퐁과 상어가족의 겨을나라> 초대현장교환권
element: <핑크퐁과
element: 상어가족의
element: 겨을나라>
element: 초대현장교환권
block: 롯데마트
line: 롯데마트
element: 롯데마트
block: R석 (1인1매)
line: R석 (1인1매)
element: R석
element: (1인1매)
block: 소: KT&G 상상마당 대치아트홀
line: 소: KT&G 상상마당 대치아트홀
element: 소:
element: KT&G
element: 상상마당
element: 대치아트홀
block: 장
line: 장
element: 장
block: 관람일자: 2017-12-28[목] 14:00
line: 관람일자: 2017-12-28[목] 14:00
element: 관람일자:
element: 2017-12-28[목]
element: 14:00
block: 관람연령: 20개월 이상 관람가능
line: 관람연령: 20개월 이상 관람가능
element: 관람연령:
element: 20개월
element: 이상
element: 관람가능
block: 롯데마트
line: 롯데마트
element: 롯데마트
block: R석 (1인1 매D
line: R석 (1인1 매D
element: R석
element: (1인1
element: 매D
block: 어린이 뮤지컬 <핑크퐁과
상어가족의 겨울나라>
line: 어린이 뮤지컬 <핑크퐁과
element: 어린이
element: 뮤지컬
element: <핑크퐁과
line: 상어가족의 겨울나라>
element: 상어가족의
element: 겨울나라>
block: 본 교환권은 공연당일 매표소 교환권 창구에서 좌석권으로 교환가능합니다.
line: 본 교환권은 공연당일 매표소 교환권 창구에서 좌석권으로 교환가능합니다.
element: 본
element: 교환권은
element: 공연당일
element: 매표소
element: 교환권
element: 창구에서
element: 좌석권으로
element: 교환가능합니다.
block: 공연 당일 공연시간 1시간전에서 30분전까지 교환권을 제출하셔야만 교환가능 합니다.
line: 공연 당일 공연시간 1시간전에서 30분전까지 교환권을 제출하셔야만 교환가능 합니다.
element: 공연
element: 당일
element: 공연시간
element: 1시간전에서
element: 30분전까지
element: 교환권을
element: 제출하셔야만
element: 교환가능
element: 합니다.
block: 본 교환권 현장교환시 좌석 지정이 불가하며, 차액지불을 통한 좌석등급 변경이 불가 합니다.
line: 본 교환권 현장교환시 좌석 지정이 불가하며, 차액지불을 통한 좌석등급 변경이 불가 합니다.
element: 본
element: 교환권
element: 현장교환시
element: 좌석
element: 지정이
element: 불가하며,
element: 차액지불을
element: 통한
element: 좌석등급
element: 변경이
element: 불가
element: 합니다.
block: 2017-12-28[목] 14:00
T&G 상상마당 대치아트홀
line: 2017-12-28[목] 14:00
element: 2017-12-28[목]
element: 14:00
line: T&G 상상마당 대치아트홀
element: T&G
element: 상상마당
element: 대치아트홀
block: 교환권 분실이나 미소지시 교환이 불가능(관람불가)하며 재 발행되자 않습니다.
line: 교환권 분실이나 미소지시 교환이 불가능(관람불가)하며 재 발행되자 않습니다.
element: 교환권
element: 분실이나
element: 미소지시
element: 교환이
element: 불가능(관람불가)하며
element: 재
element: 발행되자
element: 않습니다.
block: *문의전화: 클립서비스 1577-3363 *판매/때매 불가
line: *문의전화: 클립서비스 1577-3363 *판매/때매 불가
element: *문의전화:
element: 클립서비스
element: 1577-3363
element: *판매/때매
element: 불가

 

완벽하지는..않지만..!!! 만족스럽습니당