cv::gpu::countNonZero
をgpu::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;