본문 바로가기
🎯 etc/API

[ Google vision Cloud OCR (3)] OCR / MultipartFile - JAVA ( + ❗❗ 트러블슈팅)

by 깸뽀 2022. 11. 18.
728x90
🍃   spring boot-version '2.7.5'
🌎    java-version 11
🐘   gradle
☁️   Google Cloud Vision API - OCR

 

👉 2편 Google Storage 생성: https://bkyungkeem.tistory.com/41

 

[ Google vision Cloud OCR (2)] Google Storage 생성 - JAVA

🍃 spring boot-version '2.7.5' 🌎 java-version 11 🐘 gradle ☁️ Google Cloud Vision API - OCR 👉 1편 환경설정: https://bkyungkeem.tistory.com/40 [ Google vision Cloud OCR (1)] API 발급 및 환경변수 설정 - JAVA 🍃 spring boot-versi

bkyungkeem.tistory.com

 

 

 

예시코드는 Google Cloud Vision 공식문서에 있는 코드를 기반으로 작성했고,

🔖 깃허브 주소 https://github.com/kimbokyung1220/OCR_Test

 

GitHub - kimbokyung1220/OCR_Test: Google Cloud Vision OCR - API

Google Cloud Vision OCR - API. Contribute to kimbokyung1220/OCR_Test development by creating an account on GitHub.

github.com

+) git에서 실제로 프로젝트에서 사용한 코드를 볼 수 있습니당!

명함의 케이스가 많아서 러닝을 시킬 정도의 기간이 되지 않아 명함이미지내 텍스트 추출케이스를 정해서

if문으로 조건을 걸어서 원하는 데이터를 얻을 수 있도록 진행했다는 점 참고 부탁드려요!!! :-)

 

 

 

 

📌 참고할 코드 - Cloud Vision API 공식문서

👉 https://cloud.google.com/vision/docs/ocr

 

이미지의 텍스트 감지  |  Cloud Vision API  |  Google Cloud

의견 보내기 이미지의 텍스트 감지 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 스캔된 문서에서 텍스트를 감지하는 경우 광학 문자 인식, 구조화된 양식

cloud.google.com

 

 로컬 이미지의 텍스트 감지 => detectText () 메서드

    : 로컬 파일경로 사용

 

 원격 이미지 텍스트 인식 => detectTextGcs () 메서드

    : storage 경로 사용

 

 

📌 여기서 다룰 건 google Storage와 연결해 OCR기능을 구현하는 것 입니다!!!!!!

(참고할 코드에서 복사 가능)

 

 

📌 패키지 및 클래스

 

 


💻 build.gradle

    ✔ 의존성 추가

// json
implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
// cloud vision
implementation platform('com.google.cloud:libraries-bom:26.1.4')
implementation 'com.google.cloud:google-cloud-bigquery'
implementation 'com.google.cloud:google-cloud-vision:3.3.0'
// gcp storage 의존성
implementation 'org.springframework.cloud:spring-cloud-gcp-starter:1.2.8.RELEASE'
implementation 'org.springframework.cloud:spring-cloud-gcp-storage:1.2.8.RELEASE'

 

💻  OcrController.java

    ✔ MVC패턴 사용

@RequiredArgsConstructor
@RestController
@RequestMapping(value = "/api")
public class OcrController {
    private final OcrService ocrService;
 
    @PostMapping(value = "/scan/cards", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
    public ResponseDto<?> orcTest(@RequestPart(value = "cardImg", required = false) MultipartFile cardImg) throws IOException {
 
        return ocrService.detectTextGcs(cardImg);
    }
}

 

💻  GoogleCloudUploadService.java

      : Google Storage에 이미지 파일 업로드 로직

      : bucketName은 보안의 문제로 application.propertise에 등록해서 @Value로 연결하여 사용했음

      : @Value 👉  import org.springframework.beans.factory.annotation.Value; (Lombock X )

      : 참조 git 👉 https://gist.github.com/nogsantos/b3f4c0f7cd779b345a12d586ef552bdf

 

Google cloud bucket upload - Java Spring boot exemple

Google cloud bucket upload - Java Spring boot exemple - FileUpload.java

gist.github.com

 

import org.springframework.beans.factory.annotation.Value;

@Component
public class GoogleCloudUploadService {
 
    @Value("${cloud.gcp.storage.bucket.name}")
    String bucketName;
 
    //get service by env var GOOGLE_APPLICATION_CREDENTIALS. Json file generated in API & Services -> Service account key
    private static Storage storage = StorageOptions.getDefaultInstance().getService();
 
    public String upload(MultipartFile file) {
        try {
            BlobInfo blobInfo = storage.create(
                    //Todo: UUID 추가하기 (파일이름 중복)
                    BlobInfo.newBuilder(bucketName, file.getOriginalFilename()).build(), //get original file name
                    file.getBytes() // the file
//                    BlobTargetOption.predefinedAcl(PredefinedAcl.PUBLIC_READ) // Set file permission
            );
            return blobInfo.getMediaLink(); // Return file url
        } catch (IllegalStateException | IOException e) {
            throw new RuntimeException(e);
        }
    }
}

 

 

💻 OcrService.java

     : Google Storage에 업로드한 파일로 OCR

     : 이미지 파일은 MultipartFile타입으로 formData형식으로 보냄

@Service
@RequiredArgsConstructor
public class OcrService {
 
    @Value("${cloud.gcp.storage.bucket.filePath}")
    String bucketFilePath;
    private final GoogleCloudUploadService googleCloudUploadService;
 
    public ResponseDto<?> detectTextGcs(MultipartFile cardImg) throws IOException {
        googleCloudUploadService.upload(cardImg);
 
        // TODO(developer): Replace these variables before running the sample.
        String filePath = bucketFilePath + cardImg.getOriginalFilename();
        return detectTextGcs(filePath);
    }
 
    // Detects text in the specified remote image on Google Cloud Storage.
    public ResponseDto<?> detectTextGcs(String gcsPath) throws IOException {
        List<AnnotateImageRequest> requests = new ArrayList<>();
 
        ImageSource imgSource = ImageSource.newBuilder().setGcsImageUri(gcsPath).build();
        Image img = Image.newBuilder().setSource(imgSource).build();
        Feature feat = Feature.newBuilder().setType(Feature.Type.TEXT_DETECTION).build();
        AnnotateImageRequest request =
                AnnotateImageRequest.newBuilder().addFeatures(feat).setImage(img).build();
        requests.add(request);
 
        // Initialize client that will be used to send requests. This client only needs to be created
        // once, and can be reused for multiple requests. After completing all of your requests, call
        // the "close" method on the client to safely clean up any remaining background resources.
        try (ImageAnnotatorClient client = ImageAnnotatorClient.create()) {
            BatchAnnotateImagesResponse response = client.batchAnnotateImages(requests);
            List<AnnotateImageResponse> responses = response.getResponsesList();
 
            for (AnnotateImageResponse res : responses) {
                if (res.hasError()) {
                    System.out.format("Error: %s%n", res.getError().getMessage());
                    return null;
                }
 
                // For full list of available annotations, see http://g.co/cloud/vision/docs
                for (EntityAnnotation annotation : res.getTextAnnotationsList()) {
                    System.out.format("Text: %s%n", annotation.getDescription());
                    System.out.format("Position : %s%n", annotation.getBoundingPoly());
                }
            }
            return ResponseDto.success("성공");
        }
    }
}

 

 

💻 application.properties

     : Google Storage 정보

     : properties에 정보를 저장해두면 @Value 어노테이션을 사용할 수 있음

# Google Cloud Storage
spring.cloud.gcp.storage.credentials.location=classpath:key.json
cloud.gcp.storage.bucket.name=버킷이름
cloud.gcp.storage.bucket.filePath=gs://버킷이름/

 

 

 

👀 POST맨 결과

 

 

 


❗❗ 트러블 슈팅

기존에는 aws S3와 연결해서 코드를 작성했다

 S3에 파일업로드 - S3에 업로드 한 파일 URL을 받아 - detectText()

코드는 다 작성해 뒀고 S3에 파일 업로드 하기 까지 완료!

 

그런데

😈 에러

response에서 image에 대한 정보를 가져오지 못함 ⇒ ERROR

 

🚶 에러 찾는 과정 

  • for문 안의 AnnotateImageResponse res가 Error를 가지므로, 어느 부분에서 에러가 났는지 그 윗부분을 하나하나 찾아봐야 했음.
  • detectTextGcs() 매소드에서 setImageUri(filePath) 가 잘 작동하는지 디버깅 걸어봄

 

🔒 원인 

Google Cloud Vision API는 Google Services URL만 입·출력 대상으로 허용 ⇒ Google Cloud Storage를 제외한 URL에서 작동하지 않음

👉 구글링 검색 결과) https://stackoverflow.com/questions/52274071/pdf-tiff-document-text-detection

👉 구글 홈페이지 공식문서 참고) https://cloud.google.com/vision/docs/ocrhl=ko#vision_text_detection_gcs-java

 

🔑 해결방법 - 2번으로 함

 

1) Amazon S3에서 Cloud Storage로 마이그레이션

👉 https://cloud.google.com/storage/docs/aws-simple-migration?hl=ko 

 

Amazon S3에서 Cloud Storage로 단순 마이그레이션  |  Google Cloud

의견 보내기 Amazon S3에서 Cloud Storage로 단순 마이그레이션 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 이 페이지에서는 Amazon Simple Storage Service(Amazon S3)에

cloud.google.com

 

2) Google Cloud Storage를 사용하여 파일 업로드

👉 https://bkyungkeem.tistory.com/41

  • 구글 저장소 관리자의 권한을 준 iam계정을 새로 만들고, json타입의 키를 새로 발급받는다.
  • GCS에 이미지파일을 업로드하는 로직을 만든다.
  • detectTextGcs() 메소드를 사용해 OCR기능을 구현한다.

 

 

 

 

📖 참조

728x90

댓글