【问题标题】:Extracting Background Image Using GrabCut使用 GrabCut 提取背景图像
【发布时间】:2013-07-15 22:13:26
【问题描述】:

我有一张图片(.jpg 图片),我想从原始图片中提取背景。我搜索了很多,但只找到了提取前景图像的教程。

我从另一个stackoverflow question 获取了代码。该代码对我来说运行良好,并且我已经成功提取了前景(根据我的要求)。现在我想从原始图像中完全删除这个前景。我希望它是这样的:-

背景 = 原始图像 - 前景

空白区域可以填充黑色或白色。我怎样才能做到这一点?

我尝试过使用这种技术:-

Mat background = image2 - foreground;

但它给出了一个完整的黑色图像。

代码:-

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main( )
{
// Open another image
Mat image;
image= cv::imread("images/abc.jpg");

Mat image2 = image.clone();

// define bounding rectangle
cv::Rect rectangle(40,90,image.cols-80,image.rows-170);

cv::Mat result; // segmentation result (4 possible values)
cv::Mat bgModel,fgModel; // the models (internally used)

// GrabCut segmentation
cv::grabCut(image,    // input image
            result,   // segmentation result
            rectangle,// rectangle containing foreground
            bgModel,fgModel, // models
            1,        // number of iterations
            cv::GC_INIT_WITH_RECT); // use rectangle
cout << "oks pa dito" <<endl;
// Get the pixels marked as likely foreground
cv::compare(result,cv::GC_PR_FGD,result,cv::CMP_EQ);
// Generate output image
cv::Mat foreground(image.size(),CV_8UC3,cv::Scalar(255,255,255));
//cv::Mat background(image.size(),CV_8UC3,cv::Scalar(255,255,255));
image.copyTo(foreground,result); // bg pixels not copied

// draw rectangle on original image
cv::rectangle(image, rectangle, cv::Scalar(255,255,255),1);

imwrite("img_1.jpg",image);

imwrite("Foreground.jpg",foreground);
Mat background = image2 - foreground;
imwrite("Background.jpg",background);

return 0;
}

注意:我是 opencv 初学者,目前对它了解不多。如果您可以发布完整的代码(根据我的要求)或者只是发布代码行并告诉我这些代码行的放置位置,我将非常感谢您。谢谢。

附:这是我在 StackOverflow.com 上的第二个问题。抱歉……如果不遵守任何约定。

【问题讨论】:

    标签: c++ opencv


    【解决方案1】:

    它不是复制所有前景像素,而是复制所有非前景像素。您可以通过使用 ~ 来做到这一点,它会否定掩码:

    image.copyTo(background,~result);
    

    【讨论】:

    • 你成功了。谢谢:-)
    【解决方案2】:

    如果你//Get the pixels marked as likely background:

    // Get the pixels marked as likely background
    cv::compare(result,cv::GC_PR_BGD,result,cv::CMP_EQ);
    

    编辑:上面的代码缺少 GC_BGD 像素。尽管给出了更有效的答案,让我们完成我们开始的工作:

    // Get the pixels marked as background
    cv::compare(result,cv::GC_BGD,result_a,cv::CMP_EQ);
    // Get the pixels marked as likely background
    cv::compare(result,cv::GC_PR_BGD,result_b,cv::CMP_EQ);
    // Final results
    result=result_a+result_b;
    

    【讨论】:

    • 是的,它会移除前景,但它也会将图像裁剪为我指定的矩形。感谢您的回答。
    • 问题是,一些像素被标记为GC_PR_BGD(可能是背景),一些被标记为GC_BGD,这意味着它们肯定是背景,因为它们已作为算法的输入.
    • 是的。我们需要保留两者,这意味着可能要多写一行代码。
    【解决方案3】:

    只是一个小建议,@William's 答案可以更简洁地写成:

    result = result & 1;
    

    为了得到二进制掩码。

    【讨论】:

      【解决方案4】:

      也许另一个例子有帮助,我假设图像的中间部分肯定是前景。 所以试试这个链接。 Example

      【讨论】:

        猜你喜欢
        • 2021-06-05
        • 2022-11-09
        • 1970-01-01
        • 2019-11-20
        • 1970-01-01
        • 2014-11-30
        • 2019-05-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多