物理の駅 Physics station by 現役研究者

テクノロジーは共有されてこそ栄える

OpenCVのgpu::countNonZeroをgpu::Streamで高速化する

cv::gpu::countNonZerogpu::Streamで高速化したいという需要があったので、その解決策を書いておく。

opencvの2系のcountNonZeroはstreamを使うことが出来ない。そのため、非同期処理を行い高速化する際のボトルネックになる。cv::gpu::reduceは2次元画像を1次元に射影するための関数でstreamが使えるので、CV_REDUCE_SUMを使って射影した後、軽量化された1次元画像を非同期ダウンロードし、CPUで積算処理を行えばよい。行または列の合計値が255を超えた場合は完全に一致しないものの、ラフな値で良い場合はこの方法が適切である。

以下はサンプルコードでは、コアの部分だけ記述した。streamやgvec等を使いまわさないと初期化に時間がかかるので注意が必要。

cv::gpu::GpuMat gmat = cv::gpu::GpuMat(cv::Size(1920, 1080), CV_8UC1);
cout << cv::gpu::countNonZero(gmat) << endl; //streamが使えない

cv::gpu::GpuMat gvec;
cv::gpu::Stream stream;
cv::gpu::reduce(gmat, gvec, 1, CV_REDUCE_SUM, -1, stream); //行ごとに積算する場合
cv::Mat vec;
stream.enqueueDownload(gvec, vec);
cout << cv::sum(vec)[0] << endl;