Azure FunctionsでOpenCVSharpを利用した画像の加工を行おうとしたのですが、以下の点でうまく動作しませんでした。
最初の構成
OpenCV3.2 All-in-one package - bundles native OpenCV DLLs: .NET Framework wrapper for OpenCVを利用してx86またはx64でアプリケーションをビルドし、ローカル環境で正常に動作することを確認しました。
そこでAzureFunctionsへデプロイして実行したところ、以下の通りエラーが発生し動作しないことがわかりました。
Exception while executing function: IneiConvertFunction
Microsoft.Azure.WebJobs.Host.FunctionInvocationException : Exception while executing function: IneiConvertFunction ---> System.TypeInitializationException : The type initializer for 'OpenCvSharp.NativeMethods' threw an exception. ---> System.DllNotFoundException : Unable to load DLL 'OpenCvSharpExtern': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
at OpenCvSharp.NativeMethods.redirectError(CvErrorCallback errCallback,IntPtr userdata,IntPtr& prevUserdata)
at OpenCvSharp.NativeMethods.LoadLibraries(IEnumerable`1 additionalPaths)
at OpenCvSharp.NativeMethods..cctor()
End of inner exception
at OpenCvSharp.NativeMethods.imgcodecs_imread(String filename,Int32 flags)
at OpenCvSharp.Mat..ctor(String fileName,ImreadModes flags)
at ReportFunctions.IneiConvertUtils.IneiConverter.Convert(String filePath)
at ReportFunctions.IneiConvertFunction.Run(Stream ineiFileBlob,String name,TraceWriter log)
at lambda_method(Closure ,IneiConvertFunction ,Object[] )
at Microsoft.Azure.WebJobs.Host.Executors.VoidMethodInvoker`2.InvokeAsync(TReflected instance,Object[] arguments)
at async Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`2.InvokeAsync[TReflected,TReturnValue](Object instance,Object[] arguments)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.InvokeAsync(IFunctionInvoker invoker,ParameterHelper parameterHelper,CancellationTokenSource timeoutTokenSource,CancellationTokenSource functionCancellationTokenSource,Boolean throwOnTimeout,TimeSpan timerInterval,IFunctionInstance instance)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at async Microsoft.Azur…
この時点ではデプロイする時に何かファイルが不足しているなどが原因かと思っていました。KuduのDebug Consoleでデプロイされたファイルなどを比較してみたのですが、特に不足しているファイルなどは見当たりませんでした。
とりあえず何か足りないらしい…
さて、とりあえずこの段階でAzureFunctionsの利用をやめてVMにでも環境を構築してお茶を濁そうかとも思ったのですが、せっかくここまで作ったのでもうちょっと調べてみようと思いました。
とりあえずデプロイされているファイルの一式は特に変わりないのでアプリケーションの実行環境に差異があるのではと思い、OpenCVShapの動作環境を確認しました。
shimat/opencvsharp: .NET Framework wrapper for OpenCV
OpenCV 3.2
Visual C++ 2015 Redistributable Package
.NET Framework 2.0 or later / .NET Core / Mono
とりあえず、NuGetパッケージを利用しているのでOpenCV本体については考える必要はなさそうでした。またKuduのDebug Consoleでインストールされている.NET Frameworkのバージョンを確認しましたが以下の通り問題ないことがわかりました。
D:\home>dotnet --version
2.0.3
ということで、3つの前提条件の打ち2つは問題ないことがわかったのですが、最後のVisual C++ 2015 Redistributable Package
をどのように確認するかです。
Visual C++ 2015 Redistributable Package
はインストールされていない
ここからはGoogleでいろいろなキーワードで検索する以外にい方法が思いつきませんでした。そう、私はC++での開発経験はないのでこの辺はさっぱりわからないからです(´ω`)
とはいえ、10分位アレヤコレヤと調べたところ以下のサイトに辿り着きました。
Visual C++ Redistributable Packages for Visual Studio Azure App Service – benjamin perkins
Azure Functionsは Azure App Serviceで動作しているので多分同じようにすれば調べられるだろうと思い早速試してみることにしました。
// Visual C++ Redistributable Packages for Visual Studio 2015
// x64
D:\home>reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Dependencies\{d992c12e-cab2-426f-bde3-fb8c53950b0d} "
ERROR: The system was unable to find the specified registry key or value.
// x86
D:\home>reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Dependencies\{e2803110-78b3-4664-a479-3611a381656a}"
ERROR:
The system was unable to find the specified registry key or value.
// Visual C++ Redistributable Packages for Visual Studio 2013
// x64
D:\home>reg query "HKLM\SOFTWARE\Classes\Installer\Dependencies\{050d4fc8-5d48-4b8f-8972-47c82c46020f}"
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Dependencies\{050d4fc8-5d48-4b8f-8972-47c82c46020f}
(Default) REG_SZ {050d4fc8-5d48-4b8f-8972-47c82c46020f}
Version REG_SZ 12.0.30501.0
DisplayName REG_SZ Microsoft Visual C++ 2013 Redistributable (x64) - 12.0.30501
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Dependencies\{050d4fc8-5d48-4b8f-8972-47c82c46020f}\Dependents
// x86
D:\home>reg query "HKLM\SOFTWARE\Classes\Installer\Dependencies\{f65db027-aff3-4070-886a-0d87064aabb1}"
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Dependencies\{f65db027-aff3-4070-886a-0d87064aabb1}
(Default) REG_SZ {f65db027-aff3-4070-886a-0d87064aabb1}
Version REG_SZ 12.0.30501.0
DisplayName REG_SZ Microsoft Visual C++ 2013 Redistributable (x86) - 12.0.30501
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Dependencies\{f65db027-aff3-4070-886a-0d87064aabb1}\Dependents
どうやらVisual C++ Redistributable Packages for Visual Studio 2015
についてはインストールされておらずVisual C++ Redistributable Packages for Visual Studio 2013
であればインストールされているようです。
OpenCVSharp2.4を利用する
ここまででとりあえず現状のままだとOpenCVSharp3をAzure Functionsで動作させるのは無理そうだということになります。いや、ひょっとしたらVisual C++ Redistributable Packages for Visual Studio 2015
をインストールするような方法があるのかもしれませんが、ちょっとわかりませんでした。
そこで、Visual C++ Redistributable Packages for Visual Studio 2013
で動作するOpenCVSharpのバージョンを確認したところ2.4.10
であれば動作することがわかりました。
shimat/opencvsharp_2410: .NET Framework wrapper for OpenCV 2.4.10
OpenCV 2.4.10
Visual C++ 2013 Redistributable Package
.NET Framework 2.0 or later / Mono
これまで作っていたものを少し修正する必要がありますが、環境面ではこのバージョンで動作させることができそうだということがわかりました。
最終的に…
最終的にOpenCVSharp2.4.10を利用してAzure FunctionsでOpenCVを利用した画像加工処理を実装することができました。やりたいことが非常に単純なことで、Azure Storage のBlobContainerにファイルがアップロードされたら処理をしたいというだけだったので、この方法は最適でした。
Azure Functionsについては昨日始めて触ったのですが、一日位で一つの処理を動かすことができて満足しています。責務が明確な小さな処理は積極的に利用していこうかなと思いました。