OpenCvSharp を Azure Functions の Linux コンテナで動かす


はじめに

.NET の画像処理ライブラリである OpenCvSharp を Azure Functions の Linux ホストで動かします。
Windows ホストでは問題なく動作する OpenCvSharp ですが、Linux ホストではライブラリが不足している為、コンテナを使う必要があります。

サンプルアプリ

Blob トリガーで画像をグレースケールに変換する関数を作成します。

using System;
using System.IO;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using OpenCvSharp;

namespace opencvsharp_app_docker
{
    public class OpenCvSharpApp
    {
        [FunctionName("Grayscale")]
        public static void Run(
            [BlobTrigger("input/{name}", Connection = "")] Stream myBlob,
            string name,
            [Blob("output/{name}", FileAccess.Write)] Stream outBlob,
            ILogger log)
        {
            log.LogInformation($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");


            using (var mat = Mat.FromStream(myBlob, ImreadModes.Color))
            {
                log.LogInformation($"Height: {mat.Height}, Width: {mat.Width}");

                using (var grayMat = mat.CvtColor(ColorConversionCodes.BGR2GRAY))
                {
                    grayMat.WriteToStream(outBlob);

                    log.LogInformation($"Converted.");
                }
            }
        }
    }
}

Azure Functions 用 OpenCvSharp コンテナイメージの作成

公式リポジトリ.NET 6 用 Dockerfile を利用します。

Blob トリガーで動かすため、Final Image を Azure Functions のコンテナイメージに変更します。


...

########## Final image ##########

FROM mcr.microsoft.com/azure-functions/dotnet:4 as final
COPY --from=builder /usr/lib /usr/lib

イメージを作成してコンテナレジストリにプッシュします。

docker build . -t tkeydll/opencvsharp-docker:4.5.3-azure-functions-dotnet6
docker push tkeydll/opencvsharp-docker:4.5.3-azure-functions-dotnet6

https://hub.docker.com/layers/opencvsharp-docker/tkeydll/opencvsharp-docker/4.5.3-azure-functions-dotnet6/images/sha256-5b1296804cbff88c69539fe0f81ed54157b3feeea0551a5d60a7fac77b72c23e?context=repo

画像処理アプリの作成

Docker サポートを有効にして Function App を作成します。

func init --worker-runtime dotnet --docker
func new --name OpenCvSharpApp --template "BLOB trigger"

OpenCvSharp パッケージをインストールし、ビルドできることを確認します。

dotnet add package opencvsharp4
dotnet build

Dockerfile のランタイムイメージを、先に作成した OpenCvSharp が入った Azure Functions のイメージに変更します。

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS installer-env

# Build requires 3.1 SDK
COPY --from=mcr.microsoft.com/dotnet/core/sdk:3.1 /usr/share/dotnet /usr/share/dotnet

COPY . /src/dotnet-function-app
RUN cd /src/dotnet-function-app && \
    mkdir -p /home/site/wwwroot && \
    dotnet publish *.csproj --output /home/site/wwwroot

# To enable ssh & remote debugging on app service change the base image to the one below
# FROM mcr.microsoft.com/azure-functions/dotnet:4-appservice
# FROM mcr.microsoft.com/azure-functions/dotnet:4
FROM tkeydll/opencvsharp-docker:4.5.3-azure-functions-dotnet6
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    AzureFunctionsJobHost__Logging__Console__IsEnabled=true

COPY --from=installer-env ["/home/site/wwwroot", "/home/site/wwwroot"]

イメージを作成してプッシュします。

docker build . -t tkeydll/opencvsharp-app-docker:azure-functions
docker push tkeydll/opencvsharp-app-docker:azure-functions

デプロイ

アプリのコンテナイメージを指定して、Azure Functions をデプロイします。

# リソースグループ作成
az group create --name opencvsharp-docker --location japaneast

# ストレージアカウント作成
az storage account create --name opencvsharpdocker0403 --location japaneast --resource-group opencvsharp-docker --sku Standard_LRS

# App Service plan 作成
az functionapp plan create --resource-group opencvsharp-docker --name opencvsharp-docker-plan --location japaneast --number-of-workers 1 --sku B1 --is-linux

# Function App 作成
az functionapp create --name opencvsharp-app-docker --storage-account opencvsharpdocker0403 --resource-group opencvsharp-docker --plan opencvsharp-docker-plan --deployment-container-image-name tkeydll/opencvsharp-app-docker:azure-functions

# Blob 接続文字列の設定
$connectionstring = (az storage account show-connection-string --resource-group opencvsharp-docker --name opencvsharpdocker0403 --query connectionString --output tsv)
az functionapp config appsettings set --name opencvsharp-app-docker --resource-group opencvsharp-docker --settings AzureWebJobsStorage=$connectionstring

# Blob コンテナ作成
az storage container create -n input --resource-group opencvsharp-docker --account-name opencvsharpdocker0403
az storage container create -n output --resource-group opencvsharp-docker --account-name opencvsharpdocker0403

デプロイが終わると、Azure ポータルでも関数の存在を確認できます。

動作確認

元画像。


https://en.wikipedia.org/wiki/File:Lenna_(test_image).png

input コンテナに元画像のファイルをアップロードします。

関数が動いているようです。

output コンテナの出力を確認します。

グレースケールに変換されました。

おわりに

コンテナを使って Azure Functions の Linux ホスト上で OpenCvSharp を動作させることができました。

参考

https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-create-function-linux-custom-image?tabs=in-process%2Cbash%2Cazure-cli&pivots=programming-language-csharp