Node.js

[Node.js] Google Vision Api OCR / 텍스트 추출하기 / Tesseract?

JungCw 2024. 12. 11. 16:04

이번에 남는 시간동안 새로운 웹앱을 만들어보았다.

이용자의 출결 관리 및 분류 서비스인데,

근무하면서 출결 인원 확인과 분류를 매번 하는 것이 귀찮아 고안해본 웹앱이다.

FE: https://github.com/ChangwooJ/AttendanceList_FE

BE: https://github.com/ChangwooJ/AttendanceList_BE

 

간단히 설명하면 출석부에 손글씨로 적혀있는 결석자의 이름을 사진으로 입력받으면 OCR을 이용해 인식하고 텍스트화 시켜, 당일 출석자를 추려내 분류해주는 것을 주로 하는 서비스이다.

 

말처럼 다른 기능은 별다른 것이 없어서 손글씨를 인식하도록 하는 것이 포인트다.

 

텍스트를 인식할 수 있게 해주는 방법에는 현실적으로 2가지 방법 정도가 존재했는데,

오픈소스 라이브러리와 api를 이용하는 방법이었다.

 

아무래도 구글에서 오픈소스로 제공하는 라이브러리인 Tesseract.js를 먼저 사용해보았다.

사용은 생각보다 간단했는데, 요약하자면

 

tesseract-ocr 라이브러리 설치 - 이미지 입력 - 메서드 호출 - ocr 실행 및 결과 처리

 

의 순으로 진행된다.

 

다만, 결과가 꽤나 처참하게 나왔다.

원인은 두가지였는데, 먼저 이미지의 전처리가 중요하다는 것.

(이미지의 흑백 처리, 노이즈 처리 등을 해주어야 정확도가 높아진다.)

두번째는, 한글 지원 패키지가 필요하다는 것이다. (kor.traineddata 파일)

 

한글 지원 패키지를 적용해보았으나, 여전히 기댓값에는 미치지 못했다.
예를 들어, 입력값이 '티스토리'라면 결과는 거의 'ㅣㄹㄴㅑㅓ' 이런 수준이었다.

 

이미지 전처리의 문제일 수도 있으나, 서비스의 환경에는 전처리 등의 복잡한 작업이 들어가서는 안되기에 그 조건은 배제하였다.

 

결론적으로는 더 나은 OCR인식 도구가 필요했고, 이 때문에 Google Vision API의 OCR기능을 이용해보기로 하였다.

 

일단 구글 API를 사용하기 위해선 인증 키가 필요한데, 이 JSON키를 발급받는 과정은 생략하겠다.

이 JSON키를 가지고 있다면 이제 코드를 작성할 차례이다.

 

먼저, @google-cloud/vision 패키지를 설치해준다.

npm i @google-cloud/vision

 

패키지를 임포트 해주고, api 클라이언트 초기화를 진행해준다.

const vision = require("@google-cloud/vision");

...

const client = new vision.ImageAnnotatorClient({
  keyFilename: 'path/to/service-account-key.json',
});

 

일반적으로는 이렇지만, json키를 온라인 상에 함부러 올릴 수 없음과 이후 배포 등에 귀찮음이 발생하기에 미리 .env 파일로 정리해 제공하겠다.

const client = new vision.ImageAnnotatorClient({
    credentials: {
      type: process.env.GOOGLE_TYPE,
      project_id: process.env.GOOGLE_PROJECT_ID,
      private_key_id: process.env.GOOGLE_PRIVATE_KEY_ID,
      private_key: process.env.GOOGLE_PRIVATE_KEY.replace(/\\n/g, '\n'), // 개행문자 처리
      client_email: process.env.GOOGLE_CLIENT_EMAIL,
      client_id: process.env.GOOGLE_CLIENT_ID,
      auth_uri: process.env.GOOGLE_AUTH_URI,
      token_uri: process.env.GOOGLE_TOKEN_URI,
      auth_provider_x509_cert_url: process.env.GOOGLE_AUTH_PROVIDER_CERT_URL,
      client_x509_cert_url: process.env.GOOGLE_CLIENT_CERT_URL
    }
});

 

이제 설정이 완료되었으니 이미지로부터 텍스트를 추출하기만 하면 된다.

 

const [result] = await client.textDetection(이미지 경로);
const detections = result.textAnnotations;

if (detections && detections.length > 0) {
	const extractedText = detections[0].description; // 추출된 텍스트
	console.log("OCR 추출 결과:", extractedText);
	res.json({ text: extractedText });
} else {
	res.status(200).json({ text: "텍스트를 찾을 수 없습니다." });
}

 

성공적으로 추출되었다면, text에 담겨 반환될것이다.

 

물론 훨씬 높은 정확도를 보여주지만, 여전히 완벽하지는 않다.

아무래도 텍스트 추출에 있어서 정확도가 높기는 하나, 손글씨라는 문제가 여전히 남아있기 때문이다.

작성자가 아닌 제 3자가 보면 못알아볼 수도 있는 것이 손글씨이기 때문에 한계가 존재하는 듯 했다.

일단, 텍스트 인식은 이 정도까지인 것 같으니, 이제 이 오차를 줄일 방법을 모색해야한다.