[Python] Google Cloud Vision API 사용하기 Develop Tip

Vision, Image Re 또는 OCR 등 여러 가지 이미지 관련 클라우드 서비스를
Microsoft Azure, IBM Watson 을 포함하여 Google 에서도 제공하고 있습니다.
차후에 기회가 되면 동일한 이미지에 대하여 서로 다른 결과가 나오는
비교 결과를 만들 수 있겠지만, 이번에는 단순 Google Cloud Vision API 라는 것을
이용하여 이미지로 부터 여러가지 결과를 얻어내는 것에 관하여 살펴보도록 하겠습니다.

제일 먼저 Google Cloud Vision API를 사용하기 위해서는 자신의 사용 권한을
얻는 거이 필요합니다. 그 결과는 JSON 파일 형태가 됩니다.

다음의 과정은 https://console.cloud.google.com/ 에 접속해서 
사용자 인증정보를 생성하는 과정입니다.

최초 접속해서 콘솔에 들어갔다고 가정합니다.

해당 사이트에 들어가서 대시보드 상태에서, "cloud vision" 으로 검색을 하여 "Cloud Vision API" 를 찾습니다.

위와 같이 결과가 나오면 "사용 설정"을 누르고,

우측 상단의 "사용자 인증 정보 만들기" 가 보입니다.

이를 누르면,

프로젝트에 사용자 인증정보 추가 라는 항목이 나오는데,

필요한 사용자 인증 정보의 종류에 "Cloud Vision API" 를 선택하고,

서비스 계정을 만들고 "JSON" 형식으로 키를 저장하도록 합니다.

해당 서비스 계정 및 키를 생성하고 나서는 해당 JSON 파일을 브라우저를 통하여 저장합니다.

그러면 그 결과의 JSON은 위와 같은 형식으로 되어 있음을 알 수 있습니다.

이제는 이 키 파일을 이용하여 Google Cloud Vision API 를 파이썬에서 사용해보도록 하겠습니다.
우선은 필요한 라이브러리 입니다.

google-cloud-vision
protobuf3-to-dict>=0.1.5
opencv-python>=4.1.1.26

위 세 줄을 requirements.txt에 넣고 설치했습니다.

import cv2
from google.cloud import vision

그 다음 위와 같이 import 를 한 다음,

class GoogleVisionAPI(object):

라고 클래스를 만들고,

    # ==========================================================================
    def __init__(self, credential, image):
        json_credential = credential
        img_file = image
        self.img_file = img_file
        self.face_max_results = face_max_results
        # for internal
        self.client = None
        self.image = None
        self._open()

위와 같이 초기화를 한 다음,

    # ==========================================================================
    def _open(self):
        os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = self.json_credential
        self.client = vision.ImageAnnotatorClient()
        with io.open(os.path.abspath(self.img_file), 'rb') as ifp:
            content = ifp.read()
        # noinspection PyUnresolvedReferences
        self.image = vision.types.Image(content=content)

위와 같이 내부적으로 open한 후,

    # ==========================================================================
    def do(self, op):
        if op == 'Face':
            rp = self.client.face_detection(image=self.image)
            r = self._save_face_result(rp, self.argspec.output_image)
            sys.stdout.write(str(r))
        elif op == 'Label':
            rp = self.client.label_detection(image=self.image)
            r = self._save_label_result(rp, self.argspec.output_image)
            c = csv.writer(sys.stdout, lineterminator='\n')
            c.writerow(['description', 'score'])
            if r:
                for line in r:
                    c.writerow(line)
        elif op == 'Landmark':
            rp = self.client.landmark_detection(image=self.image)
            r = self._save_landmark_result(rp, self.argspec.output_image)
            c = csv.writer(sys.stdout, lineterminator='\n')
            c.writerow(['description', 'score', 'latitude', 'longitude'])
            if r:
                for line in r:
                    c.writerow(line)

    # ==========================================================================
    # noinspection PyMethodMayBeStatic
    def _save_landmark_result(self, rp, save_img_path):
        if save_img_path:
            img = cv2.imread(self.img_file)
            overlay = img.copy()
        lines = list()
        rs = rp.landmark_annotations
        for lm in rs:
            row = [lm.description, float('%.2f' % lm.score)]
            box = [(vertex.x, vertex.y) for vertex in lm.bounding_poly.vertices]
            if save_img_path:
                cv2.rectangle(overlay, box[0], box[2], (255, 0, 255), 2)
                cv2.putText(overlay, lm.description, (box[0][0]+10, box[0][1]+20),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 255), 1)
            for loc in lm.locations:
                row.extend([loc.lat_lng.latitude, loc.lat_lng.longitude])
            lines.append(row)
        if save_img_path:
            alpha = 0.7
            image_new = cv2.addWeighted(overlay, alpha, img, 1 - alpha, 0)
            cv2.imwrite(save_img_path, image_new)
        return lines


위와 같은 식으로 개별 visual operation에 맞게 작업을 하면 됩니다.

아직은 회사에 기능에 맞게 개발한 사항이라,
전체 코드를 open 하지 않았습니다.
(차후 정책에 따라 Open 할 수도 있을 것 같습니다)

해당 샘플 등은 구글링을 통해서 쉽게 구할 수 있었습니다.
참고할 만한 것은 API를 호출하고 나서 그 결과가 ..._annotations 라는 식의
개별 결과가 나오기 때문에 각각의 결과에 따른 분석 내용을 참고해야 한다는 것입니다.

다음은 개별 API 호출 및 그 결과의 이미지 입니다.

Page OCR 분석을 하였고, 빨간 테두리가 "Page", 녹색 테두리가 "Paragraph" 파란 테두리가 "Word" 분석 된 결과이고,
OCR 은 모두 100% 정도 잘 찾아왔습니다. 필요에 따라 개별 Page, Paragraph, Word 별 결과의 Output을 구할 수도 있습니다.

일본어, 중국어, 한국어 등도 모두 잘 분석하여 결과를 구해왔으며 심지어 필기체로 80~90% 인식하는 놀라운 결과를
보여주었습니다.

Face 결과를 구해오면 얼굴 분석된 결과 몇 명이 있는가를 결과로 가져옵니다.

Label 및 Localized Object 분석은 유사할 수도 있지만 Label은 보다 자세한 결과의 Annotation 용
label Text 결과가 나오고, Localized Object 는 구성과 전체라는 개념의 객체 분석을 합니다.
(우리집 행운이의 Label 결과를 구하면, 포유류, 개, 토이푸들, ... 등으로 상세한 결과가 나왔습니다.

위의 결과는 다른 사진의 Localized Objects 를 구해온 결과입니다. 자동차와 미녀의 부분 객체를 구해왔습니다.

Logo 기능을 이용하면 해당 로고를 딱 찾아옵니다.

Landmark 로 찾는 기능인 경우에는, 광화문 사진도 알아서 찾아오고, 위경도 까지 구할 수 있었습니다.


어느 분께는 도움이 되셨기를 ..

덧글

  • 나눔팁 2019/11/05 14:21 # 삭제 답글

    구글에서 제공하면 믿고 쓰는데, 무료아니겠죠?
  • 지훈현서아빠 2019/11/05 20:33 #

    서비스 가격을 알아보시면 될 듯요.. 아마 한달 5천번 까지는 무료인가 합니다..
댓글 입력 영역

구글애드텍스트