天天看點

OpenCV的形态學操作

/********************************************************************
    建立日期:    2020/10/06
    建立時間:    18:30
    檔案名字:   C:\Users\17806\Desktop\M\Project1\Project1\test.cpp
    ------------------------------
    檔案功能:
    
    
    ------------------------------
    作者:        K&J
    ------------------------------
    修改人:     
    ------------------------------
    版本号:     V1.0.1
    版權所有:   K&J(康傑)
*********************************************************************/
//---------------------------------【頭檔案、命名空間包含部分】----------------------------
//      描述:包含程式所使用的頭檔案和命名空間
//------------------------------------------------------------------------------------------------
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;

//-----------------------------------【全局變量聲明部分】-----------------------------------
//      描述:全局變量聲明
//-----------------------------------------------------------------------------------------------
Mat g_srcImage, g_dstImage;//原始圖和效果圖
int g_nElementShape = MORPH_RECT;//元素結構的形狀

//變量接收的TrackBar位置參數
int g_nMaxIterationNum = 10;
int g_nOpenCloseNum = 0;
int g_nErodeDilateNum = 0;
int g_nTopBlackHatNum = 0;

//-----------------------------------【全局函數聲明部分】--------------------------------------
//      描述:全局函數聲明
//-----------------------------------------------------------------------------------------------
static void on_OpenClose(int, void*);//回調函數
static void on_ErodeDilate(int, void*);//回調函數
static void on_TopBlackHat(int, void*);//回調函數
static void ShowHelpText();

//-----------------------------------【main( )函數】--------------------------------------------
//      描述:控制台應用程式的入口函數,我們的程式從這裡開始
//-----------------------------------------------------------------------------------------------
int main()
{
    //改變console字型顔色
    system("color 2F");

    ShowHelpText();

    //載入原圖
    g_srcImage = imread("1.jpg");
    if (!g_srcImage.data) 
    { 
        printf("Oh,no,讀取srcImage錯誤~! \n"); return false;
    }

    //顯示原始圖
    namedWindow("【原始圖】");
    imshow("【原始圖】", g_srcImage);

    //建立三個視窗
    namedWindow("【開運算/閉運算】", 1);
    namedWindow("【腐蝕/膨脹】", 1);
    namedWindow("【頂帽/黑帽】", 1);

    //參數指派
    g_nOpenCloseNum = 9;
    g_nErodeDilateNum = 9;
    g_nTopBlackHatNum = 2;

    //分别為三個視窗建立滾動條
    createTrackbar("疊代值", "【開運算/閉運算】", 
                    &g_nOpenCloseNum, g_nMaxIterationNum * 2 + 1, on_OpenClose);
    createTrackbar("疊代值", "【腐蝕/膨脹】",
                    &g_nErodeDilateNum, g_nMaxIterationNum * 2 + 1, on_ErodeDilate);
    createTrackbar("疊代值", "【頂帽/黑帽】", 
                    &g_nTopBlackHatNum, g_nMaxIterationNum * 2 + 1, on_TopBlackHat);

    //輪詢擷取按鍵資訊
    while (1)
    {
        int c;

        //執行回調函數
        on_OpenClose(g_nOpenCloseNum, 0);
        on_ErodeDilate(g_nErodeDilateNum, 0);
        on_TopBlackHat(g_nTopBlackHatNum, 0);

        //擷取按鍵
        c = waitKey(0);

        //按下鍵盤按鍵Q或者ESC,程式退出
        if ((char)c == 'q' || (char)c == 27)
            break;
        //按下鍵盤按鍵1,使用橢圓(Elliptic)結構元素結構元素MORPH_ELLIPSE
        if ((char)c == 49)//鍵盤按鍵1的ASII碼為49
            g_nElementShape = MORPH_ELLIPSE;
        //按下鍵盤按鍵2,使用矩形(Rectangle)結構元素MORPH_RECT
        else if ((char)c == 50)//鍵盤按鍵2的ASII碼為50
            g_nElementShape = MORPH_RECT;
        //按下鍵盤按鍵3,使用十字形(Cross-shaped)結構元素MORPH_CROSS
        else if ((char)c == 51)//鍵盤按鍵3的ASII碼為51
            g_nElementShape = MORPH_CROSS;
        //按下鍵盤按鍵space,在矩形、橢圓、十字形結構元素中循環
        else if ((char)c == ' ')
            g_nElementShape = (g_nElementShape + 1) % 3;
    }

    return 0;
}


//-----------------------------------【on_OpenClose( )函數】----------------------------------
//      描述:【開運算/閉運算】視窗的回調函數
//-----------------------------------------------------------------------------------------------
static void on_OpenClose(int, void*)
{
    //偏移量的定義
    int offset = g_nOpenCloseNum - g_nMaxIterationNum;//偏移量
    int Absolute_offset = offset > 0 ? offset : -offset;//偏移量絕對值
                                                        //自定義核
    Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
    //進行操作
    if (offset < 0)
        morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element);
    else
        morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element);

    //顯示圖像
    imshow("【開運算/閉運算】", g_dstImage);
}


//-----------------------------------【on_ErodeDilate( )函數】----------------------------------
//      描述:【腐蝕/膨脹】視窗的回調函數
//-----------------------------------------------------------------------------------------------
static void on_ErodeDilate(int, void*)
{
    //偏移量的定義
    int offset = g_nErodeDilateNum - g_nMaxIterationNum;    //偏移量
    int Absolute_offset = offset > 0 ? offset : -offset;//偏移量絕對值
                                                        //自定義核
    Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
    //進行操作
    if (offset < 0)
        erode(g_srcImage, g_dstImage, element);
    else
        dilate(g_srcImage, g_dstImage, element);
    //顯示圖像
    imshow("【腐蝕/膨脹】", g_dstImage);
}


//-----------------------------------【on_TopBlackHat( )函數】--------------------------------
//      描述:【頂帽運算/黑帽運算】視窗的回調函數
//----------------------------------------------------------------------------------------------
static void on_TopBlackHat(int, void*)
{
    //偏移量的定義
    int offset = g_nTopBlackHatNum - g_nMaxIterationNum;//偏移量
    int Absolute_offset = offset > 0 ? offset : -offset;//偏移量絕對值
                                                        //自定義核
    Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
    //進行操作
    if (offset < 0)
        morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT, element);
    else
        morphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element);
    //顯示圖像
    imshow("【頂帽/黑帽】", g_dstImage);
}

//-----------------------------------【ShowHelpText( )函數】----------------------------------
//      描述:輸出一些幫助資訊
//----------------------------------------------------------------------------------------------
static void ShowHelpText()
{
    //輸出一些幫助資訊
    printf("\n\t請調整滾動條觀察圖像效果\n\n");
    printf("\n\t按鍵操作說明: \n\n"
        "\t\t鍵盤按鍵【ESC】或者【Q】- 退出程式\n"
        "\t\t鍵盤按鍵【1】- 使用橢圓(Elliptic)結構元素\n"
        "\t\t鍵盤按鍵【2】- 使用矩形(Rectangle )結構元素\n"
        "\t\t鍵盤按鍵【3】- 使用十字型(Cross-shaped)結構元素\n"
        "\t\t鍵盤按鍵【空格SPACE】- 在矩形、橢圓、十字形結構元素中循環\n");
}      

繼續閱讀