AmazonRekognitionで投稿画像の安全性をチェックする


# はじめに
先日、LLMへの入力プロンプトから事前に悪意のあるコンテンツや個人情報を含むコンテンツを検知・除去する手段として[Amazon Comprehendを紹介しました。](https://qiita.com/kanuazut/items/c3dbb6868732c9ce55e8)
詳細は記事を確認頂ければと思いますが、Amazon Comprehendでは日本語テキスト内の違法・暴力的な内容や個人情報を検知することがある程度可能という結果でした。

一方で、最近ではマルチモーダルなLLMがAWSをはじめとするクラウドサービスで利用可能になっており、LLMに対する画像の入力も増えてきています。
そこで本記事では、画像認識のAIサービスであるAmazon Rekognitionを利用して、画像内の暴力的・性的等の不適切コンテンツを検知する機能を試し、プロンプトから除去することができるか試してみます。




# Amazon Rekognitionとは
Amazon Rekognitionは、AWSの画像/ビデオ認識のサービスで機械学習の知識なしで高度な機能を利用できるサービスです。顔やオブジェクトの検出、テキストの読み取り、安全でないコンテンツの判別など、さまざまな機能を提供し、顔認識APIを使用することでユーザー認証や人数のカウントなどにも応用可能です。
今回は、このうちの不適切コンテンツ検出を利用してみます。

## コンテンツのモデレーション
不適切コンテンツの検出には、Amazon Rekognitionのコンテンツモデレーション機能を利用します。


Amazon Rekognitionでは、入力画像に対して検出した不適切コンテンツのカテゴリラベルを出力します。ラベルは3層の階層カテゴリになっています。
検出されるラベルは一つではなくマルチラベルなため、ビジネス要件に応じて「差別表現は除去しアルコールは許可する」などの用途にも利用可能です。

以下表に最上位レベル(レイヤ1)と第2レベル(レイヤ2)のカテゴリまでを整理しておきます。L3になるほどより細分化されたカテゴリになります。
| レイヤ1                                                                               | レイヤ2                                                       | 
| ------------------------------------------------------------------------------------- | ------------------------------------------------------------- | 
| 露出(Explicit)                                                                        | 露出ヌード(Explicit Nudity)                                   | 
|                                                                                       | 性行為(Explicit Sexual Activity)                              | 
|                                                                                       | 性玩具(Sex Toys)                                              | 
| 非露出のデリケートゾーンおよびキス(Non-Explicit Nudity of Intimate parts and Kissing) | 非露出ヌード(Non-Explicit Nudity)                             | 
|                                                                                       | 隠されたデリケートゾーン(Obstructed Intimate Parts)           | 
|                                                                                       | 唇のキス(Kissing on the Lips)                                 | 
| 水着および下着(Swimwear or Underwear)                                                 | 女性用水着・下着(Female Swimwear or Underwear)                | 
|                                                                                       | 男性用水着・下着(Female Swimwear or Underwear)                | 
| 暴力(Violence)                                                                        | 武器(Weapons)                                                 | 
|                                                                                       | 暴力表現(Graphic Violence)                                    | 
| 視覚的不快(Visually Disturbing)                                                       | 死と衰弱(Death and Emaciation)                                | 
|                                                                                       | 事故(Crashes)                                                 | 
| 薬物&煙草(Drugs & Tobacco)                                                            | 製品(Products)                                                | 
|                                                                                       | 麻薬とタバコの道具と使用(Drugs & Tobacco Paraphernalia & Use) | 
| アルコール(Alcohol)                                                                   | 飲酒(Alcohol Use)                                             | 
|                                                                                       | アルコール飲料(Alcoholic Beverages)                           | 
| ジェスチャー(Rude Gestures)                                                           | 中指(Middle Finger)                                           | 
| ギャンブル(Gambling)                                                                  | N/A                                                           | 
| ヘイト・シンボル(Hate Symbols)                                                        | ナチ(Nazi Party)                                              | 
|                                                                                       | 白人至上主義(White Supremacy)                                 | 
|                                                                                       | 過激派(Extremist)                                             | 

以上のように、暴力的・性的・違法性のあるコンテンツなどはおおよそ検出可能となっています。
より詳細なL3カテゴリと説明は、[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/rekognition/latest/dg/moderation.html)を参照ください。

<br>

### 動作確認

##### 実行環境
今回は、Python SDKのboto3からAmazon Rekognitionを利用します。
動作確認は以下の環境で実行しています。
Python: 3.11.3
boto3: 1.34.66

なおAWSマネジメントコンソールからも利用可能なので、簡易な確認であればまずはそちらから試すとよいでしょう。

##### 初期化
boto3のclientを初期化しておきます。
以降の動作確認では、以下のコードが実行済みであることを前提としています。

```python
import boto3
client = boto3.client(
    'rekognition', 
    region_name="",
    aws_access_key_id="",
    aws_secret_access_key="")
```
リージョンとキーは適宜設定します。今回リージョンは`us-east-1`で試しました。

#### モデレーションのラベル付け
Rekognitionへのリクエストは非常に簡単です。
boto3 clientの`detect_moderation_labels`を利用したサンプルコードを以下に記載します。

```python: モデレーション検出のリクエスト
import base64
file_path = "./gun.jpg"
with open(file_path, "rb") as image:
    img = image.read()# bsae64エンコードした画像。5MBまで。
    
response = client.detect_moderation_labels(
    Image={'Bytes': img},
    MinConfidence=50
    )
print(response["ModerationLabels"])
```
`Image` は、検出対象の画像データを指定しています。
ローカルの画像データを利用するときは上記のように `Bytes`フィールドを指定して、base64の画像データを使います。
公式ドキュメントのサンプルなどでは、`Image={'S3Object':{'Bucket':bucket,'Name':photo}}`とS3バケットから直接参照させているようです

`MinConfidence` は、最小信頼レベルです。
各検出ラベルの信頼度がここで設定した値以下だった場合は結果に出力されません。指定しなかった場合は`50`になります。

ちなみにここで指定している画像は以下です。
![gun.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3115707/c700c4c1-54f8-db86-3ec9-938c0d001e6c.jpeg)
[画像引用元](https://www.photo-ac.com/main/detail/29063718&title=%E9%9B%BB%E5%8B%95%E3%82%AC%E3%83%B3D1)

<br>

出力結果は以下の通りです。

```json: 出力
[{"Confidence": 99.89450073242188,
  "Name": "Weapons",
  "ParentName": "Violence",
  "TaxonomyLevel": 2},
 {"Confidence": 99.89450073242188,
  "Name": "Violence",
  "ParentName": "",
  "TaxonomyLevel": 1}]
```
ラベルは2つ出力されています。
Level1の`Vilolence`とLevel2の`Weapons`のラベルです。
`Weapons`は親カテゴリが`Violence`であるという階層構造も分かるようになっていますね。
`Confidence`が100に近いのでほぼ確実に武器であるという予測ができています。

というわけで、非常に簡単に画像の不適切コンテンツの検出を行うことが出来ました。


<br>

### サンプル
手順は分かったのでいくつか画像を入れてを試してみます。

##### ビールの写真

入力画像：
![beer.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3115707/40d14887-fece-13f7-731d-2e6543869cf2.jpeg)
[画像引用元](https://www.pakutaso.com/20110428117post-42.html)


```json: 出力
[{"Confidence": 99.0602035522461,
  "Name": "Alcoholic Beverages",
  "ParentName": "Alcohol",
  "TaxonomyLevel": 2},
 {"Confidence": 99.0602035522461,
  "Name": "Alcohol",
  "ParentName": "",
  "TaxonomyLevel": 1}]
```

スコア99で、`Alcoholic Beverages`と認識できていますね。
このくらいの画角であれば全く問題なさそうです。



##### ハイボールのイラスト

次はイラストでも出来るか試してみます。

入力画像：
![A5B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3115707/ab13e230-ff5e-53fb-1368-1ccf6917b802.png)
[画像引用元](https://ctlg.asahibeer.co.jp/shop/pages/productssearchkeyvisual.aspx)

```json: 出力

[{"Confidence": 99.03900146484375,
  "Name": "Alcoholic Beverages",
  "ParentName": "Alcohol",
  "TaxonomyLevel": 2},
 {"Confidence": 99.03900146484375,
  "Name": "Alcohol",
  "ParentName": "",
  "TaxonomyLevel": 1}]
```

全く問題なく`Alcoholic Beverages`が検出できています。




##### 交通事故の画像

入力画像：
![accident.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3115707/e8a57bad-271d-c11b-f9b4-d26df574d933.jpeg)
[画像引用元](https://www.photo-ac.com/main/detail/29259188&title=%E4%BA%A4%E9%80%9A%E4%BA%8B%E6%95%85%E3%80%80%E8%BB%8A%E3%81%AE%E8%A1%9D%E7%AA%81%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E7%B4%A0%E6%9D%90)


```json: 出力
[]
```

こちらの交通事故のおもちゃ再現画像では、MinConfidenceを`1`まで下げても検出はありませんでした。
ちなみにMinConfidenceを`0`に指定すると強制的にすべてのラベルのConfidenceが出力されるようです。


##### タバコの画像
続いてタバコも見てみます。

入力画像：
![ciga.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3115707/a9353b6c-083a-c92b-27ed-2e2ea0fe34bf.jpeg)
[画像引用元](https://www.photo-ac.com/main/detail/29250192&title=%E5%96%AB%E7%85%9912)

```
[{'Confidence': 97.81539916992188,
  'Name': 'Pills',
  'ParentName': 'Products',
  'TaxonomyLevel': 3},
 {'Confidence': 97.81539916992188,
  'Name': 'Products',
  'ParentName': 'Drugs & Tobacco',
  'TaxonomyLevel': 2},
 {'Confidence': 97.81539916992188,
  'Name': 'Drugs & Tobacco',
  'ParentName': '',
  'TaxonomyLevel': 1}]
```

こちらも高いConfidenceで`Drugs & Tobacco`, `Products`が検出できています。


##### 棒状のお菓子の画像
ではタバコに似たお菓子はどうでしょうか。

入力画像：
![cocoa2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3115707/a3bf67b6-aaf4-785b-2c01-e7c1e1553a3c.jpeg)
[画像引用元](https://orionstar.co.jp/archives/products/%E3%82%B3%E3%82%B3%E3%82%A2%E3%82%B7%E3%82%AC%E3%83%AC%E3%83%83%E3%83%88)


```json: 出力
[{"Confidence": 3.9402999877929688,
  "Name": "Weapons",
  "ParentName": "Violence",
  "TaxonomyLevel": 2},
 {"Confidence": 3.9402999877929688,
  "Name": "Violence",
  "ParentName": "",
  "TaxonomyLevel": 1},
 {"Confidence": 1.4924999475479126,
  "Name": "Pills",
  "ParentName": "Products",
  "TaxonomyLevel": 3},
 {"Confidence": 1.4924999475479126,
  "Name": "Products",
  "ParentName": "Drugs & Tobacco",
  "TaxonomyLevel": 2},
 {"Confidence": 1.4924999475479126,
  "Name": "Drugs & Tobacco",
  "ParentName": "",
  "TaxonomyLevel": 1}]
```

今回はConfidenceが`4`を超えるものはありませんでした。
`Drugs & Tobacco"`はConfidence 1.49で検出されていますが、最大100のうちのこの数字なのでほぼ未検出といっていいでしょう。


##### その他
他にも暴力的、性的なものが検知可能か画像・イラストともに確かめてみました。
が、ここに掲載すると怒られそうなのでサンプルの明示は避けておきます。

試した感じでは、性的表現に関してはかなり精度高く検出ができるようでした。
一方で暴力表現については、スプラッターな映画のカバー写真などを入れてみても検出する場合とそうでない場合があるようです。
とくに武器や人体が写っておらず、血汚れのみが見られる場合には`Violence`の検出確度が低くなるような印象でした。このあたりはそもそもそれが暴力表現なのかという定義的な問題もある気がするので、精度というよりは仕様・傾向という理解に近いかもしれません。


# おわりに
コンテンツモデレーション第2弾ということで、今回は画像のモデレーションをAmazon Rekognitionで試してみました。
記事の中では、あまりきわどい画像例を出すことはできませんでしたが、画像でもイラストでも優秀な検出性能だと感じました。
完全に抜け漏れなく検出することは難しいとは思いますが、お手軽に画像のコンテンツチェックする方法としては頼れるサービスだと思います。