基本的なhsb皮膚検出、ネオン照明


14

これが適切な質問の場所であることを願っています。それ以外の場合は私の間違いとすみません、より良いサイトを教えてください。

ある範囲のhsb画像を使用して、非常にシンプルな肌検出器を実装しようとしています。私はここここで説明さているアプローチを使用しています

ウェブカメラのビデオソースを使用しようとしています。私は太陽の照明を使用する場合、それは非常にうまく機能します(それほど良くはありませんが、かなり良い)が、ネオンの光で..それは混乱です。多くの白い領域が検出され、多くの場所でノイズが発生します。

どうして?

私は2番目のソースで説明されているアルゴリズムを使用しています:

  1. 画像をHSV色空間に変換する
  2. 0 <H <38の範囲に白を置く
  3. 拡張フィルター
  4. 侵食フィルター
  5. ぼかしフィルター

ここに画像の説明を入力してください

回答:


10

これは、HSVよりもRGBの単純な生成モデルを使用すると、実際にうまく機能する場合があります。

  1. トレーニング画像またはいくつかのスキンでいくつかのトレーニング画像を取得します。
  2. スキンピクセルを手動で選択します(バイナリマスクを作成するなど)
  3. RGBで肌色の平均と共分散を計算します(それぞれ3要素ベクトルでなければなりません)
  4. 未知のピクセルの場合、共分散を使用して、平均からのマハラノビス距離を計算します。
  5. 距離がしきい値より小さい場合は、スキンとして分類します。
  6. 最高のパフォーマンスを得るためにしきい値を調整します。

n P m m m P Q QnnPmmmPQQC=QQC 3 x 3です。

編集2: 取得している値が大きすぎるようです。最大共分散を取得するには、次の行列を作成します。

255 255 255
 0   0   0

そしてその共分散を計算します。すべての値が約32513であるマトリックスを取得する必要があります。そのため、ピクセル値の範囲が0〜255であることを確認し、それらを正しくfloatまたはdoubleにコピーしてください。マハラノビス距離は分散の単位であるため、数値は小さくする必要があります。皮膚分類のしきい値は、おそらく4未満でなければなりません。


画像からopencvで3x3の共分散行列を取得する方法を理解するのに問題があります。
nkint

@nkint、編集された回答をご覧ください。
ディマ

いいよ 5行で、共分散とは何かを理解させてくれました。ありがとう。できます。しかし、結果の保存に問題があります。0-255のピクセルがある場合、マハラノビス距離にどのような数字を期待する必要がありますか?それらを8 uintに保存する場合、皮膚のほんの一部しか使用しません。32floatに保存する場合、絞られたホワイトノイズになります
nkint

共分散行列は次のとおりです。[10913058.00000000、7046611.50000000、3290781.50000000; 7046611.50000000、4811646.00000000、2225078.00000000; 3290781.50000000、2225078.00000000、1387631.87500000]
-nkint

1
共分散は、3Dで楕円体を定義すると考えることができます。Matlabで視覚化できるかもしれませんが、それは多くの作業になる可能性があります。あるいは、楕円体の2D投影を確認することもできますが、これには多少の手間がかかります。
ディマ

4

ネオンライトが適用されたときにHSVカラーで取得されたさまざまな値を考慮してください。その偏差の例はこちらです。これらの値に適合するようにアルゴリズムを調整してみてください。

ここには肌を検出する別のアルゴリズムがあり、光の状態を検出するためにこれを使用できます。

肌の検出に関連しているが、ネオンの光の効果にあまり関連していない別のアルゴリズムがこれです。


2

これまでに得た答えは、優れた代替方法を示していますが、初期アルゴリズムのようなものを使用することに興味がある場合は、おそらく修正するのは難しくありません。OpenCVのHSV特性に合わせて調整する必要があります。奇抜な結果を考えると、おそらくしきい値の選択やピクセルの変換にHSVのより一般的な数値表現の1つを使用したと思いますか?

OpenCVは、他のほとんどのソースとは異なるHSVを表します。

  • あなたにとっての最大の違いはw / r / t色相です:OpenCVは、0〜179の範囲の色相を表します。
  • もう1つの違い:彩度の測定値は標準値と比較して反転しています。したがって、255飽和はopencvでは白ではなく明るいことを意味します(注意、255に戻っています-多分「ホイール」表現のために色相だけが0-180ですか?)

おそらく手遅れになるかもしれませんが、それは興味深い質問であり、他の誰かが同じ問題に遭遇するかもしれません。


-1
import sys
import numpy
import cv2

cap = cv2.VideoCapture(0)
while(1):
    _, im = cap.read()

    im_ycrcb = cv2.cvtColor(im, cv2.COLOR_BGR2YCR_CB)

    skin_ycrcb_mint = numpy.array((0, 133, 77))
    skin_ycrcb_maxt = numpy.array((255, 173, 127))
    skin_ycrcb = cv2.inRange(im_ycrcb, skin_ycrcb_mint, skin_ycrcb_maxt)

    cv2.imshow("Second Image", skin_ycrcb) # Second image
    contours, _ = cv2.findContours(skin_ycrcb, cv2.RETR_EXTERNAL, 
        cv2.CHAIN_APPROX_SIMPLE)
    for i, c in enumerate(contours):
        area = cv2.contourArea(c)
            if area > 1000:
                cv2.drawContours(im, contours, i, (255, 0, 0), 3)
    cv2.imshow("Final Image", im)         # Final image
    cv2.waitKey(1)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.