c++ - 使用 PNG 图像作为 GrabCut 的 mask

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

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

//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。它看起来有点缩放,但我不知道如何修复它。

最佳答案

我想说的是

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

您将 3 channel 访问器用于 1 channel 图像。这会把事情搞得一团糟,使用 1 channel 版本作为 1 channel 掩码:

    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

关于c++ - 使用 PNG 图像作为 GrabCut 的 mask ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24631988/

相关文章:

android - 在 Android 中成功加载 OpenCV 后,imgproc.Canny 出现 UnsatisfiedLinkError

php - 数据库设计和图像文件系统管理?

c++ - C++ 11中的T &&(双“&”号)是什么意思?

visual-studio - 表达式 : "(_Ptr_user&(_BIG_ALLOCATION_ALIGNMENT - 1)) ==0" && 0

c++ - 在 C++ 中将两个 uint32 组合到 ulong64

java - Opencv Java fillConvexPoly 和 approxPolyDP 函数

algorithm - 如何过滤二值图像中不需要的区域和空洞区域

algorithm - 是否有可能从仿射注册中获得物体运动?

c++ - "cannot access private member' "只有当类有导出链接时才会出错

c++ - 获取键盘使用代码,如何从 read() 发送触发器