Opencv之漫水填充效果


下面是opencv的漫水填充效果代碼

這篇文章僅限個人的筆記

沒有詳細的注釋

放代碼

 

這是簡單的示范

int main()//*******************簡單的漫水填充算法實例     
{
    VideoCapture capture(0);
    Mat picture ;
    Mat img;
    Rect ccomp;
    cout << "漫水填充的簡單算法";
    while (1)
    {
        capture >> picture;
        imshow("Original picture", picture);
        floodFill(picture, Point(20, 30), Scalar(155, 255, 55), &ccomp, Scalar(20, 20, 20), Scalar(20, 20, 20));
        imshow("Dealed picture", picture);
        waitKey(1);
    }
    return 0;
}

下面是復雜的正文

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;

Mat g_srcImage, g_dstImage, g_grayImage, g_maskImage;//定義原始圖、目標圖、灰度圖、掩模圖
int g_nFillMode = 1;//漫水填充的模式
int g_nLowDifference = 20, g_nUpDifference = 20;//負差最大值、正差最大值
int g_nConnectivity = 4;//表示floodFill函數標識符低八位的連通值
int g_bIsColor = true;//是否為彩色圖的標識符布爾值
bool g_bUseMask = false;//是否顯示掩膜窗口的布爾值
int g_nNewMaskVal = 255;//新的重新繪制的像素值


static void ShowHelpText()
{

    //輸出一些幫助信息  
    printf("\n\n\t歡迎來到漫水填充示例程序~");
    printf("\n\n\t本示例根據鼠標選取的點搜索圖像中與之顏色相近的點,並用不同顏色標注。");

    printf("\n\n\t按鍵操作說明: \n\n"
        "\t\t鼠標點擊圖中區域- 進行漫水填充操作\n"
        "\t\t鍵盤按鍵【ESC】- 退出程序\n"
        "\t\t鍵盤按鍵【1】-  切換彩色圖/灰度圖模式\n"
        "\t\t鍵盤按鍵【2】- 顯示/隱藏掩膜窗口\n"
        "\t\t鍵盤按鍵【3】- 恢復原始圖像\n"
        "\t\t鍵盤按鍵【4】- 使用空范圍的漫水填充\n"
        "\t\t鍵盤按鍵【5】- 使用漸變、固定范圍的漫水填充\n"
        "\t\t鍵盤按鍵【6】- 使用漸變、浮動范圍的漫水填充\n"
        "\t\t鍵盤按鍵【7】- 操作標志符的低八位使用4位的連接模式\n"
        "\t\t鍵盤按鍵【8】- 操作標志符的低八位使用8位的連接模式\n\n");
}

//   鼠標消息onMouse回調函數
static void onMouse(int event, int x, int y, int, void*)
{
    // 若鼠標左鍵沒有按下,便返回
    //此句代碼的OpenCV2版為:
    //if( event != CV_EVENT_LBUTTONDOWN )
    //此句代碼的OpenCV3版為:
    if (event != EVENT_LBUTTONDOWN)
        return;

    //-------------------【<1>調用floodFill函數之前的參數准備部分】---------------
    Point seed = Point(x, y);
    int LowDifference = g_nFillMode == 0 ? 0 : g_nLowDifference;//空范圍的漫水填充,此值設為0,否則設為全局的g_nLowDifference
    int UpDifference = g_nFillMode == 0 ? 0 : g_nUpDifference;//空范圍的漫水填充,此值設為0,否則設為全局的g_nUpDifference

    //標識符的0~7位為g_nConnectivity,8~15位為g_nNewMaskVal左移8位的值,16~23位為CV_FLOODFILL_FIXED_RANGE或者0。
    //此句代碼的OpenCV2版為:
    //int flags = g_nConnectivity + (g_nNewMaskVal << 8) +(g_nFillMode == 1 ? CV_FLOODFILL_FIXED_RANGE : 0);
    //此句代碼的OpenCV3版為:
    int flags = g_nConnectivity + (g_nNewMaskVal << 8) + (g_nFillMode == 1 ? FLOODFILL_FIXED_RANGE : 0);

    //隨機生成bgr值
    int b = (unsigned)theRNG() & 255;//隨機返回一個0~255之間的值
    int g = (unsigned)theRNG() & 255;//隨機返回一個0~255之間的值
    int r = (unsigned)theRNG() & 255;//隨機返回一個0~255之間的值
    Rect ccomp;//定義重繪區域的最小邊界矩形區域

    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)

    Mat dst = g_bIsColor ? g_dstImage : g_grayImage;//目標圖的賦值
    int area;

    //--------------------【<2>正式調用floodFill函數】-----------------------------
    if (g_bUseMask)
    {
        //此句代碼的OpenCV2版為:
        //threshold(g_maskImage, g_maskImage, 1, 128, CV_THRESH_BINARY);
        //此句代碼的OpenCV3版為:
        threshold(g_maskImage, g_maskImage, 1, 128, THRESH_BINARY);
        area = floodFill(dst, g_maskImage, seed, newVal, &ccomp, Scalar(LowDifference, LowDifference, LowDifference),
            Scalar(UpDifference, UpDifference, UpDifference), flags);
        imshow("mask", g_maskImage);
    }
    else
    {
        area = floodFill(dst, seed, newVal, &ccomp, Scalar(LowDifference, LowDifference, LowDifference),
            Scalar(UpDifference, UpDifference, UpDifference), flags);
    }

    imshow("效果圖", dst);
    cout << area << " 個像素被重繪\n";
}


//-----------------------------------【main( )函數】--------------------------------------------  
//      描述:控制台應用程序的入口函數,我們的程序從這里開始  
//-----------------------------------------------------------------------------------------------  
int main(int argc, char** argv)
{
    //改變console字體顏色  
    system("color 02");

    //載入原圖
    g_srcImage = imread("D:\\2.jpg", 1);

    if (!g_srcImage.data) 
    { printf("讀取圖片image0錯誤~! \n"); return false; }

    //顯示幫助文字
    ShowHelpText();

    g_srcImage.copyTo(g_dstImage);//拷貝源圖到目標圖
    cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);//轉換三通道的image0到灰度圖
    g_maskImage.create(g_srcImage.rows + 2, g_srcImage.cols + 2, CV_8UC1);//利用image0的尺寸來初始化掩膜mask

    //此句代碼的OpenCV2版為:
    //namedWindow( "效果圖",CV_WINDOW_AUTOSIZE );
    //此句代碼的OpenCV2版為:
    namedWindow("效果圖", WINDOW_AUTOSIZE);


    //創建Trackbar
    createTrackbar("負差最大值", "效果圖", &g_nLowDifference, 255, 0);
    createTrackbar("正差最大值", "效果圖", &g_nUpDifference, 255, 0);

    //鼠標回調函數
    setMouseCallback("效果圖", onMouse, 0);

    //循環輪詢按鍵
    while (1)
    {
        //先顯示效果圖
        imshow("效果圖", g_bIsColor ? g_dstImage : g_grayImage);

        //獲取鍵盤按鍵
        int c = waitKey(0);
        //判斷ESC是否按下,若按下便退出
        if ((c & 255) == 27)
        {
            cout << "程序退出...........\n";
            break;
        }

        //根據按鍵的不同,進行各種操作
        switch ((char)c)
        {
            //如果鍵盤“1”被按下,效果圖在在灰度圖,彩色圖之間互換
        case '1':
            if (g_bIsColor)//若原來為彩色,轉為灰度圖,並且將掩膜mask所有元素設置為0
            {
                cout << "鍵盤“1”被按下,切換彩色/灰度模式,當前操作為將【彩色模式】切換為【灰度模式】\n";
                cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
                g_maskImage = Scalar::all(0);    //將mask所有元素設置為0
                g_bIsColor = false;    //將標識符置為false,表示當前圖像不為彩色,而是灰度
            }
            else//若原來為灰度圖,便將原來的彩圖image0再次拷貝給image,並且將掩膜mask所有元素設置為0
            {
                cout << "鍵盤“1”被按下,切換彩色/灰度模式,當前操作為將【彩色模式】切換為【灰度模式】\n";
                g_srcImage.copyTo(g_dstImage);
                g_maskImage = Scalar::all(0);
                g_bIsColor = true;//將標識符置為true,表示當前圖像模式為彩色
            }
            break;
            //如果鍵盤按鍵“2”被按下,顯示/隱藏掩膜窗口
        case '2':
            if (g_bUseMask)
            {
                destroyWindow("mask");
                g_bUseMask = false;
            }
            else
            {
                namedWindow("mask", 0);
                g_maskImage = Scalar::all(0);
                imshow("mask", g_maskImage);
                g_bUseMask = true;
            }
            break;
            //如果鍵盤按鍵“3”被按下,恢復原始圖像
        case '3':
            cout << "按鍵“3”被按下,恢復原始圖像\n";
            g_srcImage.copyTo(g_dstImage);
            cvtColor(g_dstImage, g_grayImage, COLOR_BGR2GRAY);
            g_maskImage = Scalar::all(0);
            break;
            //如果鍵盤按鍵“4”被按下,使用空范圍的漫水填充
        case '4':
            cout << "按鍵“4”被按下,使用空范圍的漫水填充\n";
            g_nFillMode = 0;
            break;
            //如果鍵盤按鍵“5”被按下,使用漸變、固定范圍的漫水填充
        case '5':
            cout << "按鍵“5”被按下,使用漸變、固定范圍的漫水填充\n";
            g_nFillMode = 1;
            break;
            //如果鍵盤按鍵“6”被按下,使用漸變、浮動范圍的漫水填充
        case '6':
            cout << "按鍵“6”被按下,使用漸變、浮動范圍的漫水填充\n";
            g_nFillMode = 2;
            break;
            //如果鍵盤按鍵“7”被按下,操作標志符的低八位使用4位的連接模式
        case '7':
            cout << "按鍵“7”被按下,操作標志符的低八位使用4位的連接模式\n";
            g_nConnectivity = 4;
            break;
            //如果鍵盤按鍵“8”被按下,操作標志符的低八位使用8位的連接模式
        case '8':
            cout << "按鍵“8”被按下,操作標志符的低八位使用8位的連接模式\n";
            g_nConnectivity = 8;
            break;
        }
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM