🌭
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 /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
画像処理アプリの作成
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 /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 ["/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 ポータルでも関数の存在を確認できます。
動作確認
元画像。
input コンテナに元画像のファイルをアップロードします。
関数が動いているようです。
output コンテナの出力を確認します。
グレースケールに変換されました。
おわりに
コンテナを使って Azure Functions の Linux ホスト上で OpenCvSharp を動作させることができました。
参考
Discussion