Google Cloud API [OCR] 구현
구글 공식 문서를 이용해 구현
https://cloud.google.com/vision/docs/ocr?hl=ko
이미지의 텍스트 감지 | Cloud Vision API | Google Cloud
의견 보내기 이미지의 텍스트 감지 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 스캔된 문서에서 텍스트를 감지하는 경우 광학 문자 인식, 구조화된 양식
cloud.google.com
로컬 이미지 분석 vs. 원격 이미지 분석
사용자가 사진을 찍으면, 사진 안에 있는 텍스트를 읽어들여 다음 화면에서 보여주면 되는 거라, 로컬 이미지 텍스트 감지 방법을 선택
를 하려다가, 문서화된 글씨가 아닌 손글씨를 분석해야할 때 더 적합한 API를 사용하기로 했다.
https://cloud.google.com/vision/docs/handwriting?hl=ko
이미지의 필기 입력 감지 | Cloud Vision API | Google Cloud
의견 보내기 이미지의 필기 입력 감지 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 참고: 이 API를 휴대기기 앱에서 사용하는 경우 Firebase 머신러닝 및 ML Ki
cloud.google.com
1. Google Cloud Vision API 신청 & 설정
https://cloud.google.com/gcp?hl=ko
https://cloud.google.com/gcp?hl=ko
cloud.google.com
여기서 신청
(이전에 사용한 경험이 있어, 이미 가입된 상태라 과정 생략)
2. VISION API 설정 (OCR)
https://console.cloud.google.com/projectselector2/home/dashboard?hl=ko&inv=1&invt=AbsVNg
Google 클라우드 플랫폼
로그인 Google 클라우드 플랫폼으로 이동
accounts.google.com
API 관련 설정
서비스 계정까지 설정 완료
json 값으로 키 발급
여기서 결제 정보 등록까지 마쳐야 한다.
이걸 안 해서 500에러 2시간 동안 봤다..
3. resources/~ . json 파일 추가
이는 .gitignore로 빼서 관리 (그렇지 않으면 git push 조차 안 됨)
4. yml 설정 추가
ocr:
api:
provider: google
key-file: src/main/resources/ocr/service-key.json
배포 시 환경 변수 설정 추가 필요
5. Controller 및 Service 코드
package com.weve.controller;
import com.weve.common.api.payload.BasicResponse;
import com.weve.domain.User;
import com.weve.service.ImageService;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.jdbc.support.CustomSQLErrorCodesTranslation;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@RestController
@RequestMapping("/api/image")
@RequiredArgsConstructor
@Tag(name = "OCR", description = "OCR 관련 API입니다.")
public class ImageController {
private final ImageService imageService;
@PostMapping
public BasicResponse<String> postOcrText(@AuthenticationPrincipal UserDetails userDetails, @RequestParam("imageFile") MultipartFile imageFile) throws IOException {
String username = userDetails.getUsername();
return imageService.postOcrTextByFile(username, imageFile);
}
}
package com.weve.service;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.cloud.vision.v1.*;
import com.google.protobuf.ByteString;
import com.weve.common.api.payload.BasicResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
@Slf4j
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class ImageService {
private final ResourceLoader resourceLoader;
@Value("${ocr.api.key-file}")
private String ocrKeyFilePath;
public BasicResponse<String> postOcrTextByFile(String username, MultipartFile imageFile) throws IOException {
// 예외처리 추가
try (ImageAnnotatorClient vision = createVisionClient()) {
ByteString imgBytes = ByteString.readFrom(imageFile.getInputStream());
Image image = Image.newBuilder().setContent(imgBytes).build();
return analyzeImage(vision, image);
}
}
// OCR 분석 로직
private BasicResponse<String> analyzeImage(ImageAnnotatorClient vision, Image image) {
AnnotateImageRequest request = AnnotateImageRequest.newBuilder()
.addFeatures(Feature.newBuilder().setType(Feature.Type.TEXT_DETECTION))
.setImage(image)
.build();
BatchAnnotateImagesResponse response = vision.batchAnnotateImages(List.of(request));
String extractedText = response.getResponses(0).getTextAnnotations(0).getDescription();
return BasicResponse.onSuccess(extractedText);
}
// API 클라이언트
private ImageAnnotatorClient createVisionClient() throws IOException {
Resource resource = resourceLoader.getResource("file:" + ocrKeyFilePath);
FileInputStream credentialsStream = new FileInputStream(resource.getFile());
GoogleCredentials credentials = GoogleCredentials.fromStream(credentialsStream);
return ImageAnnotatorClient.create(ImageAnnotatorSettings.newBuilder()
.setCredentialsProvider(() -> credentials)
.build());
}
}
결과
분석한 이미지
분석 결과
정확도 엄청 높다.. 재밌다 8ㅇ8 !!