Amazon Web Services ブログ

生成AIで外観検査をやってみた

1. はじめに

製造業における品質管理は非常に重要な課題です。製品の外観や組立状態を確認し、欠陥の有無を判断する外観検査工程は、高い品質を維持するうえで欠かせません。この検査工程を人手に頼らず自動化できれば、コスト削減と品質の安定化が期待できるため、さまざまな検査工程の自動化が試みられています。今でも外観検査のソリューションとしてAWSではAmazon Lookout for Visionというサービスを提供していますが、今回は違う切り口から、Amazon Titan Multimodal Embeddings G1を使って生成AIで同じような外観検査ができるかトライしてみました。

Embedding方式の利点は、製品カテゴリーを問わず同じ数値化モデルを活用できる点にあります。サンプル画像の数値化自体は製品に依存しないので、一度、数値化の仕組みを構築すれば、様々な製品に汎用的に適用可能となります。こうした柔軟性と効率性が、Amazon Lookout for Visionとは異なる特長となっています。また、このような汎用化により、AWSサービスに比べてコストを抑えられる可能性があります。さらに、既に外観検査モデルを持っている場合には、Embeddingを使ってモデルの改良を容易に行えるというメリットがあります。Embedding方式とLookout for Visionはそれぞれ長所があり、用途に応じた使い分けが重要です。

2. 検査画像について

今回は外観検査のサンプルとして、下記のような ガラス瓶の口の部分を極端にクローズアップして撮影したものを使ってみたいと思います。下記のように良品であれば、透明なガラス瓶の中心部を同心円状の輪郭が取り囲んでいるような形状になります。

一方で不良品の画像は、下記のようにビンの淵に汚れがある場合や(よく見ないとわかりづらいですが今回は透明なテープを貼っています)、ビンの中に何かが混入してしまっていたりといった、いくつかパターンを用意してみました。

3. 判定ロジックの作成

3-1 学習データの準備

冒頭でも記載しましたが、今回は生成AIに2023年の11月にAmazon Bedrockで一般提供開始となったAmazon Titan Multimodal Embeddings G1モデルを利用します。
手順としてはシンプルで、まず初めにAmazon Titan Multimodal Embeddings G1を使って良品画像からEmbeddingを取得します。Embeddingとは、画像データをベクトル表現=数値化することを指していて、画像の視覚的な特徴が圧縮されてベクトル化されます。今回は、画像を数値化するのにAmazon Titan Multimodal Embeddings G1を使って、分類自体はk近傍法(k-Nearest Neighbors)という別の手法を用います。

画像のEmbeddingは同じカテゴリーの画像は近いベクトル値になり、異なるカテゴリーの画像は離れたベクトル値になる性質があります。分類に利用する、k近傍法(k-Nearest Neighbors)は、 未知のデータ点に対して学習データ中の最近傍k個のデータ点の多数決により分類を行います。今回は良品画像・不良品画像のそれぞれのクラスを作成し、当該クラス分類に近いかどうかで良品・不良品を判定します。 Embeddingによって同じカテゴリーの画像が近接するよう写像されていれば、k近傍法による良品/不良品の判別が有効に機能すると期待できます。
さらに、この手法の利点は、モデル作成のハードルと、計算コストが比較的低いうえ、小規模データであれば高速に判定できるところにあります。一方で大規模データでは計算コストが高くなる懸念がありますが、他の手法と柔軟に連携しやすいという点もあり、状況に合わせて最適な手法を組み合わせられることで、 より高い判別性能を発揮できます。

それでは、実際にAmazon Titan Multimodal Embeddings G1を使って画像のEmbeddingを取得していきます。コードの一部を抜粋するとこのようになります。
出力のベクトルサイズは1,024 (デフォルト)、384、256から選択できますが、今回はより低次元の256次元にしてみました。

for i in range(start_num, end_num+1):

    file_path = os.path.join(f'{file_prefix}{i}.jpg')

    with open(file_path, "rb") as image_file:   
        input_image = base64.b64encode(image_file.read()).decode("utf8")
            
        body = json.dumps(
            {"inputText": "xxx", 
            "inputImage": input_image,
            "embeddingConfig": {
            "outputEmbeddingLength": 256
            }
                })

        response = bedrock_runtime.invoke_model(
              body=body,
              modelId="amazon.titan-embed-image-v1",
              accept="application/json",
              contentType="application/json",
              )

        response_body = json.loads(response.get("body").read())
        embedding = response_body.get("embedding")
        embedding_list_normal.append(embedding)

こちらを実行すると、このような下記の画像1枚につき、このようなベクトル表現を特徴量として得ることができます。
最初の検証では、良品画像40枚、不良品画像40枚、合計80枚分繰り返します。

[0.040440526, -0.030406332, 0.019856136, -0.03709767, -0.027063366, 0.0038649105, -0.02639588, -0.014976015, 0.010845318, -0.041676126, -0.00282769, -0.0050448384,
(中略)
0.05363304, -0.0126655055, -0.054597393, 0.0004961308, -0.04483083, 0.013465457,0.025360549, -0.0052477336, 0.057870768, 0.045011103, -0.013245691, -0.076108955, -0.025926728, 0.0072124046, -0.13566567, -0.016753113]

3-2 モデルの作成

次にk近傍法(k-Nearest Neighbors)を使って良品画像と不良品画像の学習モデルを作っていきます。コードはこのようになります。embedding_listには、先ほど出力した良品画像+不良品画像の合計80枚の画像のEmbeddingのリストが入っており、Yは正解ラベルのリストになります。

X= np.array(embedding_list)
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X, Y)

なお、この合計80枚の画像から抽出されたEmbeddingが、うまくクラス分類できているのかt-SNEという手法を使って256次元を2次元まで削減しグラフにプロットしてみたいとおもいます。 t-SNEは高次元データを低次元に視覚化する手法で、緑色の点が良品を赤色の点が不良品を表しています。グラフを見ると、概して良品と不良品がある程度分離されている傾向が見られます。

この傾向を見ても今回のサンプル画像を使ったEmbeddingによるクラス分類は、ある程度うまくいきそうだということが視覚的にもわかると思います。このようにして、良品画像および不良品画像のクラス分類が完成しました。

4. テストデータの準備

それでは、テスト画像を40枚ほど用意します。このテスト画像には、良品と不良品の画像が混ざった形で入っています。
今回は20枚の画像は良品、もう20枚は不良品という構成にしてみました。不良品の画像は異物の混入や、淵の汚れなど複数のパターンを用意します。
この合計40枚のテスト画像のEmbeddingを先ほどの手順で出力しておきます。

■良品画像の例

■不良品画像の例

それでは、先ほど訓練した良品画像の学習データとの距離を計算していきます。コードはこのようになり、良品画像のクラスに対して距離が近ければ近いほど=良品画像と近い特徴を持ち、その逆は=不良品画像の特徴を持ちます。

X_new = np.array([i]) #テスト画像
y_pred = knn.predict(X_new) #良品・不良品判定

5. 検証結果

これらの40枚のテスト画像に対して、以下のような結果が出ました。 良品→不良品と判定したケースは4件ありました。
それぞれ、Accuracy(正解率):90%、Precision(適合率):100%、Recall(再現率):80%、F値:0.889となっています。 正解率とは、全体に対する正しい判定の割合です。 適合率(Precision)が100%ということは、良品と判定されたものは全て実際の良品だったことを意味します。 一方で、再現率(Recall)が80%ということは、実際の良品の80%が良品と判定できていたことになります。なお、F値という指標があります。これは0から1の値をとり、1に近いほど識別がうまくできていることを示します。 実際の製造現場では、製品の安全性と品質を最優先し、偽陰性(不良品を良品と誤判定)を防ぐことが重視されます。今回のモデルでは、ある程度の偽陽性はありましたが、不良品は100%判定でき製品の安全性と品質を守る観点では良好な結果だと言えます。

また、今回はある程度の精度が出ましたが、実際に良好な結果が得られない場合は、学習データの質や量を変えてみることで、さらなる精度向上が図れる可能性があるかもしれません。今回のケースでも学習データを半分の40枚に減らして、不良品としてパターンの多い画像を増やしたところ、正解率が95%まで向上しました。他にも、信頼度を見て評価用データから閾値を決めて、良品と不良品の境界をより詳細に設定していく方法も考えられます。

なお、冒頭に記載したように今回のプログラムを使って今回の仕組みを汎用化できるか、他のデータセットを使って検証してみたところ、環境や条件にもよりますが正解率が95%となり高い精度が出すことができました。

まとめ

今回、Amazon Titan Multimodal Embeddings G1を活用した簡易的な外観検査を実施してみました。今回作成したモデルは、ある程度の偽陽性はありましたが、不良品は100%判定でき製品の安全性と品質を守る観点では良好な結果が得られたのではないかと思います。 本手法のポイントは、画像をAmazon Titan Multimodal Embeddings G1を利用してEmbeddingして数値化したことです。これにより、画像のタスクを数値データのアルゴリズムに落とし込むことができるようになりました。画像を数値化することで、これまでのさまざまな機械学習の手法を活用した分類が可能になります。
ただし、この方法は、今回のケースような固定された既知のサンプルに対しては比較的高い精度が期待できますが、環境条件や撮影状況が常に変化する場合には精度が低下する可能性があります。すべてのケースに万能に適用できるわけではなく、実運用時には検査対象物や環境の違いによって、結果がある程度異なる可能性があることに留意が必要です。

さらに、今回は不良品画像が十分にあるケースを考えてみましたが、必ずしも不良品画像が十分にない場合もあると思います。 その際には、生成AIに不良品かどうか直接質問したり、不足するデータを人工的に生成してモデル学習をするといったアプローチも検討できるかもしれません。このように、生成AIによる外観検査の実用化に向けては、様々な工夫の余地が残されています。本試行が、その第一歩として、生成AIの活用可能性を示す有意義な機会となれば幸いです。


著者について

test秦 将之
アマゾン ウェブ サービス ジャパン合同会社
シニアソリューションアーキテクト

製造業界のお客様向けに技術支援を担当しています。好きなサービスはAmazon SageMakerとAmazon Bedrockです。週末はジムで体力づくりしています。