【opencv学习之三十九】背景分割和漫水填充

openCV中实现了背景分割算法——grabCut()和漫水填充算法——floodFill();

其中GrabCut算法是调用仅需要确认前景和背景输入,该算法就可以完成前景和背景的相对最优的分割;该算法利用了图像中的纹理信息和边界反差信息,来进行分割,和分水岭算法比较类似,但是速度挺慢的,结果好于分水岭;

floodFill漫水填充算法比较常见,图画中的填充色用的就是这个算法;原理也比较简单就是遍历封闭区域内的像素点并置换为指定色为止;也可以用来做阈值分割;

下面是grabCut()的实例;

1、分组函数的方法:

//背景分割算法1
/****************GrabCut mask方法*******************/
void MyShowImage(Mat Image,const string winName)
{
    imshow( winName, Image );
}
void getBinMask( const Mat& comMask, Mat& binMask )
{
    binMask.create( comMask.size(), CV_8UC1 );
    binMask = comMask & 1;
}

void imgGrabCut()//背景分割算法1
{

    Mat image = imread("D:/ImageTest/qq.jpg" );
    const string winName = "image";
    MyShowImage(image,winName);

    /***********************************/
    Mat bg;Mat fg;
    Rect rect = Rect(47,48,408,464);
    Mat mask,res;
    mask.create( image.size(), CV_8UC1);
    grabCut( image, mask, rect, bg, fg, 1, 0 );

    Mat binMask;
    getBinMask( mask, binMask );
    image.copyTo( res, binMask );
    MyShowImage(res,winName);
    /***********************************/
    cvWaitKey(0);
}

效果:


2、单函数方法:

void imgGrabCut2()//背景分割算法2
{
    // 矩形外的像素是背景
    Rect rectGrab=Rect(47,48,408,464);
    // 打开另一幅图像
    cv::Mat image= cv::imread("D:/ImageTest/qq.jpg");
    Mat temp=image.clone();
    rectangle( temp,rectGrab,Scalar(0, 0, 255), 2, 8);
    imshow("src",temp);
    Mat result;
    Mat bgModel,fgModel;       //临时变量,函数需要
    grabCut(image,             //输入图像
            result,            //分段结果
            rectGrab,          // 包含前景的矩形
            bgModel,fgModel,   // 前景、背景
            1,                 // 迭代次数
            cv::GC_INIT_WITH_RECT); // 用矩形
    //比较函数保留值为GC_PR_FGD的像素
    compare(result,//输入图像1
            GC_PR_FGD,//输入图像2,或者像素级,或者具体像素
            result,//输出图像
            cv::CMP_EQ);//操作类型
    //    enum { CMP_EQ=0, //相等
    //        CMP_GT=1,   //大于
    //        CMP_GE=2,   //大于等于
    //        CMP_LT=3,   //小于
    //        CMP_LE=4,   //小于等于
    //        CMP_NE=5 }; //不相等
    //    enum GrabCutClasses {
    //        GC_BGD    = 0,  //!< an obvious background pixels
    //        GC_FGD    = 1,  //!< an obvious foreground (object) pixel
    //        GC_PR_BGD = 2,  //!< a possible background pixel
    //        GC_PR_FGD = 3   //!< a possible foreground pixel
    //    };

    // 产生输出图像
    cv::Mat foreground(image.size(),CV_8UC3,cv::Scalar(255,255,255));
    //背景值为 GC_BGD=0,作为掩码
    image.copyTo(foreground,result);
    imshow("result", foreground);
    waitKey(0);
}

效果:


漫水填充法实例:

void imgFloodFill()//满水填充法
{
    Mat src = imread("D:/ImageTest/222.JPG");
    Rect rect;
    imshow("src", src);
    floodFill(src,                         //输入图像
              Point(20,20),                //拾取点
              Scalar(255, 0, 0),           //填充颜色
              &rect,                       //重绘最小矩形,默认值是0;
              Scalar(30, 30, 30),          //负差,拾取点像素rgb与当前像素rgb做差,差值大于这个
              Scalar(12, 12, 12));         //正差,当前像素rgb与拾取点像素rgb做差,差值小于这个
    //    int floodFill( InputOutputArray image,
    //                   InputOutputArray mask,
    //                   Point seedPoint,
    //                   Scalar newVal,
    //                   CV_OUT Rect* rect=0,
    //                   Scalar loDiff = Scalar(),
    //                   Scalar upDiff = Scalar(),
    //                   int flags = 4 );
    //    函数 cvFloodFill 用指定颜色,从种子点开始填充一个连通域。连通性由象素值的接近程度来衡量。
    //    在点 (x, y) 的象素被认为是属于重新绘制的区域,如果:
    //    src(x',y')-lo_diff<=src(x,y)<=src(x',y')+up_diff, 灰度图像,浮动范围
    //    src(seed.x,seed.y)-lo<=src(x,y)<=src(seed.x,seed.y)+up_diff, 灰度图像,固定范围
    //    src(x',y')r-lo_diffr<=src(x,y)r<=src(x',y')r+up_diffr 和
    //    src(x',y')g-lo_diffg<=src(x,y)g<=src(x',y')g+up_diffg 和
    //    src(x',y')b-lo_diffb<=src(x,y)b<=src(x',y')b+up_diffb, 彩色图像,浮动范围
    //    src(seed.x,seed.y)r-lo_diffr<=src(x,y)r<=src(seed.x,seed.y)r+up_diffr 和
    //    src(seed.x,seed.y)g-lo_diffg<=src(x,y)g<=src(seed.x,seed.y)g+up_diffg 和
    //    src(seed.x,seed.y)b-lo_diffb<=src(x,y)b<=src(seed.x,seed.y)b+up_diffb, 彩色图像,固定范围
    //    其中 src(x',y') 是象素邻域点的值。也就是说,为了被加入到连通域中,一个象素的彩色/亮度应该足够接近于:
    //    它的邻域象素的彩色/亮度值,当该邻域点已经被认为属于浮动范围情况下的连通域。
    //    固定范围情况下的种子点的彩色/亮度值
    imshow("result", src);
    waitKey(0);
}

效果:


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: OpenCV是一种广泛使用的计算机视觉库,可以用于许多不同的应用程序,例如图像处理、目标识别和计算机视觉应用等。在OpenCV中,水平和垂直填充是一种常见的图像处理技术,它们可以用于扩展图像的大小并提高其质量。以下是使用OpenCV进行水平和垂直填充的示例代码: 水平填充示例代码: ``` #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main() { Mat image = imread("image.jpg"); Mat padded_image; int border_width = 50; copyMakeBorder(image, padded_image, 0, 0, border_width, border_width, BORDER_CONSTANT, Scalar(0, 0, 0)); imshow("Original Image", image); imshow("Padded Image", padded_image); waitKey(0); return 0; } ``` 垂直填充示例代码: ``` #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main() { Mat image = imread("image.jpg"); Mat padded_image; int border_width = 50; copyMakeBorder(image, padded_image, border_width, border_width, 0, 0, BORDER_CONSTANT, Scalar(0, 0, 0)); imshow("Original Image", image); imshow("Padded Image", padded_image); waitKey(0); return 0; } ``` 以上代码中,首先使用imread()函数读取图像。然后,使用copyMakeBorder()函数将图像进行填充。在水平填充示例中,将图像的左边和右边各填充50个像素,而在垂直填充示例中,将图像的上边和下边各填充50个像素。最后,使用imshow()函数显示原始图像和填充后的图像,并使用waitKey()函数等待用户输入。 ### 回答2: OpenCV中的漫水填充(Flood Fill)是一种图像处理技术,用于将特定区域填充为指定的颜色或模式。它可以应用于许多图像分割和处理任务中,如对象提取、背景去除等。 漫水填充的原理是从指定的种子点开始,通过扩散算法将相邻的像素点标记为同一种颜色,直到达到边界或满足特定的停止条件。 在OpenCV中,我们可以使用`cv2.floodFill()`函数来实现漫水填充。该函数具有以下参数: - `image`:输入图像,必须为8位单通道图像。 - `mask`:掩码图像,用于指示那些像素点已经填充的区域。 - `seedPoint`:漫水填充的种子点,即起始点。 - `newVal`:填充的新值,可以是单个整数或一个包含3个整数的元组。 - `loDiff`和`upDiff`:低和高的颜色差异阈值,用于控制是否填充相似颜色的像素点。 - `flags`:附加标志,可用于调整填充方式和行为。 通过传递适当的参数,我们可以实现不同的漫水填充效果。例如,我们可以使用不同的颜色填充区域,或者使用掩码限制填充的区域。 漫水填充是一个强大而灵活的图像处理技术,在实际应用中广泛使用。无论是处理数字图像还是计算机视觉任务,OpenCV漫水填充功能都有助于提取感兴趣的区域并进行后续处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值