1 애비 클라우드

  1. ABBYY Cloud OCR SDK에 접속하여 계정을 생성한다.
  2. 가입이 완료되면 Application ID와 비번을 등록한 전자우편을 통해 확인할 수 있다.

2 abbyyR 설치

abbyyR 웹사이트를 방문하면 abbyyR R 팩키지를 다운로드 받아 사용할 수 있다.

R 클라이언트 설정이 마무리되면 ABBYY Cloud OCR SDK를 사용하기 위해서 ABBYY 클라우드를 방문하여 APP_ID, APP_PW 를 발급받는다.

  1. ABBYY Cloud OCR SDK에서 발급받은 APP_ID, APP_PW를 usethis::edit_r_environ() 명령어를 통해 저장시킨다.
    • ABBYY_ID="d8464ac1-xxxxxxxxxxxxxxxxxx"
    • ABBYY_PW="DLuh1Zxxxxxxxxxxxxxxxxxxxxx"
  2. .Renviron 파일에 저장시킨 APP_ID, APP_PW를 Sys.getenv() 함수로 불러와서 setapp() 함수로 ABBYY CLOUD에 인증하도록 설정한다.
  3. getAppInfo() 함수를 사용해서 ABBYY CLOUD 관련 정보를 확인한다.
    • 특히 Allow getting application info 활성화를 잊지 않는다. 1.getAppInfo() 함수를 호출하여 “Hello World”를 찍는다.

{#id. class width=“70%”}

# devtools::install_github("soodoku/abbyyR", build_vignettes = TRUE)
library(abbyyR)
setapp(c(Sys.getenv("ABBYY_ID"), Sys.getenv("ABBYY_PW")))

getAppInfo()
Name of Application: d8464ac1-c354-4f73-a772-817b00baf782
No. of Pages Remaining: 499
No. of Fields Remaining: 2495
Application Credits Expire on: 2020-10-14T00:00:00
Type: Normal
$name
[1] "d8464ac1-c354-4f73-a772-817b00baf782"

$displayName
[1] "tidyverse"

$pages
[1] "499"

$fields
[1] "2495"

$expires
[1] "2020-10-14T00:00:00"

$type
[1] "Normal"

3 ABBYY 클라우드 시험가동

ABBYY 클라우드 로그인 작업을 수행하게 되면 각 국가별 대표 언어로 기술된 텍스트 문서가 포함되어 있다. 이를 다운로드 받아 ABBYY 클라우드를 통해 OCR작업을 수행해 보자. 다운로드 받은 이미지 압축을 풀게 되면 Korean.png 파일이 된다. 이를 ABBYY OCR 작업을 수행한 후에 떨어진 결과값을 텍스트로 저장한다. 작업흐름은 다음과 같다.

3.1 대상 텍스트 이미지

Korean.jpg 파일을 확인할 수 있도록 magick 팩키지를 사용해서 R로 불러읽어 들인다.

library(tidyverse)
library(magick)

korean_doc <- image_read("fig/Korean.jpg")

korean_doc %>% 
  image_resize("500x")

3.2 OCR 작업

이미지를 processImage() 함수에 넣어 실어 보내고, 언어를 한국어 language = "Korean"로 지정하여 텍스트를 추출한다. 조금 당황스러울 수도 있겠지만, 개념이 ABBYY 클라우드에 OCR 작업을 보내게 되면 taskID 부여되고 이를 추적하여 결과를 얻게 되는 방식으로 구현되어 있다. 따라서, Status of the task: Completed가 된 경우 작업 결과를 확인할 수 있다.

ocr_task <- processImage(file_path = "fig/Korean.jpg", language = "Korean", exportFormat = "txtUnstructured")
Status of the task:  Queued 
Task ID:  b5e020af-070e-4791-94e9-d6f027773f56 
Sys.sleep(5) ## 클라우드 처리 시간 보장 5초.
getTaskStatus(taskId=ocr_task$id) 
Status of the task:  Completed 
                                    id     registrationTime
1 b5e020af-070e-4791-94e9-d6f027773f56 2020-07-16T08:35:29Z
      statusChangeTime    status filesCount credits
1 2020-07-16T08:35:30Z Completed          1       0
                                                                                                                                                                                                    resultUrl
1 https://ocrsdk.blob.core.windows.net/files/b5e020af-070e-4791-94e9-d6f027773f56.result?sv=2012-02-12&se=2020-07-16T18%3A00%3A00Z&sr=b&si=downloadResults&sig=X6Y7acPhQceTNVpM1RwBtZcSlK74aCICE9UEPSdw0pU%3D

3.3 파일 저장

Status of the task: Completed 완료를 확인 후에 결과를 파일로 저장시킨다.

ocr_result <- getResults(output = "data/", save_to_file = TRUE)
No. of Finished Tasks:  18 
ocr_result %>% 
  select(id, registrationTime, status, local_file_path) %>% 
  filter(id == ocr_task$id)
                                    id     registrationTime    status
1 b5e020af-070e-4791-94e9-d6f027773f56 2020-07-16T08:35:29Z Completed
                            local_file_path
1 data/b5e020af-070e-4791-94e9-d6f027773f56

ocr_task$id을 키값으로 삼아 OCR된 문서에서 텍스트를 추출해보자. 이를 위해 먼저 파일이 위치한 경로와 파일명을 확인하고 나서 read_lines()함수로 텍스트를 불러읽어온다.

ocred_path_filename <- glue::glue("data/{ocr_task$id}")

ocr_text <- read_lines(ocred_path_filename)
ocr_text
 [1] "광학 문자 인식(0西에 011&130161 100021111:1011; 001)은 사람이 쓰거나 기계로 인쇄한 문자의"
 [2] "영상을 이미지 스캐너로 획득하여 기계가 읽을 수 있는 문자로 변환하는 것이다."               
 [3] "이미지 스캔으로 얻을 수 있는 문서의 활자 영상을 컴퓨터가 편집 가능한 문자코드 등의"        
 [4] "형식으로 변환하는 소프트웨어로써 일반적으로 00호이라고 하며, 001은 인공지능이나"           
 [5] "기계 시각(11130111116 \\시011)의 연구분야로 시작되었다."                                   
 [6] "거울이나 렌즈 등의 광학 기술을 이용한 광학 문자 인식과 스캐너 및 알고리즘에 의한"          
 [7] "디지털 문자 인식은 다른 영역으로 생각되었으나 이제는 광학 문자 인식이라는 말이"            
 [8] "디지털 문자 인식을 포함하는 것으로 간주되었다."                                            
 [9] "초기 시스템은 특정한 서체를 읽기 위해 미리 해당 서체의 샘플을 읽는 것을 뜻하는"            
[10] "\"트레이닝\"이 필요했지만, 지금은 대부분의 서체를 높은 확률로 변환이 가능하다. 몇몇"       
[11] "시스템에서는 읽어들인 이미지에서 그것과 거의 일치하는 워드 프로세서 파일과 같은"           
[12] "문서 포맷으로 된 출력 파일을 생성할 수 있으며, 그 중에는 이미지처럼 문서 이외의"           
[13] "부분이 포함되어있어도 제대로 인식하는 것도 있다."                                          

4 명함 텍스트 추출

ABBYY 클라우드 설정이 제대로 되었는지 확인했고, 다음으로 Korean.png 파일을 사용해서 텍스트를 추출하는 작업을 완료했다면 다음으로 특정문서(예를 들어, 전자세금계산서, 영수증, 사업자등록증, 납부고지서 등)를 OCR 하기 위해서 ABBYY 클라우드, 엄밀히 말하면 ABBYY 제품(FineReader)에서 제공하는 기능을 호출하여 사용한다.

4.1 OCR 대상 명함 이미지

구글 이미지 검색에서 얻은 명함 이미지를 한장 다운로드 받아 이를 명함 인식 대상으로 작업한다.

library(tidyverse)
library(magick)

biz_card <- image_read("fig/biz_card.png")

biz_card %>% 
  image_resize("300x")

4.2 명함 OCR 작업

processBusinessCard() 함수를 호출하여 명함 인식에 도전한다.

biz_card_ocr <- processBusinessCard(file_path = "fig/biz_card.png", language = "Korean", exportFormat = "vCard")
Status of the task:  Queued 
Task ID:  6b8263c3-ed24-42b3-a6a9-3a96923a7cb1 
Sys.sleep(5) ## 클라우드 처리 시간 보장 5초.
getTaskStatus(taskId=biz_card_ocr$id) 
Status of the task:  Completed 
                                    id     registrationTime
1 6b8263c3-ed24-42b3-a6a9-3a96923a7cb1 2020-07-16T08:35:42Z
      statusChangeTime    status filesCount credits
1 2020-07-16T08:35:43Z Completed          1       0
                                                                                                                                                                                                        resultUrl
1 https://ocrsdk.blob.core.windows.net/files/6b8263c3-ed24-42b3-a6a9-3a96923a7cb1.result?sv=2012-02-12&se=2020-07-16T18%3A00%3A00Z&sr=b&si=downloadResults&sig=mB6a0e51dOUqy9ezyT%2FTiNsHn804RgstAX9ANsbG%2B5A%3D

명함인식 작업결과를 로컬 컴퓨터 파일로 저장시킨다.

ocr_result <- getResults(output = "data/", save_to_file = TRUE)
No. of Finished Tasks:  19 
Sys.sleep(5)
## 다운로드 받은 명함 OCR 파일 --> 확장자 부여
vCard_name <- glue::glue("data/{biz_card_ocr$id}")
system(glue::glue("cp {vCard_name} data/contact_kim.vcf"), intern = TRUE)
character(0)
ocr_result %>% 
  select(id, registrationTime, status, local_file_path) %>% 
  filter(id == biz_card_ocr$id)
                                    id     registrationTime    status
1 6b8263c3-ed24-42b3-a6a9-3a96923a7cb1 2020-07-16T08:35:42Z Completed
                            local_file_path
1 data/6b8263c3-ed24-42b3-a6a9-3a96923a7cb1

ABBYY에서 인식한 결과를 파일로 저장시켰는데 후속 작업을 위해서 R로 불러와서 인식된 내용을 확인한다.

biz_card_path_filename <- glue::glue("data/{biz_card_ocr$id}")

biz_card_ocr_text <- read_lines(biz_card_path_filename)
biz_card_ocr_text
 [1] "BEGIN:VCARD"                                                           
 [2] "VERSION:2.1"                                                           
 [3] "TEL;CHARSET=utf-8;WORK;VOICE:(02) 5556335"                             
 [4] "TEL;CHARSET=utf-8;WORK;VOICE:01000000000"                              
 [5] "TEL;CHARSET=utf-8;WORK;VOICE:00 000"                                   
 [6] "TEL;CHARSET=utf-8;WORK;VOICE:11010101"                                 
 [7] "TEL;CHARSET=utf-8;WORK;VOICE:(03) 020171"                              
 [8] "LABEL;CHARSET=utf-8;WORK:서울시 강남구 역삼동 668-4번지, 1 층 7티느:"  
 [9] "ADR;CHARSET=utf-8;WORK:;;강남구 역삼동 668-4번지, 1 층 7티느;서울시;;;"
[10] "LABEL;CHARSET=utf-8;WORK:|\\\\40비|0 :"                                
[11] "ADR;CHARSET=utf-8;WORK:|\\40비|0 :"                                    
[12] "LABEL;CHARSET=utf-8;WORK:드-018)1 : 우"                                
[13] "ADR;CHARSET=utf-8;WORK:드-018)1 : 우"                                  
[14] "N;CHARSET=utf-8:박;지 원;;;"                                           
[15] "FN;CHARSET=utf-8:박지원"                                               
[16] "ORG;CHARSET=utf-8:I내品"                                               
[17] "TITLE;CHARSET=utf-8:대표이사"                                          
[18] "NOTE;ENCODING=QUOTED-PRINTABLE;CHARSET=utf-8:I내品=0D=0A="             
[19] "(주)00000=0D=0A="                                                      
[20] "박지 원=0D=0A="                                                        
[21] "대표이사=0D=0A="                                                       
[22] "서울시 강남구 역삼동 668-4번지, 1 층=0D=0A="                           
[23] "7티느: (02)555-6335=0D=0A="                                            
[24] "|\\\\40비|0 : 010-0000-0000=0D=0A="                                    
[25] "드-018)1 : 우1101느0日(101:@03\\\\/0厂(20171"                          
[26] "REV:15072020235408"                                                    
[27] "END:VCARD"                                                             

4.3 R 명함

pagedown 팩키지 pagedown_business_card_template() 함수를 사용해서 명함을 생성시킬 수 있다.

contact_vcf <- read_lines("data/contact_kim.vcf")

# 주요 정보 추출
phone <- str_extract(contact_vcf, "(?<=TEL;CHARSET=utf-8;WORK;VOICE:).*") %>% 
  na.omit() %>% .[1]
title <- str_extract(contact_vcf, "(?<=TITLE;CHARSET=utf-8:).*") %>% na.omit()
name <- str_extract(contact_vcf, "(?<=FN;CHARSET=utf-8:).*") %>% na.omit()
address <- str_extract(contact_vcf, "(?<=ADR;CHARSET=utf-8;WORK:).*") %>% 
  na.omit() %>% .[1]

## 명함생성을 위한 사전 작업
library(ymlthis)

biz_card_yml <- pagedown_business_card_template(
  title = "&nbsp;",
  name = name,
  phone = phone,
  email = "jane.doe@example.com",
  url = "www.example.com",
  address = address,
  logo = "../fig/biz_card_logo.png",
  .repeat = 1
)

biz_card_yml %>% 
  write_lines("data/biz_card.Rmd")

OCR에서 추출한 텍스트 정보를 사용해서 R마크다운 명함으로 다시 제작한다.

biz_card_yml %>% 
  yml_output(pagedown::business_card()) %>% 
  yaml::write_yaml("data/biz_card.Rmd")

yml_file_fixed <- read_lines("data/biz_card.Rmd") 

yml_file_fixed[length(yml_file_fixed)+1] <- NA
yml_file_fixed <- lag(yml_file_fixed, default = "---")
yml_file_fixed[length(yml_file_fixed)+1] <- "---"

yml_file_fixed %>% 
  write_lines("data/biz_card.Rmd")

yml_file_fixed
 [1] "---"                                                     
 [2] "name: 박지원"                                            
 [3] "title: '&nbsp;'"                                         
 [4] "phone: (02) 5556335"                                     
 [5] "email: jane.doe@example.com"                             
 [6] "url: www.example.com"                                    
 [7] "address: ;;강남구 역삼동 668-4번지, 1 층 7티느;서울시;;;"
 [8] "logo: ../fig/biz_card_logo.png"                          
 [9] "repeat: 1.0"                                             
[10] "output: pagedown::business_card"                         
[11] "---"                                                     

4.4 R 명함

이제 앞서 작성한 pagedown 팩키지 명함을 rmarkdown 팩키지 render()함수를 사용해서 HTML 명함을 생성시킨다.

rmarkdown::render("data/biz_card.Rmd")

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |......................................................................| 100%
  ordinary text without R code


/Applications/RStudio.app/Contents/MacOS/pandoc/pandoc +RTS -K512m -RTS biz_card.utf8.md --to html4 --from markdown --output biz_card.html --template /Library/Frameworks/R.framework/Versions/4.0/Resources/library/pagedown/resources/html/card.html --variable 'pagetitle=Business Card' 
htmltools::includeHTML("data/biz_card.html")
Business Card
 

데이터 과학자 이광춘 저작

kwangchun.lee.7@gmail.com