漫水填充算法

来源:互联网 发布:俄罗斯方块c语言程序 编辑:程序博客网 时间:2024/04/30 03:48

函数声明

    用来标记或分离图像的一部分,类似于PS内的魔术棒功能。    在确定一个中心点情况下,利用一个下限间隔值和一个上限间隔值确定连通区域,对该区域做漫填充操作。

  • 使用low(R1,G1,B1)和high(R2,G2,B2)来确定像素点可接受域

  • 该函数可以彩色图片或者灰度图操作,对于彩色图如果在区域内,可以三个通道同时设置不同的间隔值,如果在接收范围内则会留下该点。

  • 函数的操作区域一定为连续区域。


不带掩码的填充函数说明int floodFill( InputOutputArray image,  //输入图像               Point seedPoint,     //中心点               CV_OUT Rect* rect=0,  //设置边界区域最小矩阵               Scalar loDiff=Scalar(),  //低像素间隔值               Scalar upDiff=Scalar(),  //高像素间隔值               int flags=4       //控制填充区域的连通性,相关性               );
带掩码int floodFill( InputOutputArray image,   //输入图像               InputOutputArray mask,  //掩码               Point seedPoint,   //中心点               Scalar newVal,    //填充像素值               CV_OUT Rect* rect=0,  //边界最小矩阵               Scalar loDiff=Scalar(),   //低               Scalar upDiff=Scalar(),    //高               int flags=4    //标志               );----------
参数说明mask:    注意该Mat对象应该满足:          1. 单通道  CV_8UC1          2. 长宽比原图大2倍(2个像素点即可)   (src.rows+2,src.cols+2)          3. floodFill函数"只操作mask内像素点为0的值"          4. mask图像的(x+1,y+1)与原图的(x,y)点对应 - 在使用过程中可以先划定并清空mask中ROI区域,再做floodFill操作。 - 也可以在mask中标定原图的边界区域,防止floodFill填充到边界。----------seedPoint:      floodFill操作的中心点(可以利用鼠标点击事件来获取到用户输入)----------newVal:      标定区域后填充的颜色值。( 彩色:Scalar(r,g,b)或灰度:Scalar(d) )----------rect:     默认值为0,设置floodFill函数将要填充的最小边界区域----------loDiff:     低下限间隔值( 彩色:Scalar(r,g,b)  灰度:Scalar(d) )upDiff:     高上限间隔值( 彩色:Scalar(r,g,b)  灰度:Scalar(d) )----------flags:    int型定义前24位。参数包含三个部分。      1.对于低8位(0~7位)。控制填充算法的连通性。可以设置4或8。          a.为4 -->填充算法只考虑当前像素点的左右和垂直方向的相邻点          b.为8 -->填充算法还会考虑对角线方向的相邻点      2.对于8~15位。             指定填充掩码图像的值。如果设置为0,则mask即会用1填充。       3.对于16~23位。           a. FLOODFILL_FIXED_RANGE   只有当某个相邻点与中心点(seekPoint)像素差在范围内才填充           b. FLOODFILL_MASK_ONLY   函数不填充原始图像,只填充mask图像     flags可以通过OR操作连接起来。 例如:想用8领域填充,并填充固定像素值范围,填充mask图像,填充值为47.         则输入参数为:                         flags = FLOODFILL_FIXED_RANGE                              | FLOODFILL_MASK_ONLY                              | (47<<8);  ----------

程序实例

#include <opencv2/core/core.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/core/types_c.h>#include <iostream>#include <opencv.hpp>using namespace cv;using namespace std;void onMouseChangeListener(int event,int x,int y,int,void*);//鼠标回调void onBarChangeLisener(int,void*);  //bar回调Mat src,src_gray,temp,dst;int lowDiff=5,highDiff=5,maxGap=30;bool isSrc_Gray=false; //源图是否为灰度图bool isMask=false;     //floodFill是否需要掩码阵int main(){    src = imread("H:\\cat.jpg");    temp.create(src.rows+2,src.cols+2,CV_8UC1);  //初始化掩码矩阵    temp = Scalar::all(0);    namedWindow("src");setMouseCallback("src",onMouseChangeListener);createTrackbar("low","src",&lowDiff,maxGap,onBarChangeLisener);createTrackbar("high","src",&highDiff,maxGap,onBarChangeLisener);    imshow("src",src);    int key=0;    while (1)    {        key=waitKey(0);        char c=(char)key;        if (key=='e')  //按下E -->退出        {            break;        }        switch (c)          {        case 'g':   isSrc_Gray = true; break;  //按下g -->  灰度图        case 'r':  isSrc_Gray = false;break;  //按下r -->  彩色图        case 'm':  isMask=true; break;        //按下m -->  带掩码        case 'n':  isMask=false; break;     //按下n -->  不带掩码        default: break;                 }    }    waitKey(0);    return 0;}void onMouseChangeListener(int event,int x,int y,int,void*){    if (event!=CV_EVENT_LBUTTONDOWN)    {        return;     // 只响应左击事件    }    Rect ccmp;    Point seedPoint = Point(x,y);  //漫水填充原始点=鼠标点击点    isSrc_Gray?(cvtColor(src,dst,CV_RGB2GRAY)):(src.copyTo(dst));  //确定目标图是否为灰度图    if (isMask)  //需要掩码    {        threshold(temp,temp,1,128,CV_THRESH_BINARY);  //确定mask阵        if (isSrc_Gray)        {            floodFill(dst,temp,seedPoint,Scalar(1),&ccmp,                Scalar(lowDiff),Scalar(highDiff),4);        }        else //彩色通道        {            floodFill(dst,temp,seedPoint,Scalar(255,0,0),&ccmp,                Scalar(lowDiff,lowDiff,lowDiff),Scalar(highDiff,highDiff,highDiff),4);        }    }    else  //不带mask的floodFill函数    {        if (isSrc_Gray)          {            floodFill(dst,seedPoint,Scalar(1),&ccmp,Scalar(lowDiff),Scalar(highDiff),4);        }        else        {            floodFill(dst,seedPoint,Scalar(255,0,0),&ccmp,                Scalar(lowDiff,lowDiff,lowDiff),Scalar(highDiff,highDiff,highDiff),4);        }    }    imshow("dst",dst);}void onBarChangeLisener(int,void*){    lowDiff = lowDiff==0?1:lowDiff;    highDiff = highDiff==0?1:highDiff;}

上为彩色图,下为灰度图

0 0