Otsu阈值处理深度图像

bah*_*hti 13 opencv kinect background-subtraction

我试图从kinect获得的深度图像中减去背景.当我学会了什么otsu阈值时,我认为它可以用它.将深度图像转换为灰度,我希望可以应用otsu阈值来对图像进行二值化.

不过我用OpenCV 2.3实现了这个(试图实现),但是徒劳无功.然而,非常意外地将输出图像二值化.我连续进行了阈值处理(即将结果打印到屏幕上以分析每一帧),并发现对于某些帧,阈值被发现为160ish,有时它被发现为0.我不太明白为什么会发生这种情况.可能是由于kinect返回的深度图像中的0的高数量,这对应于无法测量的像素.有没有办法可以告诉算法忽略值为0的像素?或者otsu阈值对我想做的事情不好?

以下是相关代码的一些输出和部分.您可能会注意到第二个屏幕截图看起来可以做一些很好的二值化,但是我希望实现一个能够区分对应于场景中的椅子和背景的像素.

谢谢.

            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);
Run Code Online (Sandbox Code Playgroud)

图片1 这第二个截图看起来可以做一些很好的二值化

Dou*_*oug 13

大津是可能是你正在尝试做的不够好,但你需要计算与Otsu算法最佳阈值之前掩盖了零个值,否则强度值的分布将偏斜比你想的要低.

OpenCV不为cv::threshold函数提供掩码参数,因此您必须自己删除这些值.我建议把所有非零值在1 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);
Run Code Online (Sandbox Code Playgroud)