지금까지 구글 Vision API를 사용한 OCR 응답속도는 너무 느립니다. 지난 포스트에서, batch 요청으로 5초대로 응답시간이 많이 개선되었으나, 여전히 느립니다. 실제 서비스를 위해서라면 최소 3초 이내의 응답속도를 가져야만 합니다.
이를 위해서, HTML 파싱 속도 개선 및 OCR 속도 개선은 필수적인 요소입니다. 우선, HTML 파싱은 팀원이 하고 있으니 저는 OCR 속도 개선을 담당하게 되었답니다 ...ㅎㅎ
현재 OCR 요청 구조를 보면 다음과 같습니다.
ImageSource imgSource = ImageSource.newBuilder().setImageUri(url).build();
Image img = Image.newBuilder().setSource(imgSource).build();
Feature feat = Feature.newBuilder().setType(Feature.Type.TEXT_DETECTION).build();
return AnnotateImageRequest.newBuilder().addFeatures(feat).setImage(img).build();
기본 예제에 나온 방식인데, 이 외에도 구글 비전에 소개된 방법으로는
- 이미지를 바이너리로 직접 업로드
- base64로 인코딩된 이미지를 업로드
- Google Cloud Storage에 업로드된 사진을 이용
이 소개되어 있습니다. 여기서 우선, 3번 방법은 불가능합니다. OCR을 진행할 파일을 매번 드라이브에 업로드하는 것은 DB 용량도 문제고 2번 요청을 날려야하기 때문에 현실적으로 할 수 있는 것은 1번과 2번입니다.
우선 1번부터 진행해보았습니다.
바이너리로 업로드를 합니다.
요청 부분을 살짝 수정하면 됩니다.
URL imageUrl = new URL(url);
byte[] imageBytes = imageUrl.openStream().readAllBytes();
ByteString imgString = ByteString.copyFrom(imageBytes);
이렇게 이미지 URL에서 바이너리로 변환하고, 해당 결과를
ImageSource.newBuilder().setImageUriBytes(imgString)
으로 전달하면 됩니다.
테스트를 진행합니다. "광안리 맛집" 을 검색어로 5개의 결과를 파싱하였습니다.
응답시간을 보면
평균적으로 이전보다 시간이 절반으로 준 것을 볼 수 있습니다!! 바이너리로 전환했을 뿐인데, 약 50%의 성능 향상이 !?!
바이너리만으로 이런 드라마틱한 성능향상이 나타난 것을 보면, base64 인코딩도 꽤나 좋은 결과를 낼 것 같습니다.
1번 방법에서 마지막 문자열을 인코딩만 하면 끝!
URL imageUrl = new URL(url);
byte[] imageBytes = imageUrl.openStream().readAllBytes();
String toBase64 = Base64.getEncoder().encodeToString(imageBytes);
이제 성능 테스트를 해봅니다.
테스트 환경은 앞선 1번과 동일합니다. 결과를 보면
응답시간을 보면
평균적으로 앞선 1번 방법보다 1초가 줄어든 모습입니다!! 단지 바이너리로 전달하고, base64 인코딩만 했을 뿐인데 10초대에서 1.5초대로 아주 극적인 변화가 나타났습니다!
요청은 항상 바이너리로, 인코딩하자
2023.11.22일 기준 ... 위 방법은 불가능 ... 분명 가능했었는데 이젠 imageUri로는 gs 혹은 이미지 url만 가능해서 불가능합니다. REST API를 통해 호출해야 정상작동함!
https://medium.com/bankify-tech-blog/how-to-optimize-the-speed-of-google-vision-api-cdc5e452104b