2011-12-07 7 views
5

OpenCVバイナリイメージのすべての白いピクセルを数えようとしています。OpenCVバイナリイメージの「白」ピクセルをカウントする(効率的に)

whitePixels = 0; 
    for (int i = 0; i < height; ++i) 
    for (int j = 0; j < width; ++j) 
     if (binary.at<int>(i, j) != 0) 
     ++whitePixels; 

をしかし、私は、これはコードの非常に遅い部分、およびプログラムの大きなボトルネックであることを発見しましたgprofのでプロファイリングした後、次のように私の現在のコードがあります。

同じ値をより速く計算できる方法はありますか?

+0

高さと幅を変更してみましたか?私は幅と高さにループを意味する?これは、イメージがどのようにメモリにレイアウトされるかによって、ループを改善することができます。 –

+2

このat()関数ではなく、直接画像データにアクセスできますか? – jrok

+0

ジョークとして示唆を与えることはおそらくより速くなるでしょう。 [このFAQエントリ](http://opencv.willowgarage.com/wiki/faq#How_to_access_image_pixels)が適切かどうかは疑問です。 – Brian

答えて

20

cvCountNonZero。通常、タスクのOpenCV実装は大幅に最適化されています。

行の最後のピクセルは、通常、次の行の最初のピクセルが続く
+3

@karlphillipあなたは['cv :: countNonZero']を意味します(http://opencv.willowgarage.com/documentation/cpp/core_operations_on_arrays.html#cv-countnonzero)? –

+0

完璧な、最適化された組み込み関数。ちょうど私が探していたもの。 –

+0

現在のdocリンクを回答に追加しました(このコメントとは異なり、今後更新される可能性があります)。 – handle

0

パラレルコンピューティングを使用できます。 N個の部分でイメージを分割し、異なるスレッドでコードを実行すると、各スレッドの結果が得られます。その後、最終的な量を得るためにこの結果を追加することができます。

+1

Billのアルゴリズムは、正しく実装されていれば、CPUにバインドされているのではなく、メモリにバインドされているはずです。通常のデスクトップコンピュータでは、通常、並列化はメモリに依存するタスクには役に立ちません。 – Brian

-2

(Cコード):

limit=width*height; 
i=0; 
while (i<limit) 
{ 
    if (binary.at<int>(0,i) != 0) ++whitePixels; 
    ++i; 
} 
+0

または、インデックスを削除するスライディングポインタとして実装します。 –

+0

そして/または[i]と[i + 1]で同時に2つずつテストし、インデックス/ポインタに2を加えます。これにより、必要なループが半分になります。 –

+0

連続性テストは、isContinuous()を使用する前に行列に対して行う必要があります。行列が連続していない場合、このメソッドは失敗します。 –

-2

実際binary.at<int>(i, j)遅いアクセスであります!

ここでは、自分よりも高速にアクセスできる簡単なコードです。

for (int i = 0; i < height; ++i) 
{ 
uchar * pixel = image.ptr<uchar>(i); 
    for (int j = 0; j < width; ++j) 
{ 
    if(pixel[j]!=0) 
    { 
     //do your job 
    } 
} 
} 
関連する問題