はじめに
OpenCV は画像処理ライブラリです
簡単に画像加工が行え、画像データを行列(numpy array)として扱えるため、機械学習でもよく使います
バージョン 3.3 からは DNN (Deep Neural Network) モジュールが追加され、
OpenCV で機械学習モデルを使った推論が実行できるようになりました
readNetFromDarknet や readNetFromTensorflow などによって、
他の機械学習ライブラリで学習したモデルを読み込んで使うことがきます
エラー内容
先日、以下の記事でやったのと同じように、Docker コンテナで AWS の Lambda 関数を作っていた時のこと
今回は Darknet で学習したモデルを OpenCV で動かそうとしていました
以下のようなコードでロードするようにしていました
self._net = cv2.dnn.readNetFromDarknet(cfg_path, weights_path)
しかし、デプロイした Lambda 関数を実行すると、以下のようなエラーが返ってきました
error: OpenCV(4.6.0) /io/opencv/modules/dnn/src/darknet/darknet_importer.cpp:210: error: (-212:Parsing error) Failed to open NetParameter file: xxx.cfg in function 'readNetFromDarknet'
調査
とりあえず、エラーメッセージで検索すると OpenCV の GitHub Issue が引っ掛かりました
読んでいくと、エラーの原因はどちらかのようです
-
.cfg
ファイルのパスが間違っている -
.cfg
ファイルが破損している
ローカルで動作することは確認済なので、 .cfg
ファイルは問題ないはずです
パスも確認しましたが、何回確認しても間違っていません
Docker で配置した場所に確かにファイルは存在しているし、パスの指定も一字一句相違ありません
ローカルの Docker 上で動かしてもエラーは発生しません
エラーになるのは Lambda で実行したときだけです
一体なぜ、、、?
原因
勘の良い方、 Lambda に詳しい方はすでに原因がわかったと思いますが、、、
原因確認のため、コードで当該パスに ls -al
をかけると、、、
-rw------- 1 root root 8347 Jul 7 02:44 xxx.cfg
-rw------- 1 root root 246326928 Jul 7 02:48 xxx.weights
はい、所有者(root)には rx
で読み書きの権限が与えられていますが、
それ以外には一切権限がありません
Lambda 関数では、 root ではない特別なユーザー sbx_userNNNN
が使用されます
そのため、 root にしか権限のないファイルを読み込めなかったわけです
ローカル実行では所有者=自分だったためエラーが発生せず、
ローカルの Docker では root ユーザーで実行していたためにエラーが発生しませんでした
解決方法
確実にコンテナ内で権限を与えたいので、 Dockerfile に以下の一文を加えます
RUN chmod -R +r <.cfg や .wrights の配置されたディレクトリー>
-R
でディレクトリー配下のすべてのファイルを対象として、 +r
で全員に読み取り権限を与えています
おわりに
権限不足という超基本中の基本が原因でした
エラーメッセージに Permission denied
くらい出してほしいけど、、、
結論として、 OpenCV で Failed to open NetParameter
エラーが出た場合は、
以下の点を確認してください
- ファイルのパスは正しいか = 指定した場所にファイルがあるか
- ファイルの権限は正しいか = 実行ユーザーに読み取り権限があるか
- ファイルは破損していないか = ファイルの形式、内容が正しいか