23

OpenCV を使用して、ビデオ ストリーム内の赤いピクセルのしきい値を設定しようとしています。他の色も問題なく機能していますが、赤は色相軸を包み込むため問題を引き起こします (つまり、HSV(0, 255, 255) と HSV(179, 255, 255) は両方とも赤です)。私が現在使用している手法は理想的とは言えません。基本的:

cvInRangeS(src, cvScalar(0, 135, 135), cvScalar(20, 255, 255), dstA);
cvInRangeS(src, cvScalar(159, 135, 135), cvScalar(179, 255, 255), dstB);
cvOr(dstA, dstB, dst);

青の簡単なケースと比較すると、赤 (潜在的なバグ) のコードの分岐、2 つの余分な画像の割り当て、および 2 つの追加の操作が必要になるため、これは最適ではありません。

cvInRangeS(src, cvScalar(100, 135, 135), cvScalar(140, 255, 255), dst);

私が思いついたより良い代替案は、画像の色を「回転」して、ターゲットの色相が 90 度になるようにすることでした。例えば。

int rotation = 90 - 179; // 179 = red
cvAddS(src, cvScalar(rotation, 0, 0), dst1);
cvInRangeS(dst1, cvScalar(70, 135, 135), cvScalar(110, 255, 255), dst);

これにより、すべての色を同じように扱うことができます。

ただし、cvAddS色相値が 0 を下回った場合、この操作では色相値が 180 に戻されないため、データが失われます。CvMat画像から減算し、モジュラスを使用して負の値を範囲の一番上にラップできるように画像を変換することを検討しましたが、CvMatモジュラスをサポートしていないようです。もちろん、すべてのピクセルを反復処理することもできますが、非常に遅くなることが懸念されます。


私は多くのチュートリアルとコードサンプルを読みましたが、それらはすべて、色相スペクトルをラップしない範囲のみを便利に見ているか、さらに醜いソリューションを使用しているようです (たとえばcvInRangeS、すべてのピクセルを反復して再実装し、カラー テーブルとの手動比較)。

それで、これを解決する通常の方法は何ですか?最善の方法は何ですか?それぞれのトレードオフは何ですか?組み込みの CV 関数を使用するよりも、ピクセルの反復処理がはるかに遅くなりますか?

4

5 に答える 5

1

信じられないかもしれませんが、まったく同じ問題があり、Hue (HSV 全体ではない) 画像を単純に反復して解決しました。

組み込みの CV 関数を使用するよりも、ピクセルの反復処理がはるかに遅くなりますか?

cv::inRange関数を理解しようとしましたが、まったく理解できませんでした (作者が特定の反復を使用したようです)。

于 2012-08-30T20:55:54.670 に答える
0

cvAddS(...)要素レベルでは、次のものと同等です。

 out = static_cast<dest> ( in + shift );

この static_cast が問題です。これは、値をクリップ/切り捨てるためです。

解決策は、データを (0-180) から (x, 255) にシフトしてから、オーバーフローを伴う非クリッピング加算を適用することです。

 out = uchar(in + (255-180) + rotation );

これで、単一の InRange 呼び出しを使用できるはずです。上記の式に従って赤の間隔をシフトするだけです

于 2012-08-31T09:13:45.420 に答える