OpenCV简单的操作实例程序

//-----------------------------------【头文件包含部分】---------------------------------------
//      描述:包含程序所依赖的头文件
//----------------------------------------------------------------------------------------------
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/features2d.hpp"
#include<opencv2/opencv.hpp>
#include <iostream>
#include<vector>
//-----------------------------------【命名空间声明部分】---------------------------------------
//      描述:包含程序所使用的命名空间
//-----------------------------------------------------------------------------------------------
using namespace cv;
using namespace std;


//-----------------------------------【全局变量声明部分】--------------------------------------
//      描述:全局变量声明
//-----------------------------------------------------------------------------------------------
Mat g_srcImage, g_dstImage, g_grayImage, g_maskImage;//定义原始图、目标图、灰度图、掩模图
Mat element;
Mat  g_tmpImage;
Mat src1, src2;
vector<Vec3f> circles;
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;//新的重新绘制的像素值
//-----------------------------------【ShowHelpText( )函数】----------------------------------
//      描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
static void ShowHelpText()
{
    //输出一些帮助信息
    printf("\n\n\n\t欢迎来到漫水填充示例程序~\n\n");
    printf( "\n\n\t按键操作说明: \n\n"
            "\t\t鼠标点击图中区域- 进行漫水填充操作\n"
            "\t\t键盘按键【ESC】- 退出程序\n"
            "\t\t键盘按键【W】- 进行基于【resize】函数的图片放大\n"
            "\t\t键盘按键【S】- 进行基于【resize】函数的图片缩小\n"
            "\t\t键盘按键【A】- 进行基于【pyrUp】函数的图片放大\n"
            "\t\t键盘按键【D】- 进行基于【pyrDown】函数的图片缩小\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"
            "\t\t键盘按键【V】- 方框boxFilter滤波器使用\n"
            "\t\t键盘按键【b】- 二值化用\n"
            "\n\n\t\t\t\t\t\t\t\t by浅墨\n\n\n"
            );
}

//-----------------------------------【onMouse( )函数】--------------------------------------
//      描述:鼠标消息onMouse回调函数
//---------------------------------------------------------------------------------------------
static void onMouse( int event, int x, int y, int, void* )
{
    // 若鼠标左键没有按下,便返回
    if( event != CV_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
    int flags = g_nConnectivity + (g_nNewMaskVal << 8) +
            (g_nFillMode == 1 ? CV_FLOODFILL_FIXED_RANGE : 0);//标识符的0~7位为g_nConnectivity,8~15位为g_nNewMaskVal左移8位的值,16~23位为CV_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 )
    {
        threshold(g_maskImage, g_maskImage, 1, 128, CV_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("result", dst);
    cout << area << " 个像素被重绘\n";
}


//-----------------------------------【main( )函数】--------------------------------------------
//      描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main( int argc, char** argv )
{
    //改变console字体颜色
    system("color 2F");

    //载入原图
    g_srcImage = imread("C://Users//Administrator//Desktop//1.jpg", 1);

    if( !g_srcImage.data ) { printf("Oh,no,读取图片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

    namedWindow( "result",CV_WINDOW_AUTOSIZE );
    //参数赋值
    g_tmpImage = g_srcImage;
    g_dstImage = g_tmpImage;
    //创建Trackbar
    createTrackbar( "max value", "result", &g_nLowDifference, 255, 0 );
    createTrackbar( "mix value" ,"result", &g_nUpDifference, 255, 0 );

    //鼠标回调函数
    setMouseCallback( "result", onMouse, 0 );

    //循环轮询按键
    while(1)
    {
        //先显示result
        imshow("result", g_bIsColor ? g_dstImage : g_grayImage);

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

        //根据按键的不同,进行各种操作
        switch( (char)c )
        {
        //如果键盘“1”被按下,result在在灰度图,彩色图之间互换
        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;
        case 'a'://按键A按下,调用pyrUp函数
            pyrUp( g_tmpImage, g_dstImage, Size( g_tmpImage.cols*2, g_tmpImage.rows*2 ) );
            printf( ">检测到按键【A】被按下,开始进行基于【pyrUp】函数的图片放大:图片尺寸×2 \n" );
            break;

        case 'w'://按键W按下,调用resize函数
            resize(g_tmpImage,g_dstImage,Size( g_tmpImage.cols*2, g_tmpImage.rows*2 ));
            printf( ">检测到按键【W】被按下,开始进行基于【resize】函数的图片放大:图片尺寸×2 \n" );
            break;
        case 'd': //按键D按下,调用pyrDown函数
            pyrDown( g_tmpImage, g_dstImage, Size( g_tmpImage.cols/2, g_tmpImage.rows/2 ));
            printf( ">检测到按键【D】被按下,开始进行基于【pyrDown】函数的图片缩小:图片尺寸/2\n" );
            break;

        case  's' : //按键S按下,调用resize函数
            resize(g_tmpImage,g_dstImage,Size( g_tmpImage.cols/2, g_tmpImage.rows/2 ));
            printf( ">检测到按键【S】被按下,开始进行基于【resize】函数的图片缩小:图片尺寸/2\n" );
            break;
        case  'v' : //按键V按下,调用方框滤波函数
            boxFilter(g_tmpImage, g_dstImage, -1, Size(5, 5));
            printf( ">检测到按键【V】被按下,开始进行方框滤波/2\n" );
            break;
        case  'z' : //按键v按下,开始进行膨胀
            element = getStructuringElement(MORPH_RECT, Size(15, 15));
            dilate(g_tmpImage, g_dstImage, element);
            printf( ">检测到按键【z】被按下,开始进行膨胀/2\n" );
            break;
        case  'b' : //按键x按下,开始圆形检测
            //adaptiveThreshold(g_tmpImage, g_dstImage,255.0, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 27, -25);
            threshold(g_tmpImage, g_dstImage, 150 , 255 ,0);
            printf( ">检测到按键【b】被按下,开始进行二值化/2\n" );
            break;
        case  'x' : //按键x按下,开始圆形检测
            cvtColor(g_tmpImage, src1, CV_BGR2GRAY);//转化边缘检测后的图为灰度图
            GaussianBlur(src1, src2, Size(9, 9), 2, 2);
            HoughCircles(src2, circles, CV_HOUGH_GRADIENT, 1.5, 10, 200, 100, 0, 0);
            printf( ">检测到按键【x】被按下,%d,开始圆形检测/2\n",circles.size() );
            for (size_t i = 0; i < circles.size(); i++)
            {
                Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
                int radius = cvRound(circles[i][2]);
                circle(g_dstImage, center, 3, Scalar(0, 255, 0), -1, 8, 0);
                circle(g_dstImage, center, radius, Scalar(155, 50, 255), 3, 8, 0);
            }
            printf( ">检测到按键【x】被按下,开始圆形检测/2\n" );
            break;
        case  'n' : //按键x按下,开始圆形检测
            Canny(g_tmpImage, g_dstImage, 150, 100, 3);//进行轮廓检测
            printf( ">检测到按键【n】被按下,开始边缘检测/2\n" );
            break;

        }
        //将g_dstImage赋给g_tmpImage,方便下一次循环
        imshow( "result", g_dstImage );
        g_tmpImage = g_dstImage;
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

vqt5_qt6

你的鼓励是我们创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值