Opencv 深度图像的Otsu阈值分割

Opencv 深度图像的Otsu阈值分割,opencv,kinect,background-subtraction,Opencv,Kinect,Background Subtraction,我试图从kinect获取的深度图像中减去背景。当我知道什么是大津阈值,我认为它可以与它。将深度图像转换为灰度,我希望能应用otsu阈值对图像进行二值化 然而,我用OpenCV 2.3实现了(试图实现)这一点,结果是徒劳的。然而,输出图像被二值化,这是非常意外的。我连续进行阈值处理(即将结果打印到屏幕上,以便对每一帧进行分析),发现某些帧的阈值为160ish,有时为0。我不太明白为什么会这样。这可能是由于kinect返回的深度图像中有大量的0,对应于无法测量的像素。有没有办法让算法忽略值为0的像素

我试图从kinect获取的深度图像中减去背景。当我知道什么是大津阈值,我认为它可以与它。将深度图像转换为灰度,我希望能应用otsu阈值对图像进行二值化

然而,我用OpenCV 2.3实现了(试图实现)这一点,结果是徒劳的。然而,输出图像被二值化,这是非常意外的。我连续进行阈值处理(即将结果打印到屏幕上,以便对每一帧进行分析),发现某些帧的阈值为160ish,有时为0。我不太明白为什么会这样。这可能是由于kinect返回的深度图像中有大量的0,对应于无法测量的像素。有没有办法让算法忽略值为0的像素?或者大津阈值法不适合我正在尝试的事情

下面是一些输出和相关代码段。您可能会注意到,第二个屏幕截图看起来可以进行一些很好的二值化,但是我想实现一个在场景和背景中与椅子对应的像素之间进行明显区分的屏幕截图

谢谢

            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);
cv::Mat1s depthcv(depth->getHeight(),depth->getWidth());
cv::Mat1b depthcv8(深度->获取高度(),深度->获取宽度());
cv::Mat1b depthcv8_th(深度->获取高度(),深度->获取宽度());
depthcv.data=(uchar*)depth->getDepthMetaData().data();
深度CV.convertTo(深度cv8,CV_8U,255/5000.f);
//应用大津阈值法
cv::阈值(depthcv8,depthcv8_th,128,255,cv_THRESH_BINARY | cv_THRESH_OTSU);
std::流输出;
output.open(“output.txt”);

//输出大津对于您尝试执行的操作来说可能已经足够好了,但是在使用大津算法计算最佳阈值之前,您确实需要屏蔽零值,否则强度值的分布将偏离您想要的值

OpenCV没有为
cv::threshold
函数提供掩码参数,因此您必须自己删除这些值。我建议将所有非零值放入一个1×N矩阵中,并使用
cv_THRESH_OTSU
调用
cv::threshold
函数,并保存返回值(这是估计的最佳阈值),然后在原始图像上再次运行
cv::threshold
函数,仅使用
cv\u THRESH\u 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);
//将零移到临时数组的后面
cv::Mat copyImg=原始文件;
uint8*ptr=copyImg.datastart;
uint8*ptr_end=copyImg.dataend;
while(ptr
要在Ubuntu中制作单个窗口的屏幕截图,请按
alt+prtsc
。我只熟悉官方的Windows SDK,因此无法直接回答问题。但是,如果您安装了Windows,官方的Kinect for Windows SDK工具包示例中会有“绿屏”示例。你可以从那里得到一些想法。大概您似乎在创建矩阵数组时更改了高度和宽度。校正应该是
cv::Mat1s depthcv(depth->getWidth(),depth->getHeight())