2012-10-18 24 views
13

私はkinectで取得した奥行き画像から背景を減算しようとしています。私はotsuしきい値を知ったとき、それがそれと一緒にできると思った。奥行き画像をグレースケールに変換すると、otsu閾値を適用して画像を二値化することができます。深度画像のための大津閾値処理

しかし、私はOpenCV 2.3でこれを実装(実装しようとしました)、無駄にしました。しかし、出力画像は2値化されますが、非常に予期しないことです。私は閾値処理を連続的に行いました(つまり、各フレームの分析結果を画面に出力します)。いくつかのフレームの閾値は160ishであることがわかりました。それは時には0であることがわかりました。キネクトによって返された深さイメージの0の数が多いことが原因である可能性があります。これは、測定できないピクセルに対応しています。値0のピクセルを無視するようにアルゴリズムに指示する方法はありますか?またはotsu thresholdingは私がやろうとしていることには良くないのですか?

ここには、関連コードのいくつかの出力とセグメントがあります。 2番目のスクリーンショットは、良い2値化ができるように見えるかもしれませんが、シーン内の椅子に対応するピクセルとバックグラウンドとを区別するものを実現したいと思います。

ありがとうございました。それ以外の場合は、配布

  cv::Mat1s depthcv(depth->getHeight(), depth->getWidth()); 
      cv::Mat1b depthcv8(depth->getHeight(), depth->getWidth()); 
      cv::Mat1b depthcv8_th(depth->getHeight(), depth->getWidth()); 
      depthcv.data =(uchar*) depth->getDepthMetaData().Data(); 
      depthcv.convertTo(depthcv8,CV_8U,255/5000.f); 

      //apply otsu thresholding 
      cv::threshold(depthcv8, depthcv8_th, 128, 255, CV_THRESH_BINARY|CV_THRESH_OTSU); 
      std::ofstream output; 
      output.open("output.txt"); 
      //output << "M = "<< endl << " " << depthcv8 << endl << endl; 
      cv::imshow("lab",depthcv8_th); 
      cv::waitKey(1); 

Image 1 this second screenshot looks like it could do some good binarization

+2

Ubuntuのプレス 'ALT + prtsc'に単一のウィンドウのスクリーンショットを作成するには。 – ArtemStorozhuk

+0

私は公式のWindows SDKに慣れているので、直接質問に答えることはできません。ただし、Windowsをインストールしている場合、公式のKinect for Windows SDK Toolkitの例には「緑色の画面」の例があります。あなたはそこからいくつかのアイデアを得ることができるかもしれません。多分... ? –

+0

投稿画像を投稿してください – nkint

答えて

13

大津は何をしようとするために十分な、おそらく良いですが、大津アルゴリズムで最適なしきい値を計算する前にゼロ値をマスクする必要があります強度の値があなたが望むものよりも低く歪んでしまいます。

OpenCVはcv::threshold関数のマスク引数を提供しないため、これらの値を自分で削除する必要があります。 0以外の値をすべてN行列に入れてcv::threshold関数をCV_THRESH_OTSUと呼び出し、戻り値(推定される最適なしきい値)を保存してから、元の画像でcv::threshold関数を再度実行することをお勧めしますCV_THRESH_BINARYフラグと計算されたしきい値だけです。ここで

は、一つの可能​​な実装である:

// move zeros to the back of a temp array 
cv::Mat copyImg = origImg; 
uint8* ptr = copyImg.datastart; 
uint8* ptr_end = copyImg.dataend; 
while (ptr < ptr_end) { 
    if (*ptr == 0) { // swap if zero 
    uint8 tmp = *ptr_end; 
    *ptr_end = *ptr; 
    *ptr = tmp; 
    ptr_end--; // make array smaller 
    } else { 
    ptr++; 
    } 
} 

// make a new matrix with only valid data 
cv::Mat nz = cv::Mat(std::vector<uint8>(copyImg.datastart,ptr_end),true); 

// compute optimal Otsu threshold 
double thresh = cv::threshold(nz,nz,0,255,CV_THRESH_BINARY | CV_THRESH_OTSU); 

// apply threshold 
cv::threshold(origImg,origImg,thresh,255,CV_THRESH_BINARY_INV); 
関連する問題