zoukankan      html  css  js  c++  java
  • opencv学习之路(31)、GrabCut & FloodFill图像分割

    一、GrabCut

    1、利用Rect做分割

    #include "opencv2/opencv.hpp"
    using namespace cv;
    
    void main()
    {
        Mat src = imread("E://bird.jpg");
        Rect rect(84, 84, 406, 318);//左上坐标(X,Y)和长宽
        Mat result, bg, fg;
    
        grabCut(src, result, rect, bg, fg, 1, GC_INIT_WITH_RECT);
        imshow("grab", result);
        /*threshold(result, result, 2, 255, CV_THRESH_BINARY);
        imshow("threshold", result);*/
    
        compare(result, GC_PR_FGD, result, CMP_EQ);//result和GC_PR_FGD对应像素相等时,目标图像该像素值置为255
        imshow("result",result);
        Mat foreground(src.size(), CV_8UC3, Scalar(255, 255, 255));
        src.copyTo(foreground, result);//copyTo有两种形式,此形式表示result为mask
        imshow("foreground", foreground);
        waitKey(0);
    }

    grab并非是全黑图像,对其使用二值化后能看到低像素值的情况 

    2、利用mask做分割

    #include "opencv2/opencv.hpp"
    using namespace cv;
    
    void main()
    {
        Mat src = imread("E://bird.jpg");
        //Rect rect(84, 84, 406, 318);
        Rect rect;
        Mat bgModel, fgModel;
        Mat result(src.size(), CV_8U, Scalar(0));
        Mat ROI(result(Rect(84, 84, 406, 318)));
        ROI.setTo(GC_PR_FGD);//ROI设置为可能是前景
    
        grabCut(src, result, rect, bgModel, fgModel, 1, GC_INIT_WITH_MASK);
        //threshold(result, result, 2, 255, CV_THRESH_BINARY);
        imshow("grab", result);
        compare(result, GC_PR_FGD, result, CMP_EQ);
        //result = result&1;
        imshow("result", result);
        Mat foreground(src.size(), CV_8UC3, Scalar(255, 255, 255));
        src.copyTo(foreground, result);
        imshow("foreground", foreground);
    
        waitKey(0);
    }

     二、漫水填充算法——floodFill

    #include "opencv2/opencv.hpp"
    using namespace cv;
    
    void main()
    {
        Mat src = imread("E://bird.jpg");
        imshow("src", src);
        Rect rect;
        //原图,种子点,新颜色,重绘区域的最小边界矩形,负差,正差
        floodFill(src, Point(20,20), Scalar(255, 0, 0), &rect, Scalar(10, 10, 10), Scalar(10, 10, 10));
        imshow("result", src);
        waitKey(0);
    }

    三、综合应用(代码来自浅墨大神)

      1 #include "opencv2/opencv.hpp"
      2 #include <iostream>
      3 using namespace std;
      4 using namespace cv;
      5 
      6 Mat g_srcImage, g_dstImage, g_grayImage, g_maskImage;//定义原始图、目标图、灰度图、掩模图  
      7 int g_nFillMode = 1;//漫水填充的模式  
      8 int g_nLowDifference = 20, g_nUpDifference = 20;//负差最大值、正差最大值  
      9 int g_nConnectivity = 4;//表示floodFill函数标识符低八位的连通值  
     10 int g_bIsColor = true;//是否为彩色图的标识符布尔值  
     11 bool g_bUseMask = false;//是否显示掩膜窗口的布尔值  
     12 int g_nNewMaskVal = 255;//新的重新绘制的像素值 
     13 
     14 static void ShowHelpText()
     15 {
     16     //输出一些帮助信息    
     17     printf("
    
    
    	欢迎来到漫水填充示例程序~
    
    ");
     18     printf("
    
    	按键操作说明: 
    
    "
     19         "		鼠标点击图中区域- 进行漫水填充操作
    "
     20         "		键盘按键【ESC】- 退出程序
    "
     21         "		键盘按键【1】-  切换彩色图/灰度图模式
    "
     22         "		键盘按键【2】- 显示/隐藏掩膜窗口
    "
     23         "		键盘按键【3】- 恢复原始图像
    "
     24         "		键盘按键【4】- 使用空范围的漫水填充
    "
     25         "		键盘按键【5】- 使用渐变、固定范围的漫水填充
    "
     26         "		键盘按键【6】- 使用渐变、浮动范围的漫水填充
    "
     27         "		键盘按键【7】- 操作标志符的低八位使用4位的连接模式
    "
     28         "		键盘按键【8】- 操作标志符的低八位使用8位的连接模式
    "
     29         "
    
    								 by浅墨
    
    
    "
     30     );
     31 }
     32 
     33 //鼠标消息onMouse回调函数  
     34 static void onMouse(int event, int x, int y, int, void*)
     35 {
     36     // 若鼠标左键没有按下,便返回  
     37     if (event != CV_EVENT_LBUTTONDOWN)
     38         return;
     39     //-------------------【<1>调用floodFill函数之前的参数准备部分】---------------  
     40     Point seed = Point(x, y);
     41     int LowDifference = (g_nFillMode == 0) ? 0 : g_nLowDifference;//空范围的漫水填充,此值设为0,否则设为全局的g_nLowDifference  
     42     int UpDifference = g_nFillMode == 0 ? 0 : g_nUpDifference;//空范围的漫水填充,此值设为0,否则设为全局的g_nUpDifference  
     43     int flags = g_nConnectivity + (g_nNewMaskVal << 8) +
     44         (g_nFillMode == 1 ? CV_FLOODFILL_FIXED_RANGE : 0);//标识符的0~7位为g_nConnectivity,8~15位为g_nNewMaskVal左移8位的值,16~23位为CV_FLOODFILL_FIXED_RANGE或者0。  
     45 
     46                                                           //随机生成bgr值  
     47     int b = (unsigned)theRNG() & 255;//随机返回一个0~255之间的值  
     48     int g = (unsigned)theRNG() & 255;//随机返回一个0~255之间的值  
     49     int r = (unsigned)theRNG() & 255;//随机返回一个0~255之间的值  
     50     Rect ccomp;//定义重绘区域的最小边界矩形区域  
     51 
     52     Scalar newVal = g_bIsColor ? Scalar(b, g, r) : Scalar(r*0.299 + g*0.587 + b*0.114);//在重绘区域像素的新值,若是彩色图模式,取Scalar(b, g, r);若是灰度图模式,取Scalar(r*0.299 + g*0.587 + b*0.114)  
     53 
     54     Mat dst = g_bIsColor ? g_dstImage : g_grayImage;//目标图的赋值  
     55     int area;
     56 
     57     //--------------------【<2>正式调用floodFill函数】-----------------------------  
     58     if (g_bUseMask)
     59     {
     60         threshold(g_maskImage, g_maskImage, 1, 128, CV_THRESH_BINARY);
     61         area = floodFill(dst, g_maskImage, seed, newVal, &ccomp, Scalar(LowDifference, LowDifference, LowDifference),
     62             Scalar(UpDifference, UpDifference, UpDifference), flags);
     63         imshow("mask", g_maskImage);
     64     }
     65     else
     66     {
     67         area = floodFill(dst, seed, newVal, &ccomp, Scalar(LowDifference, LowDifference, LowDifference),
     68             Scalar(UpDifference, UpDifference, UpDifference), flags);
     69     }
     70 
     71     imshow("效果图", dst);
     72     cout << area << " 个像素被重绘
    ";
     73 }
     74 
     75 void main()
     76 {
     77     system("color 2F");//改变console字体颜色 
     78     g_srcImage = imread("E://lena.jpg", 1);//载入原图  
     79     if (!g_srcImage.data) { printf("Oh,no,读取图片image0错误~! 
    "); return; }
     80     ShowHelpText();
     81 
     82     g_srcImage.copyTo(g_dstImage);//拷贝源图到目标图  
     83     //cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);//转换三通道的image0到灰度图  
     84     g_maskImage.create(g_srcImage.rows + 2, g_srcImage.cols + 2, CV_8UC1);//利用image0的尺寸来初始化掩膜mask  
     85 
     86     namedWindow("效果图", CV_WINDOW_NORMAL);
     87     //创建Trackbar  
     88     createTrackbar("负差最大值", "效果图", &g_nLowDifference, 255, 0);
     89     createTrackbar("正差最大值", "效果图", &g_nUpDifference, 255, 0);
     90     //鼠标回调函数  
     91     setMouseCallback("效果图", onMouse, 0);
     92 
     93     //循环轮询按键  
     94     while (1)
     95     {
     96         //先显示效果图  
     97         imshow("效果图", g_bIsColor ? g_dstImage : g_grayImage);
     98         //获取键盘按键  
     99         int c = waitKey(0);
    100         //判断ESC是否按下,若按下便退出  
    101         if ((c & 255) == 27)
    102         {
    103             cout << "程序退出...........
    ";
    104             break;
    105         }
    106 
    107         //根据按键的不同,进行各种操作  
    108         switch ((char)c)
    109         {
    110         case '1':    //如果键盘“1”被按下,效果图在在灰度图,彩色图之间互换 
    111             if (g_bIsColor)//若原来为彩色,转为灰度图,并且将掩膜mask所有元素设置为0  
    112             {
    113                 cout << "键盘“1”被按下,切换彩色/灰度模式,当前操作为将【彩色模式】切换为【灰度模式】
    ";
    114                 cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
    115                 g_maskImage = Scalar::all(0);   //将mask所有元素设置为0  
    116                 g_bIsColor = false; //将标识符置为false,表示当前图像不为彩色,而是灰度  
    117             }
    118             else//若原来为灰度图,便将原来的彩图image0再次拷贝给image,并且将掩膜mask所有元素设置为0  
    119             {
    120                 cout << "键盘“1”被按下,切换彩色/灰度模式,当前操作为将【彩色模式】切换为【灰度模式】
    ";
    121                 g_srcImage.copyTo(g_dstImage);
    122                 g_maskImage = Scalar::all(0);
    123                 g_bIsColor = true;//将标识符置为true,表示当前图像模式为彩色  
    124             }
    125             break;
    126         case '2'://显示/隐藏掩膜窗口  
    127             if (g_bUseMask)
    128             {
    129                 destroyWindow("mask");
    130                 g_bUseMask = false;
    131             }
    132             else
    133             {
    134                 namedWindow("mask", 0);
    135                 g_maskImage = Scalar::all(0);
    136                 imshow("mask", g_maskImage);
    137                 g_bUseMask = true;
    138             }
    139             break;
    140         case '3'://恢复原始图像
    141             cout << "按键“3”被按下,恢复原始图像
    ";
    142             g_srcImage.copyTo(g_dstImage);
    143             cvtColor(g_dstImage, g_grayImage, COLOR_BGR2GRAY);
    144             g_maskImage = Scalar::all(0);
    145             break;
    146         case '4'://使用空范围的漫水填充 
    147             cout << "按键“4”被按下,使用空范围的漫水填充
    ";
    148             g_nFillMode = 0;
    149             break;
    150         case '5'://使用渐变、固定范围的漫水填充
    151             cout << "按键“5”被按下,使用渐变、固定范围的漫水填充
    ";
    152             g_nFillMode = 1;
    153             break;
    154         case '6'://使用渐变、浮动范围的漫水填充 
    155             cout << "按键“6”被按下,使用渐变、浮动范围的漫水填充
    ";
    156             g_nFillMode = 2;
    157             break;
    158         case '7'://操作标志符的低八位使用4位的连接模式  
    159             cout << "按键“7”被按下,操作标志符的低八位使用4位的连接模式
    ";
    160             g_nConnectivity = 4;
    161             break;  
    162         case '8'://操作标志符的低八位使用8位的连接模式
    163             cout << "按键“8”被按下,操作标志符的低八位使用8位的连接模式
    ";
    164             g_nConnectivity = 8;
    165             break;
    166         }
    167     }
    168 }

  • 相关阅读:
    第四章 瞬时响应:网站的高性能架构(待续)
    第三章 大型网站核心架构要素(待续)
    Luogu P1140 相似基因 【dp】By cellur925
    矩阵快速幂/矩阵加速线性数列 By cellur925
    [POI2008]BLO-Blockade 【无向图tarjan/鸽点】By cellur925
    USACO Training3.3 A Game【区间Dp】 By cellur925
    Luogu P2858 [USACO06FEB]奶牛零食Treats for the Cows 【区间dp】By cellur925
    Luogu P2921 在农场万圣节 【tarjan in 有向图】 By cellur925
    浅谈扩展欧几里得[exgcd] By cellur925
    NOIp 2014 联合权值 By cellur925
  • 原文地址:https://www.cnblogs.com/little-monkey/p/7598529.html
Copyright © 2011-2022 走看看