LoginSignup
2

More than 1 year has passed since last update.

posted at

updated at

OpenAIのCLIPをTerminalコマンド化した

GitHubに公開しました

つくったもの

CLIPはOpenAIから公開されたツールで、画像ファイルと(1つ以上の)単語を入力すると、画像が各単語に該当する確率を、(指定した単語の数だけ)数値で表現してくれるものです。

あらかじめモデル学習させた単語でない未知の単語も扱えます。
これは、One-shot learningという技術が裏側で活躍しています。

CLIPに、画像ファイルと(1つ以上の)単語を与えて動かすとき、多くの行数のコードを打ち込む必要があります。

そこで今回、Terminalで次の1行を叩いてエンターキーを押すだけで、CLIPを動かせるようにしました。CLIPの処理結果は、Terminal(標準出力)に表示されます。

( ラベル名: 1つだけ指定 )

Terminal
% python3 display_textlabelprob_on_image.py --image_file xxx.jpg 'cat'

( ラベル名: 複数指定 )

Terminal
% python3 display_textlabelprob_on_image.py --image_file xxx.jpg 'cat' 'dog' 'egg'

引数に渡すラベルを、'happy', 'angry', 'suprising', 'exciting', 'disappointing', 'disgusted', ...などと、感情や面持ちを表す単語にすることで、画像に映る被写体の感情分析を行うこともできそうです。

コマンド化の総仕上げ

この記事の最後で、python3 display_textlabelprob_on_image.pyの部分をaliasで、任意のコマンド名に置き換えて動かしてみます。

( エイリアス登録 )

  • clipという名前で登録します(他の名前でも可能)
Terminal
> % alias clip='python3 display_textlabelprob_on_image.py'

( エイリアス実行 )

Terminal
DALL-E_Python3_Script % clip --image_file doraemon.jpg 'cat' 'dog' 'banana' 'car' 'vehicle'
次の画像を解析します。:  doraemon.jpg
次のラベルの該当確率を推定します。 :  ['cat', 'dog', 'banana', 'car', 'vehicle']
ラベル名: cat   該当確率: 54.0%
ラベル名: dog   該当確率: 5.0%
ラベル名: banana   該当確率: 3.0%
ラベル名: car   該当確率: 31.0%
ラベル名: vehicle   該当確率: 7.000000000000001
DALL-E_Python3_Script %

使い方

GitHubから資源を取得

Terminal
% git clone 

取得したディレクトリに移動

Terminal
% cd DALL-E_Python3_Script
DALL-E_Python3_Script % ls
README.md               display_textlabelprob_on_image.py
DALL-E_Python3_Script % 

画像ファイルを用意

Terminal
DALL-E_Python3_Script % ls
README.md               doraemon.jpg
display_textlabelprob_on_image.py   nozomi.jpg
DALL-E_Python3_Script %
( 画像1 )
  • 画像は、取り扱いたい任意の画像ファイルを用意してください。
Terminal
DALL-E_Python3_Script % ls doraemon.jpg                                                          
doraemon.jpg
DALL-E_Python3_Script % open doraemon.jpg 

( 画像2 )
  • 画像は、取り扱いたい任意の画像ファイルを用意してください。
Terminal
DALL-E_Python3_Script % open nozomi.jpg 

スクリプトを実行 ( ドラえもん画像 )

  • コマンドライン引数:第1引数に、画像ファイルを相対パスで渡す
  • コマンドライン引数:第2引数以降に、1つ以上のラベルを文字列で与える
Terminal
DALL-E_Python3_Script % python3 display_textlabelprob_on_image.py --image_file doraemon.jpg 'cat' 'dog'
次の画像を解析します。:  doraemon.jpg
次のラベルの該当確率を推定します。 :  ['cat', 'dog']
ラベル名: cat   該当確率: 91.0%
ラベル名: dog   該当確率: 9.0%
DALL-E_Python3_Script %
Terminal
DALL-E_Python3_Script % python3 display_textlabelprob_on_image.py --image_file doraemon.jpg 'cat' 'dog' 'human' 'pig' '
raccoon dog' 'house' 'robot' 'sky'
次の画像を解析します。:  doraemon.jpg
次のラベルの該当確率を推定します。 :  ['cat', 'dog', 'human', 'pig', '\nraccoon dog', 'house', 'robot', 'sky']
ラベル名: cat   該当確率: 52.0%
ラベル名: dog   該当確率: 5.0%
ラベル名: human   該当確率: 14.000000000000002%
ラベル名: pig   該当確率: 3.0%
ラベル名: 
raccoon dog   該当確率: 1.0%
ラベル名: house   該当確率: 1.0%
ラベル名: robot   該当確率: 18.0%
DALL-E_Python3_Script %

スクリプトを実行 ( 佐々木希の画像 )

Terminal
DALL-E_Python3_Script % python3 display_textlabelprob_on_image.py --image_file nozomi.jpg 'cat' 'dog' 'human' 'woman' 'girl'
次の画像を解析します。:  nozomi.jpg
次のラベルの該当確率を推定します。 :  ['cat', 'dog', 'human', 'woman', 'girl']
ラベル名: cat   該当確率: 0.0%
ラベル名: dog   該当確率: 0.0%
ラベル名: human   該当確率: 4.0%
ラベル名: woman   該当確率: 48.0%
ラベル名: girl   該当確率: 48.0%
DALL-E_Python3_Script %
Terminal
DALL-E_Python3_Script % python3 display_textlabelprob_on_image.py --image_file nozomi.jpg 'cute' 'beautiful' 'elegant' 'awful' 'boyish' 'big' 'small'       
次の画像を解析します。:  nozomi.jpg
次のラベルの該当確率を推定します。 :  ['cute', 'beautiful', 'elegant', 'awful', 'boyish', 'big', 'small']
ラベル名: cute   該当確率: 15.0%
ラベル名: beautiful   該当確率: 19.0%
ラベル名: elegant   該当確率: 61.0%
ラベル名: awful   該当確率: 0.0%
ラベル名: boyish   該当確率: 1.0%
ラベル名: big   該当確率: 1.0%
ラベル名: small   該当確率: 4.0%
DALL-E_Python3_Script %
Terminal
DALL-E_Python3_Script %python3 display_textlabelprob_on_image.py --image_file nozomi.jpg 'cute' 'awful' 'boyish' 'big' 'small'          
次の画像を解析します。:  nozomi.jpg
次のラベルの該当確率を推定します。 :  ['cute', 'awful', 'boyish', 'big', 'small']
ラベル名: cute   該当確率: 72.0%
ラベル名: awful   該当確率: 1.0%
ラベル名: boyish   該当確率: 6.0%
ラベル名: big   該当確率: 3.0%
ラベル名: small   該当確率: 18.0%
DALL-E_Python3_Script %

エイリアスでコマンド化

最後に、エイリアスでコマンド化します。

Terminal
% alias clip='python3 display_textlabelprob_on_image.py'

コマンドに、引数を渡して実行します。

  • ラベル名:1つ
Terminal
DALL-E_Python3_Script % clip --image_file doraemon.jpg 'cat'      
次の画像を解析します。:  doraemon.jpg
次のラベルの該当確率を推定します。 :  ['cat']
ラベル名: cat   該当確率: 100.0%
DALL-E_Python3_Script % 
  • ラベル名:2つ
Terminal
DALL-E_Python3_Script % clip --image_file doraemon.jpg 'cat' 'dog'
次の画像を解析します。:  doraemon.jpg
次のラベルの該当確率を推定します。 :  ['cat', 'dog']
ラベル名: cat   該当確率: 91.0%
ラベル名: dog   該当確率: 9.0%
DALL-E_Python3_Script %
  • ラベル名:3つ以上
Terminal
DALL-E_Python3_Script % clip --image_file doraemon.jpg 'cat' 'dog' 'banana' 'car' 'vehicle'
次の画像を解析します。:  doraemon.jpg
次のラベルの該当確率を推定します。 :  ['cat', 'dog', 'banana', 'car', 'vehicle']
ラベル名: cat   該当確率: 54.0%
ラベル名: dog   該当確率: 5.0%
ラベル名: banana   該当確率: 3.0%
ラベル名: car   該当確率: 31.0%
ラベル名: vehicle   該当確率: 7.000000000000001
DALL-E_Python3_Script %

感情分析:感情を表すラベルを渡す

Terminal
DALL-E_Python3_Script % python3 display_textlabelprob_on_image.py --image_file doraemon.jpg 'happy' 'angry' 'suprising' 'exciting' 'disappointing' 'disgusted' 
次の画像を解析します。:  doraemon.jpg
次のラベルの該当確率を推定します。 :  ['happy', 'angry', 'suprising', 'exciting', 'disappointing', 'disgusted']
ラベル名: happy   該当確率: 22.0%
ラベル名: angry   該当確率: 67.0%
ラベル名: suprising   該当確率: 10.0%
ラベル名: exciting   該当確率: 1.0%
ラベル名: disappointing   該当確率: 1.0%
ラベル名: disgusted   該当確率: 0.0%
DALL-E_Python3_Script %
Terminal
DALL-E_Python3_Script % python3 display_textlabelprob_on_image.py --image_file nozomi.jpg 'happy' 'angry' 'suprising' 'exciting' 'disappointing' 'disgusted'
次の画像を解析します。:  nozomi.jpg
次のラベルの該当確率を推定します。 :  ['happy', 'angry', 'suprising', 'exciting', 'disappointing', 'disgusted']
ラベル名: happy   該当確率: 63.0%
ラベル名: angry   該当確率: 12.0%
ラベル名: suprising   該当確率: 24.0%
ラベル名: exciting   該当確率: 1.0%
ラベル名: disappointing   該当確率: 0.0%
ラベル名: disgusted   該当確率: 0.0%
DALL-E_Python3_Script %

clipコマンド

Terminal
DALL-E_Python3_Script % clip --image_file doraemon.jpg 'happy' 'angry' 'suprising' 'exciting' 'disappointing' 'disgusted'  
次の画像を解析します。:  doraemon.jpg
次のラベルの該当確率を推定します。 :  ['happy', 'angry', 'suprising', 'exciting', 'disappointing', 'disgusted']
ラベル名: happy   該当確率: 22.0%
ラベル名: angry   該当確率: 67.0%
ラベル名: suprising   該当確率: 10.0%
ラベル名: exciting   該当確率: 1.0%
ラベル名: disappointing   該当確率: 1.0%
ラベル名: disgusted   該当確率: 0.0%
DALL-E_Python3_Script %
Terminal
DALL-E_Python3_Script % clip --image_file nozomi.jpg 'happy' 'angry' 'suprising' 'exciting' 'disappointing' 'disgusted'    
次の画像を解析します。:  nozomi.jpg
次のラベルの該当確率を推定します。 :  ['happy', 'angry', 'suprising', 'exciting', 'disappointing', 'disgusted']
ラベル名: happy   該当確率: 63.0%
ラベル名: angry   該当確率: 12.0%
ラベル名: suprising   該当確率: 24.0%
ラベル名: exciting   該当確率: 1.0%
ラベル名: disappointing   該当確率: 0.0%
ラベル名: disgusted   該当確率: 0.0%
DALL-E_Python3_Script %

ソースコード

裏側では、Huggingface版のDALL-Eを叩いています。

from transformers import CLIPProcessor, CLIPModel

display_textlabelprob_on_image.py
import argparse
from PIL import Image
import requests
from transformers import CLIPProcessor, CLIPModel
from pprint import pprint

parser = argparse.ArgumentParser(description='')    #
parser.add_argument('--image_file')
parser.add_argument('args', nargs=argparse.REMAINDER)
args = parser.parse_args()
image_file = args.image_file
token_list = args.args

def get_textlabel_prob_on_image(text_label_list, image_file):
    model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
    processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")
    image = Image.open(image_file)
    inputs = processor(text=text_label_list, images=image, return_tensors="pt", padding=True)
    outputs = model(**inputs)
    logits_per_image = outputs.logits_per_image
    probs = logits_per_image.softmax(dim=1)

    return probs

def main():     
    prob_list = get_textlabel_prob_on_image(token_list , image_file)
    #prob_list = get_textlabel_prob_on_image(["cat", "dog"], "doraemon.jpg")
    print("次の画像を解析します。: ", image_file)
    print("次のラベルの該当確率を推定します。 : ", token_list)
    #print(prob_list.tolist())
    tmp_double_list = prob_list.tolist() # 結果は二重リスト
    probability_list = tmp_double_list[0]
    probability_list = [round(prob, 2) for prob in probability_list]
    #print(probability_list)
    output_list = ["ラベル名: {label}   該当確率: {prob}".format(label=label,  prob=str(prob*100)+"%") for label, prob  in zip(token_list, probability_list)]  
    for label_prob_str in output_list:
        print(label_prob_str)

if __name__ == "__main__":
    main()

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
2