7
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Azure Functions + Azure AI Custom Visionで画像分類 API を構築してみた

Last updated at Posted at 2025-12-11

NTTテクノクロスの清水です。
この記事は、NTTテクノクロスアドベントカレンダーシリーズ1の12日目の記事になります。

業務でAzureを使う機会があり、大学時代には画像分類の研究をしていたため、これらを組み合わせてみよう!と思い執筆しました。

本記事では、Azure Functions + Azure AI Custom Visionを組み合わせて、画像分類APIを構築する方法を紹介します。

はじめに

1. Azure Functionsとは

Azure Functionsは、Microsoftが提供するサーバーレスコンピューティングサービスです。サーバーの管理が不要で、コードを書いて実行するだけで、自動的にスケーリングされます。

HTTP、Blob、Timer、Queueなど複数のトリガーに対応しており、Python、C#、JavaScriptなど複数の言語に対応しています。

本実装では、HTTP Triggerを使用して、HTTPリクエストで画像を受け取り、分類結果を返します。

2. Azure AI Custom Visionとは

Azure AI Custom Visionは、画像分類モデルを構築できるサービスです。機械学習の知識がなくても、ブラウザ上で画像をアップロードしてタグ付けするだけで、分類モデルが完成します。

本実装では、Custom Visionで犬と猫の分類モデルを作成し、Azure Functionsから呼び出します。

実装

1. 本実装の概要

本実装では、ユーザーが送信した画像をAzure Functionsで受け取り、Custom Visionで分類して、結果を返すAPIを構築します。以下が処理の流れです。

2. 実装環境

  • エディタ:Visual Studio Code (VSCode)
  • VSCode拡張機能
    • Azure Functions
    • Python
    • Japanese Language Pack for Visual Studio Code(お好みで)
  • azure-functions-core-tools:4.5.0
  • Python:3.11.9
  • データセットCat and Dog(kaggle)

3. Azure AI Custom Visionでのモデル作成

① Azureアカウントの作成

② リソースグループの作成

  • 作成したアカウントでAzureポータルにログインします。
  • ホームからリソースグループを選択します。
  • 左上の「作成」ボタンをクリックします。
  • 以下の設定でリソースグループを作成します。
項目 設定値
サブスクリプション 任意のサブスクリプション
リソースグループ名 任意のリソースグループ名
リージョン Japan East

③ Custom Visionリソースの作成

  • Azure Portalの検索窓から「Custom Vision」と検索し、表示されたサービスを開きます。
  • 表示されたが画面左上の「作成」ボタンをクリックします。
  • 以下の設定でリソースを作成します。
項目 設定値
作成オプション 両方
サブスクリプション リソースグループが所属するサブスクリプション
リソースグループ 作成したリソースグループ
リージョン Japan East
名前 任意のリソース名
トレーニング価格レベル Free F0
予測価格レベル Free F0

④ Custom Visionポータルでモデルの作成

  • Custom Visionポータルにアクセスして作成したAzureアカウントでサインインします。
  • 「NEW PROJECT」をクリックします。
    image.png
  • 以下の設定でプロジェクトを作成します。
項目 設定値
Name 任意のプロジェクト名
Resource 作成したリソース名
Project Types Classification
Classification types Multiclass
Domains General
  • 「Add images」をクリックして学習用画像をアップロードし、タグ付けします。今回は犬40枚、猫40枚の画像を学習に使用し、それぞれ「dog」「cat」とタグ付けしました。

  • アップロードした画像を学習させます。「Train」クリックして、今回は「Quick Training」を選択します。数分待っていると学習が完了します。

image.png

  • 画面左上の「Publish」をクリックしてモデルの公開をします。モデル名は任意で設定し、リソースは「{作成したリソース名}-Prediction」を選択してください。

image.png

  • 「Publish」の右にある「Prediction URL」をクリックします。今回はローカル上の画像を分類するので「If you have an image file:」のURLとKeyを取得して、メモなどに残しておきます。

image.png

4. Functionsプロジェクトの作成

  • 事前準備として、ローカル上にプロジェクトを作成するディレクトリを用意しておきます。また、今回の実装では、テスト用の画像をプロジェクト配下の「img」というディレクトリに配置しています。
  • VSCodeを開き、「フォルダを開く」を選択してプロジェクトを作成したいディレクトリを開きます。
  • "Ctrl + Shift + P" でコマンドパレットを開き、検索窓から「Azure Functions: Create New Project...」を検索して選択します。
  • プロジェクトを作成したいディレクトリを選択し、以下の設定でプロジェクトを作成します。
項目 設定値
言語 Python
Pythonのバージョン 3.11.9
テンプレート HTTP Trigger
関数名 任意の関数名
認可レベル Function
  • プロジェクト作成が完了すると、以下のようなディレクトリ構造でファイルが生成されます。
{任意のプロジェクト名}
│  .funcignore
│  function_app.py
│  host.json
│  local.settings.json
│  requirements.txt
│  .venv
│  .vscode    
├─img
   │  test_cat.jpg
ファイル/フォルダ 説明
function_app.py メインの関数定義ファイル
requirements.txt Pythonの依存パッケージを記載
local.settings.json ローカル実行時の設定ファイル

5. Pythonコードの実装とローカルでのテスト

①ライブラリのインストール

  • プロジェクト作成時に作られた「requirements.txt」を開き、外部API呼び出しとJSON処理に必要なライブラリ requests を追加します。追加した後、必ず保存するようにしてください。

※azure-functionsは最初から記述されています。

requirements.txt
azure-functions
requests
  • "Ctrl + @"でターミナルを開き、以下のコマンドを実行してライブラリをインストールします。
pip install -r requirements.txt

②Pythonコードの実装

  • プロジェクト作成時に作られた「function_app.py」を開きます。
  • 以下のコードを記述し、保存します。

プロジェクト作成時の関数名で関数が作成されるため、13,14行目の「image_classifier_api」の部分は「4. Functionsプロジェクトの作成」で設定した関数名に変更してください。

function_app.py
import azure.functions as func
import logging
import requests
import json
import os

# 接続情報は環境変数から取得
PREDICTION_KEY = os.environ.get('PREDICTION_KEY')
PREDICTION_URL = os.environ.get('PREDICTION_URL')

app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)

@app.route(route="image_classifier_api")
def image_classifier_api(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    try:
        # 1. リクエストボディから画像データを取得
        image_data = req.get_body()

        # 2. Custom Vision APIへのリクエストヘッダーを設定
        headers = {
            'Prediction-Key': PREDICTION_KEY,
            'Content-Type': 'application/octet-stream'
        }

        # 3. Custom Vision APIを呼び出し
        response = requests.post(PREDICTION_URL, headers=headers, data=image_data)
        response.raise_for_status() # 400, 500エラーなどを検出

        # 4. 結果をJSONで取得
        result_json = response.json()

        # 5. 結果をHTTPレスポンスとして返す
        return func.HttpResponse(
            json.dumps(result_json, indent=4, ensure_ascii=False), # ensure_ascii=Falseで日本語も対応
            mimetype="application/json",
            status_code=200
        )

    except ValueError:
        return func.HttpResponse(
             "リクエストボディに画像データがありません。",
             status_code=400
        )
    except requests.exceptions.HTTPError as err:
        logging.error(f"Custom Vision API呼び出しエラー: {err}")
        # Custom Vision APIからの具体的なエラーレスポンスをそのまま返す
        error_content = response.text if 'response' in locals() else "Unknown API Error"
        return func.HttpResponse(
             f"Custom Vision APIでエラーが発生しました。詳細: {error_content}",
             status_code=response.status_code if 'response' in locals() else 500
        )
    except Exception as e:
        logging.error(f"予期せぬエラー: {e}")
        return func.HttpResponse(
             "サーバー内部エラーが発生しました。",
             status_code=500
        )

③環境変数の設定

  • local.settings.jsonを開いて、環境変数を設定します。
local.settings.json
{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",  
    "PREDICTION_KEY": "【Custom Visionポータルから取得した予測キー】",        
    "PREDICTION_URL": "【Custom Visionポータルから取得した予測URL】",         
    "FUNCTIONS_WORKER_RUNTIME": "python"
  },
  "ConnectionStrings": {},
  "Host": {}
}

変数名 説明
AzureWebJobsStorage ローカル開発用のストレージ設定
PREDICTION_KEY Custom Vision APIの認証キー
PREDICTION_URL Custom Vision APIのエンドポイントURL
FUNCTIONS_WORKER_RUNTIME Python ランタイムの指定

④ローカルテスト

  • VSCodeのターミナルで以下のコマンドを実行し、ローカルサーバーを起動します。
func start
  • VSCodeで"Ctrl + Shift + @"で別のターミナルを開き、下記コマンドを実行します。
& curl.exe -X POST "http://localhost:7071/api/{作成した関数名 例:image_classifier_api}" `
  --header "Content-Type: application/octet-stream" `
  --data-binary "@{テスト画像のパス 例:img/test_cat.jpg}"
  • 下画像のように結果が出力されたらローカルでのテストが完了です。本例では猫の画像をテスト画像として分類しました。"tagName": "Cat" で "probability": 0.9999... となっているため、猫の確率が99.99%以上であり、正しく分類できていることが確認できます。
  • 実行後はFunc Startを実行したターミナルを開き、"CTRLC"で実行を停止してください。

6. Azure Functionsのリソース作成とデプロイ

①Azure Functionsのリソース作成

  • VSCode上の左のメニューからAzureマークをクリックします。
    image.png
  • 「RESOURCES > {自身のサブスクリプション名} > Function APPを右クリック > Create Function App in Azure...」の順に選択します。
  • コマンドパレットが出るので、下表の設定でリソースを作成します。数分待つとAzure上にリソースが作成されます。
項目 設定値
名前 任意の名前
ランタイム Python 3.11
リージョン Japan East
関数名 自身で設定した任意の関数名
認証タイプ secrets

②コードのデプロイ

作成したリソースにローカルのコードをデプロイします。

  • VSCode左下のWORKSPACE上にある「Local Project」にカーソルを合わせ、右側に出てくる雲マークを選択します。
  • 先ほど作成した Azure Functionsのリソース名を選択します。
  • 確認ダイアログが出たら「Deploy」をクリックします。
  • 少し待つとデプロイが完了します。

③環境変数の設定

デプロイ後、Functionsが Custom Vision API にアクセスできるように、クラウド側で環境変数を設定します。

  • Azure Portal上にアクセスし、作成したFunctionsのリソースを開きます。
  • 左側メニューから「設定 > 環境変数」を選択します。
  • 以下の2つの環境変数を設定します。
キー
PREDICTION_KEY Custom Visionポータルから取得した予測キー
PREDICTION_URL Custom Visionポータルから取得した予測URL

image.png

④関数URLの取得

  • Azure Portal上の左側メニューから「概要」をクリックします。
  • 画面下部の「関数」から自身で決定した関数名をクリックします。
  • 画面上部の「関数のURLの取得」をクリックし、表示された URL をコピーします。

3つのキーが表示されますが、default (ファンクション キー) のURLをコピーしてください。

image.png

7. クラウドでの動作確認

最後に、デプロイしたFunctionがクラウド上で正しく動作するか確認します。

  • PowerShellを開きます。

    VSCode上のターミナルでも、Windows PowerShellでも構いません。

  • 作成したプロジェクトのディレクトリに移動します。
  • 以下のコマンドを実行します。セクション6-④で取得した関数URLに置き換えてください。
& curl.exe -X POST "{6-④で取得した関数URL}" `
  --header "Content-Type: application/octet-stream" `
  --data-binary "@{テスト画像のパス 例:img/test_cat.jpg}"

本例では、テスト画像をプロジェクトの img フォルダ配下に配置しているため、プロジェクトのディレクトリに移動しています。テスト画像のパスは適宜環境に合わせて設定してください。

  • ローカルでテストしたときと同様の出力がされたら動作確認完了です!

感想と今後の展望

本記事では、Azure Functions + Azure AI Custom Visionを組み合わせて、画像分類APIを構築する方法を紹介しました。

実装を通じた感想

大学時代の研究では、画像分類モデルを構築するために、大量の学習データの収集・前処理、モデルの設計・パラメータチューニング、環境構築など、多くの時間と手間がかかっていました。

しかし、Azureのサービスを使うことで、数時間程度の短い時間で簡単に画像分類を行うことができました。クラウドサービスの進化により、機械学習がより身近で実用的になったことを実感しました。

今後の展望

本記事ではHTTP Triggerを使用して1枚の画像を処理していますが、Blob Triggerを使用することで、Azure Blob Storageにアップロードされた複数の画像を自動検出し、大量の画像を効率的に分類できるようになります。今後、Blob Triggerを用いた実装も行っていこうと考えています。


私の記事は以上となります。引き続き、NTTテクノクロス Advent Calendar 2025 をお楽しみください!

7
0
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
7
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?