• 边缘检测(OpenCV)


    梯度算子

    不变矩

    #include <opencv2/highgui.hpp>
    #include <opencv2/imgproc.hpp>
    #include <iostream>
    #include <cmath>
    
    using namespace std;
    using namespace cv;
    
    //原图,原图的灰度版,目标图
    Mat g_srcImage, g_srcGrayImage, g_dstImage;
    
    //Canny边缘检测相关变量
    Mat g_cannyDetectedEdges;
    int g_cannyLowThreshold = 1;//TrackBar位置参数  
    
    //Sobel边缘检测相关变量
    Mat g_sobelGradient_X, g_sobelGradient_Y;
    Mat g_sobelAbsGradient_X, g_sobelAbsGradient_Y;
    int g_sobelKernelSize = 1;//TrackBar位置参数  
    
    //Scharr滤波器相关变量
    Mat g_scharrGradient_X, g_scharrGradient_Y;
    Mat g_scharrAbsGradient_X, g_scharrAbsGradient_Y;
    
    static void ShowHelpText();
    static void on_Canny(int, void*);//Canny边缘检测窗口滚动条的回调函数
    static void on_Sobel(int, void*);//Sobel边缘检测窗口滚动条的回调函数
    void Scharr();// 封装了Scharr边缘检测相关代码的函数
    void laplacian(); // 封装了laplacian边缘检测相关代码的函数
    
    /* 不变矩 */
    void hu(Mat image);
    
    /* 轮廓 */
    Mat src, dst, drawImage;
    const char* result = "moments_demo";
    int threshold_value = 120;
    int threshold_max = 255;
    RNG rng(12345);
    void Moments_demo(int, void*);
    void moments_demo_start();
    
    int main(int argc, char** argv)
    {
        ShowHelpText();
        g_srcImage = imread("1.png");
        if (!g_srcImage.data) { printf("Oh,no,读取srcImage错误~! 
    "); return false; }
        namedWindow("【原始图】");
        imshow("【原始图】", g_srcImage);
    
        g_dstImage.create(g_srcImage.size(), g_srcImage.type());
    
        cvtColor(g_srcImage, g_srcGrayImage, COLOR_BGR2GRAY);
    
        namedWindow("【效果图】Canny边缘检测", WINDOW_AUTOSIZE);
        namedWindow("【效果图】Sobel边缘检测", WINDOW_AUTOSIZE);
    
        createTrackbar("参数值:", "【效果图】Canny边缘检测", &g_cannyLowThreshold, 120, on_Canny);
        createTrackbar("参数值:", "【效果图】Sobel边缘检测", &g_sobelKernelSize, 3, on_Sobel);
    
        on_Canny(0, 0);
        on_Sobel(0, 0);
    
        Scharr();
        laplacian();
        // moments_demo_start();
    
        waitKey();
        return 0;
    }
    
    static void ShowHelpText()
    {
        printf("当前使用的OpenCV版本为:" CV_VERSION);
        printf("
    运行成功,请调整滚动条观察图像效果
    ");
    }
    
    void on_Canny(int, void*)
    {
        // 先使用 3x3内核来降噪
        blur(g_srcGrayImage, g_cannyDetectedEdges, Size(3, 3));
    
        // 运行我们的Canny算子
        Canny(g_cannyDetectedEdges, g_cannyDetectedEdges, g_cannyLowThreshold, g_cannyLowThreshold * 3, 3);
    
        //先将g_dstImage内的所有元素设置为0 
        g_dstImage = Scalar::all(0);
    
        //使用Canny算子输出的边缘图g_cannyDetectedEdges作为掩码,来将原图g_srcImage拷到目标图g_dstImage中
        g_srcImage.copyTo(g_dstImage, g_cannyDetectedEdges);
    
        //显示效果图
        imshow("【效果图】Canny边缘检测", g_dstImage);
    
        //计算边缘图像不变矩
        hu(g_dstImage);
    }
    
    void on_Sobel(int, void*)
    {
        Sobel(g_srcImage, g_sobelGradient_X, CV_16S, 1, 0, (2 * g_sobelKernelSize + 1), 1, 1, BORDER_DEFAULT);
        convertScaleAbs(g_sobelGradient_X, g_sobelAbsGradient_X);//计算绝对值,并将结果转换成8位
        Sobel(g_srcImage, g_sobelGradient_Y, CV_16S, 0, 1, (2 * g_sobelKernelSize + 1), 1, 1, BORDER_DEFAULT);
        convertScaleAbs(g_sobelGradient_Y, g_sobelAbsGradient_Y);//计算绝对值,并将结果转换成8位
        addWeighted(g_sobelAbsGradient_X, 0.5, g_sobelAbsGradient_Y, 0.5, 0, g_dstImage);
        imshow("【效果图】Sobel边缘检测", g_dstImage);
    
    }
    
    void Scharr() // 
    {
        Scharr(g_srcImage, g_scharrGradient_X, CV_16S, 1, 0, 1, 0, BORDER_DEFAULT);
        convertScaleAbs(g_scharrGradient_X, g_scharrAbsGradient_X);//计算绝对值,并将结果转换成8位
        Scharr(g_srcImage, g_scharrGradient_Y, CV_16S, 0, 1, 1, 0, BORDER_DEFAULT);
        convertScaleAbs(g_scharrGradient_Y, g_scharrAbsGradient_Y);//计算绝对值,并将结果转换成8位
        addWeighted(g_scharrAbsGradient_X, 0.5, g_scharrAbsGradient_Y, 0.5, 0, g_dstImage);
        imshow("【效果图】Scharr滤波器", g_dstImage);
    }
    
    void laplacian()
    {
        Mat result;
        int ksize = 5; // 当ksize==1时,3*3的拉普拉斯算子
        int depth = CV_16S; // 目标图像的深度,当depth==-1时,为原图图像深度
        Laplacian(g_srcImage, g_dstImage, depth, ksize);
        // imshow("【效果图】laplacian滤波器", g_dstImage);
        convertScaleAbs(g_dstImage, result); // (3 + 1) * 0.25
        imshow("Laplacian", result);
    }
    
    void Moments_demo(int, void*)
    {
        //提取图像边缘
        Mat canny_out;
        Canny(dst, canny_out, threshold_value, threshold_value * 2, 3, false);
        //imshow("canny image", canny_out);
    
        //发现轮廓,找到图像轮廓
        vector<vector<Point>> contours;
        vector<Vec4i> hierachy;
        findContours(canny_out, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
    
        //计算每个轮廓对象的矩
        vector<    Moments> contours_moments(contours.size());
        vector<Point2f> centers(contours.size());
        for (size_t i = 0; i < contours.size(); i++)
        {
            //计算矩
            contours_moments[i] = moments(contours[i]);
            //moments(InputArray  array,//输入数据
            //bool   binaryImage = false // 是否为二值图像
            centers[i] = Point(static_cast<float>(contours_moments[i].m10 / contours_moments[i].m00), static_cast<float>(contours_moments[i].m01 / contours_moments[i].m00));
            //图像中心Center(x0, y0)=(m10/m00,m01/m00)
        }
    
        src.copyTo(drawImage);
        for (size_t i = 0; i < contours.size(); i++)
        {
            printf("centers point x:%.2f,y:%.2f
    ", centers[i].x, centers[i].y);
            printf("contours %d Area:%.2f Arc length:%.2f 
    ", i, contourArea(contours[i]), arcLength(contours[i], true));
            Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
            drawContours(drawImage, contours, i, color, 2, LINE_AA, hierachy, 0, Point(0, 0));//绘制轮廓
            circle(drawImage, centers[i], 2, color, 2, LINE_AA);//绘制图形中心
        }
        imshow(result, drawImage);
        return;
    }
    
    void moments_demo_start()
    {
        src = imread("1.png");
        if (!src.data)
        {
            printf("could not load image...
    ");
        }
        char input[] = "gray image";
        namedWindow(input, WINDOW_AUTOSIZE);
        namedWindow(result, WINDOW_AUTOSIZE);
        //输入图像转为灰度图像
        cvtColor(src, dst, COLOR_BGR2GRAY);
        GaussianBlur(dst, dst, Size(3, 3), 0, 0);
        imshow(input, dst);
    
        const char* thresh = "threshold value";
        createTrackbar(thresh, result, &threshold_value, threshold_max, Moments_demo);
        Moments_demo(0, 0);
    }
    
    void hu(Mat image)
    {
        cvtColor(image, image, COLOR_BGR2GRAY);
        Moments mts = moments(image);
        double hu[7];
        HuMoments(mts, hu);
        cout << endl << "Canny算子处理后的图像的不变矩 :" << endl;
        for (int i = 0; i < 7; i++)
        {
            cout << "η" << i+1 << '=' << abs(log(abs(hu[i]))) << endl;
        }
    }
    edgedetection

    角点检测

    #include <opencv2/opencv.hpp>  
    #include <opencv2/imgproc/imgproc.hpp>  
    using namespace cv;
    
    int main()
    {
        //以灰度模式载入图像并显示
        Mat srcImage = imread("1.jpg", 0);
        imshow("原始图", srcImage);
    
        //进行Harris角点检测找出角点
        Mat cornerStrength;
        cornerHarris(srcImage, cornerStrength, 2, 3, 0.01);
    
        //对灰度图进行阈值操作,得到二值图并显示  
        Mat harrisCorner;
        threshold(cornerStrength, harrisCorner, 0.00001, 255, THRESH_BINARY);
        imshow("角点检测后的二值效果图", harrisCorner);
    
        waitKey(0);
        return 0;
    }
    cornerharris

     角点检测综合示例

    #include <opencv2/opencv.hpp>
    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    using namespace cv;
    using namespace std;
     
    #define WINDOW_NAME1 "【程序窗口1】"        //为窗口标题定义的宏  
    #define WINDOW_NAME2 "【程序窗口2】"        //为窗口标题定义的宏  
    
    Mat g_srcImage, g_srcImage1, g_grayImage;
    int thresh = 30; //当前阈值
    int max_thresh = 175; //最大阈值
    
    void on_CornerHarris(int, void*);//回调函数
    static void ShowHelpText();
    
    int main(int argc, char** argv)
    {
        ShowHelpText();
    
        //【1】载入原始图并进行克隆保存
        g_srcImage = imread("1.jpg", 1);
        if (!g_srcImage.data) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! 
    "); return false; }
        imshow("原始图", g_srcImage);
        g_srcImage1 = g_srcImage.clone();
    
        //【2】存留一张灰度图
        cvtColor(g_srcImage1, g_grayImage, COLOR_BGR2GRAY);
    
        //【3】创建窗口和滚动条
        namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);
        createTrackbar("阈值: ", WINDOW_NAME1, &thresh, max_thresh, on_CornerHarris);
    
        //【4】调用一次回调函数,进行初始化
        on_CornerHarris(0, 0);
    
        waitKey(0);
        return(0);
    }
    
    void on_CornerHarris(int, void*)
    {
        //---------------------------【1】定义一些局部变量-----------------------------
        Mat dstImage;//目标图
        Mat normImage;//归一化后的图
        Mat scaledImage;//线性变换后的八位无符号整型的图
    
        //---------------------------【2】初始化---------------------------------------
        //置零当前需要显示的两幅图,即清除上一次调用此函数时他们的值
        dstImage = Mat::zeros(g_srcImage.size(), CV_32FC1);
        g_srcImage1 = g_srcImage.clone();
    
        //---------------------------【3】正式检测-------------------------------------
        //进行角点检测
        cornerHarris(g_grayImage, dstImage, 2, 3, 0.04, BORDER_DEFAULT);
    
        // 归一化与转换
        normalize(dstImage, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
        convertScaleAbs(normImage, scaledImage);//将归一化后的图线性变换成8位无符号整型 
    
        //---------------------------【4】进行绘制-------------------------------------
        // 将检测到的,且符合阈值条件的角点绘制出来
        for (int j = 0; j < normImage.rows; j++)
        {
            for (int i = 0; i < normImage.cols; i++)
            {
                if ((int)normImage.at<float>(j, i) > thresh + 80)
                {
                    circle(g_srcImage1, Point(i, j), 5, Scalar(10, 10, 255), 2, 8, 0);
                    circle(scaledImage, Point(i, j), 5, Scalar(0, 10, 255), 2, 8, 0);
                }
            }
        }
        //---------------------------【4】显示最终效果---------------------------------
        imshow(WINDOW_NAME1, g_srcImage1);
        imshow(WINDOW_NAME2, scaledImage);
    
    }
    
    static void ShowHelpText()
    {
        printf("当前使用的OpenCV版本为:" CV_VERSION);
        printf("【欢迎来到Harris角点检测示例程序~】");
        printf("
    请调整滚动条观察图像效果");
    }
    cornerharris1

    shi_Tomashi角点检测

    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    #include <iostream>
    using namespace cv;
    using namespace std;
    
    #define WINDOW_NAME "【Shi-Tomasi角点检测】"        //为窗口标题定义的宏 
    
    Mat g_srcImage, g_grayImage;
    int g_maxCornerNumber = 33;
    int g_maxTrackbarNumber = 500;
    RNG g_rng(12345);//初始化随机数生成器
    
    void on_GoodFeaturesToTrack(int, void*)
    {
        //【1】对变量小于等于1时的处理
        if (g_maxCornerNumber <= 1) { g_maxCornerNumber = 1; }
    
        //【2】Shi-Tomasi算法(goodFeaturesToTrack函数)的参数准备
        vector<Point2f> corners;
        double qualityLevel = 0.01;//角点检测可接受的最小特征值
        double minDistance = 10;//角点之间的最小距离
        int blockSize = 3;//计算导数自相关矩阵时指定的邻域范围
        double k = 0.04;//权重系数
        Mat copy = g_srcImage.clone();    //复制源图像到一个临时变量中,作为感兴趣区域
    
        //【3】进行Shi-Tomasi角点检测
        goodFeaturesToTrack(g_grayImage,//输入图像
            corners,//检测到的角点的输出向量
            g_maxCornerNumber,//角点的最大数量
            qualityLevel,//角点检测可接受的最小特征值
            minDistance,//角点之间的最小距离
            Mat(),//感兴趣区域
            blockSize,//计算导数自相关矩阵时指定的邻域范围
            false,//不使用Harris角点检测
            k);//权重系数
    
    
        //【4】输出文字信息
        cout << "	>此次检测到的角点数量为:" << corners.size() << endl;
    
        //【5】绘制检测到的角点
        int r = 4;
        for (int i = 0; i < corners.size(); i++)
        {
            //以随机的颜色绘制出角点
            circle(copy, corners[i], r, Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255),
                g_rng.uniform(0, 255)), -1, 8, 0);
        }
    
        //【6】显示(更新)窗口
        imshow(WINDOW_NAME, copy);
    }
    
    
    //-----------------------------------【ShowHelpText( )函数】----------------------------------
    //          描述:输出一些帮助信息
    //----------------------------------------------------------------------------------------------
    static void ShowHelpText()
    {
        printf("当前使用的OpenCV版本为:" CV_VERSION);
        printf("欢迎来到【Shi-Tomasi角点检测】示例程序
    ");
        printf("请调整滑动条观察图像效果
    ");
    
    }
    
    int main()
    {
        ShowHelpText();
    
        //【1】载入源图像并将其转换为灰度图
        g_srcImage = imread("1.jpg", 1);
        cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
    
        //【2】创建窗口和滑动条,并进行显示和回调函数初始化
        namedWindow(WINDOW_NAME, WINDOW_AUTOSIZE);
        createTrackbar("最大角点数", WINDOW_NAME, &g_maxCornerNumber, g_maxTrackbarNumber, on_GoodFeaturesToTrack);
        imshow(WINDOW_NAME, g_srcImage);
        on_GoodFeaturesToTrack(0, 0);
    
        waitKey(0);
        return(0);
    }
    Tomashi

    亚像素级角点检测

    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    #include <iostream>
    using namespace cv;
    using namespace std;
    
    #define WINDOW_NAME "【亚像素级角点检测】"        //为窗口标题定义的宏 
    
    Mat g_srcImage, g_grayImage;
    int g_maxCornerNumber = 33;
    int g_maxTrackbarNumber = 500;
    RNG g_rng(12345);//初始化随机数生成器
    
    void on_GoodFeaturesToTrack(int, void*)
    {
        //【1】对变量小于等于1时的处理
        if (g_maxCornerNumber <= 1) { g_maxCornerNumber = 1; }
    
        //【2】Shi-Tomasi算法(goodFeaturesToTrack函数)的参数准备
        vector<Point2f> corners;
        double qualityLevel = 0.01;//角点检测可接受的最小特征值
        double minDistance = 10;//角点之间的最小距离
        int blockSize = 3;//计算导数自相关矩阵时指定的邻域范围
        double k = 0.04;//权重系数
        Mat copy = g_srcImage.clone();    //复制源图像到一个临时变量中,作为感兴趣区域
    
        //【3】进行Shi-Tomasi角点检测
        goodFeaturesToTrack(g_grayImage,//输入图像
            corners,//检测到的角点的输出向量
            g_maxCornerNumber,//角点的最大数量
            qualityLevel,//角点检测可接受的最小特征值
            minDistance,//角点之间的最小距离
            Mat(),//感兴趣区域
            blockSize,//计算导数自相关矩阵时指定的邻域范围
            false,//不使用Harris角点检测
            k);//权重系数
    
        //【4】输出文字信息
        cout << "
    	>-------------此次检测到的角点数量为:" << corners.size() << endl;
    
        //【5】绘制检测到的角点
        int r = 4;
        for (unsigned int i = 0; i < corners.size(); i++)
        {
            //以随机的颜色绘制出角点
            circle(copy, corners[i], r, Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255),
                g_rng.uniform(0, 255)), -1, 8, 0);
        }
    
        //【6】显示(更新)窗口
        imshow(WINDOW_NAME, copy);
    
        //【7】亚像素角点检测的参数设置
        Size winSize = Size(5, 5);
        Size zeroZone = Size(-1, -1);
        //此句代码的OpenCV2版为:
        //TermCriteria criteria = TermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 40, 0.001 );
        //此句代码的OpenCV3版为:
        TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 40, 0.001);
    
        //【8】计算出亚像素角点位置
        cornerSubPix(g_grayImage, corners, winSize, zeroZone, criteria);
    
        //【9】输出角点信息
        for (int i = 0; i < corners.size(); i++)
        {
            cout << " 	>>精确角点坐标[" << i << "]  (" << corners[i].x << "," << corners[i].y << ")" << endl;
        }
    
    
    }
    
    static void ShowHelpText()
    {
        printf("当前使用的OpenCV版本为:" CV_VERSION);
        printf("欢迎来到【亚像素级角点检测】示例程序
    ");
        printf("请调整滑动条观察图像效果
    ");
    
    }
    
    int main()
    {
        ShowHelpText();
    
        //【1】载入源图像并将其转换为灰度图
        g_srcImage = imread("1.jpg", 1);
        cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
    
        //【2】创建窗口和滑动条,并进行显示和回调函数初始化
        namedWindow(WINDOW_NAME, WINDOW_AUTOSIZE);
        createTrackbar("最大角点数", WINDOW_NAME, &g_maxCornerNumber, g_maxTrackbarNumber, on_GoodFeaturesToTrack);
        imshow(WINDOW_NAME, g_srcImage);
        on_GoodFeaturesToTrack(0, 0);
    
        waitKey(0);
        return(0);
    }
    cornersubpix

    ---------------------continue------------------------------------------

  • 相关阅读:
    [网络流24题]飞行员配对方案问题
    bzoj 1571: [Usaco2009 Open]滑雪课
    bzoj 1001: [BeiJing2006]狼抓兔子
    bzoj 1711: [Usaco2007 Open]Dining吃饭
    bzoj 3379: [Usaco2004 Open]Turning in Homework 交作业
    bzoj 1412: [ZJOI2009]狼和羊的故事
    luogu P1345 [USACO5.4]奶牛的电信Telecowmunication
    hdu1512 Monkey King
    [BZOJ2006][NOI2010]超级钢琴(ST表+堆)
    [BZOJ4824][CQOI2017]老C的键盘(树形DP)
  • 原文地址:https://www.cnblogs.com/jianle23/p/13893848.html
Copyright © 2020-2023  润新知