본문 바로가기

과거공부모음

Nest.js에서 Google Vision API 사용하기

프로젝트를 진행하면서 유사한 이미지를 추천해 주는 기능을 위해서 Vision을 이용해 사진에 라벨링 하는 기능을 구현했는데 복습하며 정리해 보도록 하겠다

 

Google Cloud Console을 먼저 세팅하자

https://cloud.google.com/vision/docs/setup?hl=ko 

 

빠른 시작: Vision API 설정  |  Google Cloud

의견 보내기 빠른 시작: Vision API 설정 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 이 가이드에서는 Vision을 처음 사용하는 데 필요한 모든 설정 단계를 제

cloud.google.com

 

해당 문서를 따라서 설정을 하면 json으로 된 키파일을 다운받을 수 있다 안전하게 보관해 두자

 

필요한 패키지를 먼저 다운로드하고 시작하자

npm install @google-cloud/vision --save

 

google vision api를 사용하기 위해서 class를 만들자

import vision, { ImageAnnotatorClient } from '@google-cloud/vision';
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as _ from 'lodash';

@Injectable()
export class GoogleVisionService {
  client: ImageAnnotatorClient;

  constructor(private configSerivce: ConfigService) {
    const googlePrivateKey = this.configSerivce.get('GOOGLE_VISION_API_SECRET_KEY');
    const clientEmail = this.configSerivce.get('GOOGLE_VISION_API_CLIENT_EMAIL');
    this.client = new vision.ImageAnnotatorClient({
      credentials: {
        private_key: googlePrivateKey,
        client_email: clientEmail,
      },
    });
  }

  async imageLabeling(image: string) {
    return this.client
      .labelDetection(image)
      .then((results) => {
        const labels = results[0].labelAnnotations;
        if (_.isNil(labels)) return [];

        const result = labels.map((label) => {
          if (_.isString(label.description)) {
            return label.description;
          }
        });

        return [...new Set(result)];
      })
      .catch((err) => {
        console.log('error: ', err);
        return [];
      });
  }
}

아까 받은 json파일에서 API 시크릿키와 API 이메일을 가지고 vision 클라이언트를 생성하고 사용한다

imageLabeling에서 매개변수로 받은 이미지를 labelDetection메세드를 사용해서 해당 이미지에 대한 라벨링을 진행한다

중복되는 라벨이 존재하기 때문에 Set을 이용해서 중복값을 제거한 후 반환한다

 

만든 GoogleVisionService클래스를 사용하러 가보자

photospot.module에 의존성 주입을 시킨다

providers: [PhotospotService, S3Service, GoogleVisionService],

 

그리고 photospot.service로 가보자

async createImageKeyword(image: string, photoId: number): Promise<void> {
    const photoKeywords = await this.googleVisionService.imageLabeling(image);
    const keyword = [];
    for (const photoKeyword of photoKeywords) {
      if (_.isUndefined(photoKeyword)) {
        continue;
      }

      const preKeyword = await this.photoKeywordRepository.findOne({ where: { keyword: photoKeyword } });
      if (_.isNil(preKeyword)) {
        const insertKeyword = await this.photoKeywordRepository.save({ keyword: photoKeyword });
        keyword.push(insertKeyword);
      } else {
        keyword.push(preKeyword);
      }
    }
    const photo = await this.photoRepository.findOne({ where: { id: photoId } });
    if (_.isNil(photo)) {
      return;
    }
    photo.photoKeywords = keyword;
    await this.photoRepository.save(photo);
  }

포토스팟을 등록하는 부분에서 포토스팟에 포토를 등록하고 후 createImageKeyword를 호출한다

그렇다면 전달받은 이미지와 포토아이디를 가지고 라벨링 후 DB에 저장한다

이미 존재하는 키워드에 경우에는 중복되어 저장되는 걸 막기 위해서 preKeyword로 따로 지정하고

새로운 키워드의 경우 새로 만들어 저장 후 insertKeyword로 지정한다 그리고 각각 keyword 배열에 집어넣는다

포토아이디를 가지고 라벨링이 돼야 하는 해당 포토를 가져와 photoKeywords 컬럼을 keyword로 재할당 후 save를 시키는 방식으로 사진에 라벨링을 한다