SpringBoot

SpringBoot : OCR 화면 번역 프로그램 만들기 ( API 사용 )

흰색기린 2024. 7. 11. 10:50

프로젝트 개요

이미지 업로드 및 텍스트 번역 기능을 제공하는 웹 애플리케이션입니다. 주요 기능은 이미지에서 텍스트 추출과 번역입니다.

사용된 기술 스택

백엔드

  • Spring Boot: 백엔드 프레임워크
    • spring-boot-starter-web: 웹 애플리케이션 개발
    • spring-boot-starter-thymeleaf: 템플릿 엔진
    • spring-boot-starter-test: 테스트 라이브러리
    • spring-boot-devtools: 개발 도구
  • OkHttp: HTTP 클라이언트 라이브러리 (com.squareup.okhttp3:okhttp:4.9.3)
  • Jackson: JSON 데이터 파싱 및 생성 (com.fasterxml.jackson.core:jackson-databind)
  • Tess4J: OCR 라이브러리 (net.sourceforge.tess4j:tess4j:4.5.5)
  • Google Cloud Translate: 구글 클라우드 번역 API (com.google.cloud:google-cloud-translate:1.94.0)
  • Apache Tika: 언어 감지 (org.apache.tika:tika-core:1.27)

프론트엔드

  • HTML/CSS: UI 구성 및 스타일링
  • JavaScript: 클라이언트 측 스크립팅

기타

  • Gradle: 빌드 도구
  • Thymeleaf: 서버사이드 템플릿 엔진

주요 설정 파일

  • application.properties
    • spring.application.name, spring.servlet.multipart.max-file-size, spring.servlet.multipart.max-request-size, deepl.api.key

주요 클래스 및 파일

유틸리티 클래스

  • OCRUtil: 이미지에서 텍스트를 추출하는 기능 제공

서비스 클래스

  • TranslationService: 텍스트 번역 기능 제공

컨트롤러 클래스

  • TranslationController: HTTP 요청을 처리하고 서비스 호출

HTML 파일

  • index.html: 기본 웹 페이지로, 이미지 업로드 및 번역 UI 요소 포함

rapidapi 에서 DeepApi 이용하여 OkHttpClient 이용하여 json 형식으로 보냄

 

트러블 슈팅

1. 400 Bad Request를 200 OK 상태값에서 토해냄

2. json 타입의 문제인가 해서 봤는데 문제 없었고 보내는 data값들도 맞았음 

3. 로그를 하나하나 다 찍어보면서 Debug해본 결과 "p" 내용 값에 이미지를 번역한 마지막 text에 줄바꿈 문자가 들어가 있는 것을 확인 

 

        text = text.replace("\n", "").replace("\r", ""); // text 줄바꿈 제거
        // Construct the JSON body correctly
        String jsonBody = String.format("{\"q\":\"%s\",\"source\":\"en\",\"target\":\"%s\"}", text, targetLang);

 

4. 보내기전 replace를 이용하여 줄바꿈 제거하니 번역된 결과가 나오는 것을 확인

 


간단 프로젝트 구성 

<div class="container">
  <div class="upload-section">
    <input type="file" id="imageInput">
    <button onclick="uploadImage()">upload Image</button>
    <button class="translateImage" onclick="translateImage('en')">translate</button>
    <button class="translateImage" onclick="translateImage('ko')">translate-KR</button>
    <button class="translateImage" onclick="translateImage('ja')">translate-JP</button>
  </div>

  <div class="image-display">
    <h2>Translated Text (en)</h2>
    <div id="translatedText-EN"></div>
  </div>

  <div class="image-display">
    <h2>Translated Text (ko)</h2>
    <div id="translatedText-KR"></div>
  </div>

  <div class="image-display">
    <h2>Translated Text (jp)</h2>
    <div id="translatedText-JP"></div>
  </div>
</div>

 

화면은 이런식으로 번역할 값 en , ko , ja 등등 여기서 en을 EN으로보내면 이것도 제대로 받지 못한다.

 

형식을 정확하게 해서 보내야함.

 

보내는 값
테스트값 400 에러

 

스크립트에서는 fetch를 이용하여 번역할 텍스트값을 url로 보내줌.

 

fetch(`/translate?q=${textToTranslate}&targetLang=${targetLang}`)
        .then(response => {
            console.log('응답 상태:', response.status);
            // HTTP 응답이 정상적이지 않은 경우 오류를 throw합니다
            if (!response.ok) {
                throw new Error('네트워크 응답이 문제가 있습니다 ' + response.statusText);
            }
            return response.json(); // JSON 형식으로 응답을 가져옵니다
        })
        .then(data => {
            console.log('번역된 데이터:', data);
            // 대상 언어에 따라 적절한 요소에 번역된 텍스트를 설정합니다
            switch (targetLang) {
                case 'en':
                    document.getElementById('translatedText-EN').innerText = data.translatedText;
                    break;
                case 'ko':
                    document.getElementById('translatedText-KR').innerText = data.translatedText;
                    break;
                case 'ja':
                    document.getElementById('translatedText-JP').innerText = data.translatedText;
                    break;
                default:
                    break;
            }
        })
        .catch(error => {
            console.error('fetch 작업 중 문제가 발생했습니다:', error);
        });
*   1. fetch에서 보낼 수 있는 옵션들
*    - method : 'POST' 요청 메소드
*    - header : 헤더를 설정
*    headers: {
           'Content-Type': 'application/json',
           'Authorization': 'Bearer token'
      }
      JSON 데이터 전송할때 body : JSON.stringfy({ key : 'value }) 형식으로 보낼 수 있음
      mode: 'cors' 요청 모드 기본값 'cors' 임
      credentials: 'include' 요청에 포함될 자격 증명 기본 값 'same-origin'임

      2. Promise는 작업의 완료 또는 실패를 나타내는 객체
        - Pending (대기) , Fullfilled (이행) , Rejected (거부)
      -> fetch는 promise 객체를 반환하여 현재 대기,이행,거부 인지 보여준다.

      - promise는 이런 형태
      let promise = new Promise(function(resolve, reject) {
          setTimeout(() => resolve("완료!"), 1000); // 1초 후에 "완료!"를 반환
        });

        promise.then(
          result => console.log(result), // "완료!"를 출력
          error => console.log(error) // 에러 발생 시 실행
        );

        fetch를 세밀하게 다룰 수 있음

 

OCR을 사용하려면 일단 

implementation 'net.sourceforge.tess4j:tess4j:4.5.5'
import net.sourceforge.tess4j.Tesseract; // 광학 문자 인식 수행 라이브러리 Tess4j 사용
import net.sourceforge.tess4j.TesseractException;

 

광학 문자 인식 수행 라이브러리가 필요함

tesseract.doOCR(new java.io.File(imagePath)); // 해당 이미지 파일 객체 선택해서 분석

 

이런식으로 doOCR하면 알아서 번역해준다.

 

이미지 번역까지는 확인을 했고 각 언어 마다 번역을 하려면 번역 api가 필요함 , 다른것들도 많았는데 무료이고 비교적 설정이 간단한거로 채택.


번역 API

 

RapidAPI에서 제공하는 DeepL API를 사용

 

1. RapidAPI Key 설정

rapidapi.key=YOUR_RAPIDAPI_KEY

 

2. DeepL API에서 보내는 예제 방법대로 Service구현 후 요청

3. JSON 타입으로온 데이터를 본인 프로젝트에 맞게 뿌려주면 완료

프로젝트 전체 소스 댓글로 남겨주시면 알려드립니다.