【Rails】Cloud Vision APIを用いて画像解析し、過激な画像を検知する方法


目標

refileでユーザーのプロフィール画像を編集した場合、
アップロードする画像をCloud Vision APIで画像解析し、
過激な画像の場合はDBに保存出来なくする。

開発環境

・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina

前提

下記実装済み。

ログイン機能実装
投稿機能実装

Cloud Vision APIを有効化

1.下記記事の「Geocoding APIを有効化」と同様の手順で、Cloud Vision APIを有効化して下さい。

Geolocation APIを用いて緯度経度を算出する方法

2.ホーム画面に遷移し、IAMと管理をクリック

3.サービスアカウントをクリック

4.サービスアカウントを追加をクリック

5.サービスアカウント名(適当で良い)を入力し、作成をクリック

6.続行をクリック

7.キーを作成をクリック

8.キーのタイプをJSONに設定し、作成をクリック

9.キーが作成された事を確認し、閉じるをクリック

10.完了をクリック

11.キーをアプリケーション直下に移動

Cloud Vision APIの評価について

評価カテゴリー

カテゴリー 内容
adult アダルト画像かどうか
spoof インターネットミームかどうか
medical インターネットミームかどうか
violence 暴力的な画像かどうか
racy 際どい画像かどうか

評価値

評価値 度合い
UNKNOWN 解析不可
VERY_UNLIKELY 非常に低い
UNLIKELY 低い
POSSIBLE 可能性あり
LIKELY 高い
VERY_LIKELY 非常に高い

実装

1.Gemを導入

評価カテゴリーを問わず、評価値がLIKELY又はVERY_LIKELY
含む場合はDBに保存しない様に実装をしていきます。

Gemfile
gem 'google-cloud-vision'
ターミナル
$ bundle

2.Cloud Vision APIの設定ファイルを作成し、編集

ターミナル
$ touch lib/vision.rb
lib/vision.rb
require 'base64'
require 'json'
require 'net/https'
module Vision
  class << self
    def image_analysis(profile_image)
      image_annotator = Google::Cloud::Vision::ImageAnnotator.new(
          version: :v1,
          credentials: JSON.parse(File.open('キーのファイル名') do |f| f.read end)
      )

      # リクエストパラメータ作成
      image = profile_image # 解析させたい画像(引数)
      requests_content = { image: { content: image }, features: [{ type: :SAFE_SEARCH_DETECTION }] }
      requests =   [requests_content]

      # Cloud Vision APIに画像を送信
      response = image_annotator.batch_annotate_images(requests)
      result = response.responses[0].safe_search_annotation.to_h

      # 解析結果が「LIKELY」又は「VERY_LIKELY」を含む場合はfalse、それ以外はtrueを返す
      if result.values.include?(:LIKELY) || result.values.include?(:VERY_LIKELY)
        return false
      else
        return true
      end
    end
  end
end

3.コントローラーを編集

users_controller.rb
def update
  # 画像が編集された場合
  if params[:user][:profile_image].present?
    # パラメーター(画像)を「tempfile」として開いて変数に代入
    profile_image = File.open(params[:user][:profile_image].tempfile)
    # Cloud Vision APIで画像分析して、分析結果を変数に代入
    result = Vision.image_analysis(profile_image)
  else
    # 画像が編集されてない場合は「true」を代入
    result = true
  end
  # 解析結果によって条件分岐
  if result == true
    @user.update(user_params)
    redirect_to user_user_path(@user)
  elsif result == false
    flash[:notice] = '画像が不適切です'
    render 'edit'
  end
end