LoginSignup
2
2

More than 1 year has passed since last update.

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

Last updated at Posted at 2021-08-24

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()
2
2
0

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
  3. You can use dark theme
What you can do with signing up
2
2