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

##GitHubに公開しました

https://github.com/electronicsdiy/DALL-E_Python3_Script

##つくったもの

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

https://huggingface.co/transformers/model_doc/clip.html

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

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

https://note.com/npaka/n/n74a9b172b41d

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

####__（ ラベル名：　１つだけ指定 ）__

>```bash:Terminal
>% python3 display_textlabelprob_on_image.py --image_file xxx.jpg 'cat'
>```

####__（ ラベル名：　複数指定 ）__


>```bash: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*__という名前で登録します（他の名前でも可能）
 
```bash:Terminal
> % alias clip='python3 display_textlabelprob_on_image.py'
```

__（ エイリアス実行 ）__


```bash: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から資源を取得

```bash:Terminal
% git clone 
```

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

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


####画像ファイルを用意

```bash:Terminal
DALL-E_Python3_Script % ls
README.md				doraemon.jpg
display_textlabelprob_on_image.py	nozomi.jpg
DALL-E_Python3_Script %
```

#####（ 画像１ ）

- 画像は、取り扱いたい任意の画像ファイルを用意してください。
 
```bash:Terminal
DALL-E_Python3_Script % ls doraemon.jpg                                                          
doraemon.jpg
DALL-E_Python3_Script % open doraemon.jpg 
```

![](https://user-images.githubusercontent.com/87643752/130586549-beb07952-24ae-418c-beab-1c14ca611e87.png)

#####（ 画像２ ）

- 画像は、取り扱いたい任意の画像ファイルを用意してください。


```bash:Terminal
DALL-E_Python3_Script % open nozomi.jpg 
```

![](https://user-images.githubusercontent.com/87643752/130586573-035a2380-acdb-4385-9cd1-bec76ee705e9.png)


####スクリプトを実行 （ ドラえもん画像 ）

- コマンドライン引数：第１引数に、画像ファイルを相対パスで渡す
- コマンドライン引数：第２引数以降に、１つ以上のラベルを文字列で与える

```bash: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 %
```

```bash: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 %
```

####スクリプトを実行 （ 佐々木希の画像 ）

```bash: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 %
```

```bash: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 %
```

```bash: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 %
```

##エイリアスでコマンド化

最後に、エイリアスでコマンド化します。
 
```bash:Terminal
% alias clip='python3 display_textlabelprob_on_image.py'
```

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

- ラベル名：１つ

```bash:Terminal
DALL-E_Python3_Script % clip --image_file doraemon.jpg 'cat'      
次の画像を解析します。：　 doraemon.jpg
次のラベルの該当確率を推定します。　：　 ['cat']
ラベル名： cat   該当確率： 100.0%
DALL-E_Python3_Script % 
```

- ラベル名：２つ

```bash: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 %
```

- ラベル名：３つ以上

```bash: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 %
```

##感情分析：感情を表すラベルを渡す

```bash: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 %
```

```bash: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コマンド

```bash: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 %
```

```bash: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を叩いています。

>```Python3:
> from transformers import CLIPProcessor, CLIPModel
>```

https://huggingface.co/transformers/model_doc/clip.html

```Python3: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()
```