自作の物体検出アプリをもうすこし速くできないか?
Windows用の物体検出アプリをリリースしてしばらく経ちました。
モデルも当初の正方形から入力画像形状に近い長方形へ変更し、処理速度を大きく改善することができました。
また学習データも少しずつ増やして、検出精度自体も当初よりも向上していると考えています。
今後更に処理速度をあげるにはどのようなアプローチができるだろう?
物体検出をした後、OpenCVで検出個所を矩形描画を行っています。
OpenCVは動的リンクとなるworld.dllを利用しています。
これを静的リンクにしたらどの程度改善するのだろう?
どこかで、静的リンクと動的リンクで大きな差はない、とちらっと見ましたが、もしかすると意外と効果があるかもしれない!
ということで、やってみました。
静的libがなかったのでOpenCVのビルドから
環境
OpenCV 4.11
Windows 11 Pro 24H2
VisualStudio 2022 17.14.3
CPU intel 11400F
OpenCVの静的ライブラリを使いた時のCMakeでのビルド
わたしが良く分かっていなかったのですが、静的ライブラリを利用したい場合には、CMake GuiではBUILD_SHARED_LIBSのチェックを外してGenerateする必要があります。
これが分かっておらず数回くらいビルドしました

テストコード
Windows Copilotに作ってもらいました。
矩形描画を100000回繰り返してもらい、かかった時間を計測してもらいます。
#include <opencv2/opencv.hpp>
#include <chrono>
#include <iostream>
#include <cstdlib>
int main(int argc, char** argv)
{
// デフォルトは 100000 回、コマンドライン引数で回数を指定可能(例:100000)
int iterCount = 100000;
if (argc > 1)
{
iterCount = std::atoi(argv[1]);
}
std::cout << "Iteration count: " << iterCount << std::endl;
// 640x480 の黒画像を作成
cv::Mat image(480, 640, CV_8UC3, cv::Scalar(0, 0, 0));
// テスト対象:矩形描画のパラメータ
cv::Point pt1(50, 50);
cv::Point pt2(300, 300);
cv::Scalar color(0, 255, 0); // 緑色
int thickness = 2;
// ウォームアップ(初回呼び出しによるオーバーヘッドの影響を抑える)
cv::rectangle(image, pt1, pt2, color, thickness);
// 時間計測開始
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < iterCount; ++i)
{
// 同じ画像に矩形を描画(オーバーライドされるため最終結果は同じですが、処理は実施される)
cv::rectangle(image, pt1, pt2, color, thickness);
}
auto end = std::chrono::high_resolution_clock::now();
// 計測結果(ミリ秒単位)
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
std::cout << "Total time for " << iterCount << " iterations: " << duration.count() << " ms" << std::endl;
// 最適化によってループが削除されないよう、簡単なチェックを実施
cv::Scalar sumVal = cv::sum(image);
std::cout << "Checksum: "
<< sumVal[0] << ", "
<< sumVal[1] << ", "
<< sumVal[2] << std::endl;
return 0;
}
- 静的リンクの時、プロジェクトのプロパティ > リンカー > 追加の依存ファイルに、次を設定しました
ippiw.lib;zlib.lib;ippicvmt.lib;opencv_core4110.lib;opencv_imgproc4110.lib - 動的リンクの時、プロジェクトのプロパティ > リンカー > 追加の依存ファイルに、次を設定しています
opencv_world4110.lib;
実行結果
Iteration count: 100000
Total time for 100000 iterations: 905 ms
Checksum: 0, 763980, 0
何回か実行してみましたが、900~950くらいの間という感じでした。
Iteration count: 100000
Total time for 100000 iterations: 1052 ms
Checksum: 0, 763980, 0
何回か実行してみましたが、1000~1050くらいの間という感じでした。
考察と感想
静的リンクは手間がかかる割には、そこまで変わらない、という印象。
DLLで全然問題ない感じがします。
今回は評価できていませんが、静的リンクはビルドに時間がかかるらしいので、やっぱりDLLの方が簡単でいいかなと感じました。
本件は以前からなんとなく気になっていたことで、結果的には見聞きしていた通りでしたが、実際に自分で試してみてやっぱり似たような結果を得られた、というのは良かったです。
実際に自分でやってみて納得でき、良かったです。

