【问题标题】:opencv background substractionopencv背景减法
【发布时间】:2011-12-19 00:23:36
【问题描述】:

我有一张背景场景的图像和一张前面有物体的同一场景的图像。现在我想用背景减法在前景中创建对象的蒙版。两个图像都是 RGB。

我已经创建了以下代码:

cv::Mat diff;
diff.create(orgImage.dims, orgImage.size, CV_8UC3);
diff = abs(orgImage-refImage);

cv::Mat mask(diff.rows, diff.cols, CV_8U, cv::Scalar(0,0,0));
//mask = (diff > 10);

for (int j=0; j<diff.rows; j++) {
    // get the address of row j
    //uchar* dataIn= diff.ptr<uchar>(j);
    //uchar* dataOut= mask.ptr<uchar>(j);
    for (int i=0; i<diff.cols; i++) {
        if(diff.at<cv::Vec3b>(j,i)[0] > 30 || diff.at<cv::Vec3b>(j,i)[1] > 30 || diff.at<cv::Vec3b>(j,i)[2] > 30)
            mask.at<uchar>(j,i) = 255;
    }
}

我不知道我这样做对不对?

【问题讨论】:

    标签: opencv background-subtraction


    【解决方案1】:

    查看 OpenCV 中的 inRange 函数。这将允许您同时为 3 通道图像设置多个阈值。

    因此,要创建您正在寻找的面具,请执行以下操作:

    inRange(diff, Scalar(30, 30, 30), Scalar(255, 255, 255), mask);
    

    这也应该比尝试自己访问每个像素要快。

    编辑:如果您要进行皮肤检测,我会先进行皮肤检测,然后再进行背景减法以去除背景。否则,您的皮肤检测器将不得不考虑由减法引起的强度变化。

    看看我的另一个answer,关于皮肤检测的好技术。

    编辑:

    这样更快吗?

    int main(int argc, char* argv[])
    {
        Mat fg = imread("fg.jpg");
        Mat bg = imread("bg.jpg");
    
        cvtColor(fg, fg, CV_RGB2YCrCb);
        cvtColor(bg, bg, CV_RGB2YCrCb);
    
        Mat distance = Mat::zeros(fg.size(), CV_32F);
    
        vector<Mat> fgChannels;
        split(fg, fgChannels);
    
        vector<Mat> bgChannels;
        split(bg, bgChannels);
    
        for(size_t i = 0; i < fgChannels.size(); i++)
        {
            Mat temp = abs(fgChannels[i] - bgChannels[i]);
            temp.convertTo(temp, CV_32F);
    
            distance = distance + temp;
        }
    
    
        Mat mask;
        threshold(distance, mask, 35, 255, THRESH_BINARY);
    
        Mat kernel5x5 = getStructuringElement(MORPH_RECT, Size(5, 5));
        morphologyEx(mask, mask, MORPH_OPEN, kernel5x5);
    
        imshow("fg", fg);
        imshow("bg", bg);
        imshow("mask", mask);
    
        waitKey();
    
        return 0;
    }
    

    此代码根据您的输入图像生成此掩码:

    最后,这是我使用简单的阈值方法得到的结果:

        Mat diff = fgYcc - bgYcc;
        vector<Mat> diffChannels;
        split(diff, diffChannels);
    
        // only operating on luminance for background subtraction...
        threshold(diffChannels[0], bgfgMask, 1, 255.0, THRESH_BINARY_INV);
    
        Mat kernel5x5 = getStructuringElement(MORPH_RECT, Size(5, 5));
        morphologyEx(bgfgMask, bgfgMask, MORPH_OPEN, kernel5x5);
    

    这会产生以下掩码:

    【讨论】:

    • 感谢您的评论!但我这样做对吗?因为 diff 图像中的像素在输入图像和参考图像之间存在差异的地方是全黑的......
    • 你能贴出你在上述算法中使用的图片吗?
    • 这是图像:dl.dropbox.com/u/5276376/image.jpg 参考图像:dl.dropbox.com/u/5276376/refImage.jpg 和差异:dl.dropbox.com/u/5276376/diff.jpg(是的,图像和参考图像之间的照明存在微小差异)。如您所见,差异图像中的手臂包含许多黑色像素。结果,所有这些像素都会丢失,例如阈值。 30
    • 嗯,我认为问题在于我使用的 RGB 色彩空间不是感知上统一的色彩空间。两种颜色可能看起来非常相似,而相隔相同距离的另外两种颜色看起来会非常不同......所以现在我首先将图像转换为 YCrCb 颜色空间,但结果更糟。也许是因为我使用了错误的类型来保存每个像素,因此低于零的值将被剪裁为零或其他什么?目前我正在使用 CV_32F 来区分: diff.create(table.dims, table.size, CV_32F); diff = abs(table - refRoi);
    • 我知道皮肤检测技术,但我也想要其他部分的轮廓,例如衣服...所以背景减法技术
    【解决方案2】:

    我认为当我这样做时,我会得到正确的结果:(在 YCrCb 颜色空间中)但访问每个 px 很慢,所以我需要找到另一种算法

        cv::Mat mask(image.rows, image.cols, CV_8U, cv::Scalar(0,0,0));
    
        cv::Mat_<cv::Vec3b>::const_iterator itImage= image.begin<cv::Vec3b>();
        cv::Mat_<cv::Vec3b>::const_iterator itend= image.end<cv::Vec3b>();
        cv::Mat_<cv::Vec3b>::iterator itRef= refRoi.begin<cv::Vec3b>();
        cv::Mat_<uchar>::iterator itMask= mask.begin<uchar>();
    
        for ( ; itImage!= itend; ++itImage, ++itRef, ++itMask) {
            int distance = abs((*itImage)[0]-(*itRef)[0])+
                            abs((*itImage)[1]-(*itRef)[1])+
                            abs((*itImage)[2]-(*itRef)[2]);
    
            if(distance < 30)
                *itMask = 0;
            else
                *itMask = 255;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-03
      • 2016-06-19
      • 2011-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多