【问题标题】:Using a PNG image as mask for GrabCut使用 PNG 图像作为 GrabCut 的蒙版
【发布时间】:2014-08-29 04:45:47
【问题描述】:

我有一个带有绿色和红色线条以及透明背景的 png 图像,我需要将其用作执行 GrabCut 的蒙版。但我得到了意想不到的结果。这是我的代码:

//find the mask
Mat mask;
mask.create( image.size(), CV_8UC1);
mask.setTo(Scalar::all(GC_BGD));
Mat maskImg = imread("messi5.png");

for(int i=0; i<maskImg.cols; i++)    
    for(int j=0; j<maskImg.rows; j++)    
    {               
        //if it's red, make it white
        if ((int)maskImg.at<cv::Vec3b>(j,i)[0]==0 && (int)maskImg.at<cv::Vec3b>(j,i)[1] == 0 && (int)maskImg.at<cv::Vec3b>(j,i)[2] == 255) {

            mask.at<cv::Vec3b>(j,i)[0]= GC_BGD;
            mask.at<cv::Vec3b>(j,i)[1] = GC_BGD;
            mask.at<cv::Vec3b>(j,i)[2] = GC_BGD;
        }           

        //if it's green, make it black
        if ((int)maskImg.at<cv::Vec3b>(j,i)[0]==0 && (int)maskImg.at<cv::Vec3b>(j,i)[1] == 255 && (int)maskImg.at<cv::Vec3b>(j,i)[2] == 0) {    
            mask.at<cv::Vec3b>(j,i)[0] = GC_FGD;
            mask.at<cv::Vec3b>(j,i)[1] = GC_FGD;
            mask.at<cv::Vec3b>(j,i)[2] = GC_FGD;
        }
    }

 ...

这是输出:http://prntscr.com/40kt4e。我想这就像没有矩形,它只看到 GC_FGD 像素,其他所有东西都被认为是 BG。它看起来以某种方式缩放,但我不知道如何修复它。

【问题讨论】:

    标签: c++ opencv image-processing image-segmentation


    【解决方案1】:

    我想说的是

    GrabCut reading mask from PNG file in OpenCV (C++)

    您使用 3 通道访问器获取 1 通道图像。这会有点混乱,使用 1 通道版本作为 1 通道掩码:

        Mat image;
        image= cv::imread(file);
    
        //everything outside this box will be set to def. 
        //background GC_BGD, clearly from the image you can see that the players legs are outside the box, 
        //so this will cause problems. you need to either change the box, 
        //such that everything is outside the box is the background, or use your mask to scribble on the players legs in green.  
        cv::Rect rectangle(startX, startY, width, height);  
        cv::Mat bgModel,fgModel;
    
        //find the mask
        Mat mask;
        mask.create( image.size(), CV_8UC1);  //CV_8UC1 is single channel
        mask.setTo(Scalar::all(GC_BGD));  //you have set it to all def. background 
    
        Mat maskImg = imread("messi5.png");
    
    
        for(int i=0; i<maskImg.cols; i++)    
            for(int j=0; j<maskImg.rows; j++)    
            {               
                //if it's red, make it black
                if ((int)maskImg.at<cv::Vec3b>(j,i)[0]==0 && (int)maskImg.at<cv::Vec3b>(j,i)[1] == 0 && (int)maskImg.at<cv::Vec3b>(j,i)[2] == 255) {
    
                    //the whole mask is black so this is redundant
                    mask.at<uchar>(j,i)= GC_BGD;  //GC_BGD := 0 := black 
    
                }           
    
                //if it's green, make it white
                if ((int)maskImg.at<cv::Vec3b>(j,i)[0]==0 && (int)maskImg.at<cv::Vec3b>(j,i)[1] == 255 && (int)maskImg.at<cv::Vec3b>(j,i)[2] == 0) {    
    
                        mask.at<uchar>(j,i) = GC_FGD; //GC_FGD:= 1 := white 
    
                }
            }
    

    有关循环图像的更有效代码,请参阅: http://docs.opencv.org/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html

    LUT 函数在这里可以解决问题: http://docs.opencv.org/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html#the-core-function

    【讨论】:

    • 这很好用,但是对于大分辨率图像来说很慢?除了让它在 GPU 上运行之外,您对提高性能有什么建议吗?
    • 嗨,如果你的意思只是那个循环,那么你可以直接访问数据,而不是使用 .at 函数。如果您的意思是 GrabCut,那么恐怕不是,因为这将意味着加速图形切割,这本质上是最大流量,因此您输入了沉重的补偿。那里的科学工作。
    • @QUED 我认为我应该尝试并行编程,我认为这是提高性能的最佳方式。你能给我任何指示,只是为了知道从哪里开始?
    • 嗨,如果你真的想这样做,那么也许从这里开始:双重分解的并行和分布式图形切割,lup.lub.lu.se/luur/…。还要考虑“cudacuts”和多尺度金字塔,解决方案从粗到细传播。否则,也许可以看看不使用图形切割的交互式图像分割的替代方案。
    猜你喜欢
    • 2020-05-13
    • 2017-07-17
    • 2012-12-16
    • 1970-01-01
    • 2010-12-17
    • 2020-03-24
    • 2017-02-05
    • 2016-07-15
    • 2022-11-23
    相关资源
    最近更新 更多