【OpenCV】边缘检测

Sobel一阶导数

  Sobel操作符是一个离散的微分算子。它计算了图像强度函数的梯度,结合了高斯平滑和微分。

  函数Sobel() 检测水平变化、检测垂直变化


  函数Scharr() 比传统Sobel函数运算快而且更为准确。


代码示例

#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
    CommandLineParser parser(argc, argv,            // 命令行解析类,减少命令行使用过程中的工作量
        "{@input  | ../data/lena.jpg|input image}"
        "{ksize k | 1 |hit 'K' to increase value}"
        "{scale s | 1 |hit 'S' to increase value}"
        "{delta d | 0 |hit 'D' to increase value}"
        "{help  h | false |show help message}");


    cout << "The sample uses Sobel or Scharr OpenCV functions for edge detection\n\n";
    parser.printMessage();
    cout << "\nPress 'ESC' to exit program.\n"
        "Press 'R' to reset values ( ksize will be -1 equal to Scharr function )";

    Mat image, src, src_gray, grad;
    String window_name = "Sobel Demo";
    int ksize = parser.get<int>("ksize");
    int scale = parser.get<int>("scale");
    int delta = parser.get<int>("delta");
    int ddepth = CV_16S;

    String imageName = parser.get<String>("@input");    // 获取图像路径和图像名           
    image = imread(imageName, IMREAD_COLOR);
    if (image.empty()) { return -1; }

    while (1)
    {
        GaussianBlur(image, src, Size(3, 3), 0, 0, BORDER_DEFAULT);     // 高斯模糊
        cvtColor(src, src_gray, COLOR_BGR2GRAY);                        // 转换灰度图像

        Mat grad_x, grad_y, abs_grad_x, abs_grad_y;

        Sobel(src_gray, grad_x, ddepth, 1, 0, ksize, scale, delta, BORDER_DEFAULT);
        Sobel(src_gray, grad_y, ddepth, 0, 1, ksize, scale, delta, BORDER_DEFAULT);

        convertScaleAbs(grad_x, abs_grad_x);            // 缩放,计算绝对值,并将结果转换为8位
        convertScaleAbs(grad_y, abs_grad_y);

        addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);
        imshow(window_name, grad);

        char key = (char)waitKey(0);
        if (key == 27)
        {
            return 0;
        }
        if (key == 'k' || key == 'K')
        {
            ksize = ksize < 30 ? ksize + 2 : -1;
        }
        if (key == 's' || key == 'S')
        {
            scale++;
        }
        if (key == 'd' || key == 'D')
        {
            delta++;
        }
        if (key == 'r' || key == 'R')
        {
            scale = 1;
            ksize = -1;
            delta = 0;
        }
    }

    return 0;
}


运行结果


拉普拉斯二阶导数


代码示例

#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"

using namespace cv;

int main(int argc, char** argv)
{
    Mat src, src_gray, dst;
    int kernel_size = 3;
    int scale = 1;
    int delta = 0;
    int ddepth = CV_16S;

    char* window_name = "Laplace Demo";
    char* imageName = "../data/lena.jpg";
    src = imread(imageName, IMREAD_COLOR);
    if (src.empty()) { return -1; }

    GaussianBlur(src, src, Size(3, 3), 0, 0, BORDER_DEFAULT);       // 高斯模糊

    cvtColor(src, src_gray, COLOR_BGR2GRAY);                        // 转换灰度图像

    Mat abs_dst;                                                    // 拉普拉斯二阶导数
    Laplacian(src_gray, dst, ddepth, kernel_size, scale, delta, BORDER_DEFAULT);

    convertScaleAbs(dst, abs_dst);                                  // 绝对值8位

    imshow(window_name, abs_dst);
    waitKey(0);

    return 0;
}


运行结果


Canny

优点:

  Low error rate: Meaning a good detection of only existent edges.

  Good localization: The distance between edge pixels detected and real edge pixels have to be minimized.

  Minimal response: Only one detector response per edge.


代码示例

#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"

using namespace cv;

Mat src, src_gray, dst, detected_edges;

int lowThreshold = 1;
int max_lowThreshold = 100;
int ratio = 3;
int kernel_size = 3;
char* window_name = "Canny Demo";

void CannyThreshold(int, void*)
{
    blur(src_gray, detected_edges, Size(3, 3));     // 平均滤波平滑
    Canny(detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size);
    dst = Scalar::all(0);
    src.copyTo(dst, detected_edges);
    imshow(window_name, dst);
}

int main(int, char** argv)
{
    char* filename = "../data/lena.jpg";
    src = imread(filename, IMREAD_COLOR);
    if (src.empty()) { return -1;}

    dst.create(src.size(), src.type());

    cvtColor(src, src_gray, COLOR_BGR2GRAY);

    namedWindow(window_name, WINDOW_AUTOSIZE);

    createTrackbar("Min Threshold", window_name, &lowThreshold, max_lowThreshold, CannyThreshold);

    CannyThreshold(0, 0);

    waitKey(0);

    return 0;
}


运行结果


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值