良薬口に苦し

情報系出身の僕が毎日更新を目標にタメにならないこと、なること、ならないことを投稿。その横で毎日(は終了しました)誰かの誕生日をお祝いしてるかも。ライトノベル(青ブタとよう実)やヴァイスシュヴァルツについて浅く広く書いています。

PythonでのGoogle Cloud Vision API (safe_search_annotation) を利用方法①【10月5日】

Google Cloud Vision APIを利用して行ったエロ画像識別のPythonで書いたプログラムについて紹介します。今回はrequestを使っていない方式なのでerrorが出にくいと思います。申請方法や実行結果などは以下の記事を参考にしてください。

ryoyaku.hatenablog.com

ryoyaku.hatenablog.com

準備

  • Googleアカウント(APIが利用できる)
  • Google Cloud Platformにプロジェクトが有ること
  • Python3.7(Python3系でなら動くと思いますが、必要ならアップデートしてください)
  • ダウンロードしたjsonファイル
  • 画像

コード

少し修正しました

# -*- coding:utf-8 -*-

#各種インポート
import io 
import os
import glob
import shutil
import json

from google.protobuf.json_format import MessageToJson
from google.cloud import vision
from google.cloud.vision import types

#作業用ディレクトリ
base_dir = 'sample/'

#JSONファイルのファイル名
credential_path = Your_json_file_name

#サービスアカウントキーへのパスを通す
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = credential_path

#visionクライアントの初期化
client = vision.ImageAnnotatorClient()

#対象となる画像のファイル名
file_dir = base_dir
files = glob.glob(file_dir + "**/*[jpg|png]",recursive=True)

#作業用ディレクトリに以下のディレクトリを作成
id_dir_name = ['Non/','Very_NotH/','NotH/','Possible/','H/','VeryH/']
for id in id_dir_name:
    if id =='Non/':
        continue
    #ディレクトリを一度消去
    #shutil.rmtree(base_dir + id)
    os.makedirs(base_dir + id , exist_ok=True)

#画像読み込み識別
for file in files:
    with io.open(file, 'rb') as image_file:
        content = image_file.read()
        image = types.Image(content=content)
        response = client.safe_search_detection(image=image)
        annotation = response.safe_search_annotation
        file_name = file[len(os.path.dirname(file)):]
        try:
            
            if annotation.adult == 1:#Very_NotH
                shutil.copy(file,base_dir + id_dir_name[1] + file_name)
            
            if annotation.adult == 2:#NotH
                shutil.copy(file,base_dir + id_dir_name[2] + file_name)
            
            if annotation.adult == 3:#Possible
                shutil.copy(file,base_dir + id_dir_name[3] + file_name)
            
            if annotation.adult == 4:#H
                shutil.copy(file,base_dir + id_dir_name[4] + file_name)

            if annotation.adult == 5:#Very_H
                shutil.copy(file,base_dir + id_dir_name[5] + file_name)
        except:
            continue
    

僕のコードを使うなら、作業用ディレクトリ内にある画像を全て読み込んでくれます。複数の画像に対して処理したいためglob.glob()を利用しています。これはディレクトリ内の()を満たすファイルを検索し、リストアップしてくれます。

なおjsonファイルについては、APIの申請を通したときにダウンロード(なければ再ダウンロード)した自分のを利用してください。また。importできないものは pip install するなどしてください。 pip install google-cloudpip install google-cloud-vision はすることになると思います。

f:id:yoyr_3501:20201004172335p:plain
image dirの例

今回鍵となるのはresponse = client.safe_search_detection(image=image)の部分です。reaponseの中身を見ると以下のようになります。

safe_search_annotation {
  adult: LIKELY
  spoof: VERY_UNLIKELY
  medical: VERY_UNLIKELY
  violence: VERY_UNLIKELY
  racy: VERY_LIKELY
}

ここでsafe_search_detection(image=image)について説明すると、adult(性的か)の他にspoof(コラ画像か)、medical(医療的か)、violence(暴力的か)、racy(性的内容を示唆しいるかどうか)の5つの要素から結果を返してくれます。これら5つの要素を5段階評価[VERY_UNLIKELY,UNLIKERY,POSSIBLE,LIKELY,VERY_LIKERY]で判定します。僕も調べるまでわからなかったんですけど、racyっていうのにそういう意味があったんですね...racyは「性的」ではないものの、性的内容を示唆しているかどうかということらしいです。これに関しては今後違いとかを見ていきたいと思います。気になる人は是非自分で調べてみてください。

プログラムの中身に戻りますが、safe_search_annotationの中の今回はadult要素を利用したいので、まずは中身を取ってくるため、annotation = response.safe_search_annotationとしています。

annotationの中身は

adult: UNLIKELY
spoof: VERY_UNLIKELY
medical: UNLIKELY
violence: VERY_UNLIKELY
racy: POSSIBLE

となります。annotationの中のadult観点5段階評価はannotation.adultで得られます。ただしannotation.adult[VERY_UNLIKELY,UNLIKERY,POSSIBLE,LIKELY,VERY_LIKERY]ではなく[1,2,3,4,5]となっています。

そのため

      try:
            if annotation.adult == 5:#VeryH
                shutil.copy(file,base_dir + Id_dir_name[0] + file[len(file_dir+dir_name):])
            
            if annotation.adult == 4:#H
                shutil.copy(file,base_dir + Id_dir_name[1] + file[len(file_dir+dir_name):])
            
            if annotation.adult == 3:#Possible
                shutil.copy(file,base_dir + Id_dir_name[2] + file[len(file_dir+dir_name):])
            
            if annotation.adult == 2:#NotH
                shutil.copy(file,base_dir + Id_dir_name[3] + file[len(file_dir+dir_name):])

            if annotation.adult == 1:#Very_NotH
                shutil.copy(file,base_dir + Id_dir_name[4] + file[len(file_dir+dir_name):])
        except:
            continue

このようなな書き方となっています。今回は自分の用意した画像を分類、分類した先に元のファイルをコピー(shutil.copy())をしています。

以上となります。

f:id:yoyr_3501:20200929194103j:plain
五等分の花嫁【公式】

jsonファイルの名前はconfig.pyなどを利用して管理したりすると楽かもしれませんね。実際、僕もjsonファイルの名前はconfig.pyのCloud_Vision_jsonとしています。また、ディレクトリ操作は自分のやりやすい形にしてください。例えば、['VeryH/','H/','Possible/','NotH/','Very_NotH/']内に、「ことり」、「真姫」とディレクトリを生成していくなど。

VisionAPIの他の要素などについても気が向いたら書いていきます。

ryoyaku.hatenablog.com

ryoyaku.hatenablog.com

余談ですが今日は虹ヶ咲学園スクールアイドル同好会の10人(11人)目のメンバー三船栞子さんの誕生日です。
㊗おめでとうございます㊗

f:id:yoyr_3501:20201005180147p:plain
スクスタ誕生日バナー

半年くらい前からスクスタやってなかったので、正直栞子さんのことあんまりしらないんですよね。ネットの情報くらいは追ってたので、最初のような出だしなわけですけど...そんな僕ですが、虹アニメに感動してしまいました。

アニメの画が今までとタッチが違い、より日常らしかったく、ちょっと太ましかったのが僕好みでした。そしてライブシーン、こちらは打って変わって「進化」を感じました。演出はかっこよく、可愛く、キレイで久しぶりに鳥肌がたちました。神か?これはもう神化なのか?個人的にはμ’sという単語が出てこなかったのが良かったと思いました。

虹ちゃんたちには虹ちゃんとして虹ちゃんらしくトキメキを見つけていって欲しいです。

掲載している各画像は、著作権法32条に基づいて引用しております。
画像の著作権は権利者様に帰属しています。
権利者様から削除のご依頼があった場合、速やかに対処いたします。