OpenCV3.0 Examples学习笔记(6)-edge.cpp

这个系列的目的是通过对OpenCV示例,进一步了解OpenCV函数的使用,不涉及具体原理。

目录
简介
Example运行截图
Example分析
Example代码

简介
本文记录了对OpenCV示例edge.cpp 的分析。
资料地址: http://docs.opencv.org/3.0.0/d3/d63/edge_8cpp-example.html

首先这个示例,主要讲述了使用 Canny函数获取图像边缘。

Canny算法原理
    Canny 边缘检测算法  是 John F. Canny 于 1986年开发出来的一个多级边缘检测算法,也被很多人认为是边缘检测的  最优算法 , 最优边缘检测的三个主要评价标准是:
  • 低错误率: 标识出尽可能多的实际边缘,同时尽可能的减少噪声产生的误报。
  • 高定位性: 标识出的边缘要与图像中的实际边缘尽可能接近。
  • 最小响应: 图像中的边缘只能标识一次。

Canny步骤
  1. 消除噪声。 使用高斯平滑滤波器卷积降噪。 下面显示了一个size = 5 的高斯内核示例:


  2. 计算梯度幅值和方向。 此处,按照Sobel滤波器的步骤:

    1. 运用一对卷积阵列 (分别作用于 x 和 y方向):


    2. 使用下列公式计算梯度幅值和方向:


      梯度方向近似到四个可能角度之一(一般 0, 45, 90, 135)

  3. 非极大值 抑制。 这一步排除非边缘像素, 仅仅保留了一些细线条(候选边缘)。

  4. 滞后阈值: 最后一步,Canny 使用了滞后阈值,滞后阈值需要两个阈值(高阈值和低阈值):

    1. 如果某一像素位置的幅值超过  阈值, 该像素被保留为边缘像素。
    2. 如果某一像素位置的幅值小于  阈值, 该像素被排除。
    3. 如果某一像素位置的幅值在两个阈值之间,该像素仅仅在连接到一个高于  阈值的像素时被保留。

    Canny 推荐的 : 阈值比在 2:1 到3:1之间。

    以上内容摘至参考资料5.《图像边缘检测--OpenCV之cvCanny函数


Canny函数在OpenCV中的原型
Canny

函数原型:
void Canny( InputArray image, OutputArray edges,
                         double threshold1, double threshold2,
                         int apertureSize = 3, bool L2gradient = false );

参数说明:
image: 输入图像,需要8位图像。
edges: 输出边缘图像。
threshold1: 第一个滞后阈值。
threshold2: 第二个滞后阈值。
apertureSize: Sobel算子的孔径大学。
L2gradient : 计算图像梯度值的标识,一般使用默认值false。

PS: 参数threshold1和threshold2中使用小的一个进行边缘连接,大的用来控制强边缘的初始段,一般比例为2:1至3:1之间。

Example截图
原图
处理结果
参数
threshold1 = 1
threshold2 = 3
apertureSize = 3
L2gradient =false

Example分析
示例主要步骤如下:
1.申明需要使用的变量:
int edgeThresh = 1;
Mat image, gray, edge, cedge;

PS:Canny函数由高低两个阈值,用户在本示例只设置低阈值edgeThresh,令高阈值为低阈值的3倍。

2.从命令行参数中加载图像:
CommandLineParser parser(argc, argv, keys);
    string filename = parser.get<string>(0);

    image = imread(filename, 1);
    if(image.empty())
    {
        printf("Cannot read image file: %s\n", filename.c_str());
        help();
        return -1;
    }

3.创建与原图相同尺寸样式的图像,用于绘制边缘检测结果:
cedge.create(image.size(), image.type());

4.灰度化
cvtColor(image, gray, COLOR_BGR2GRAY);

5创建预览窗口
namedWindow("Edge map", 1);

6.创建滑动条,用于用户交互,设置阈值
createTrackbar("Canny threshold", "Edge map", &edgeThresh, 100, onTrackbar);

PS:认为低阈值上限为100;
PS1: Trackbar变动改变edgeThresh,调用回调函数onTrackbar。

7.分析onTrackbar函数
     7.1均值滤波,平滑图像
    blur(gray, edge, Size(3,3));

     7.2使用Canny寻找边缘
    Canny(edge, edge, edgeThresh, edgeThresh*3, 3);

     7.3将cedge 填充为黑色(0
    cedge = Scalar::all(0);

     7.4将Canny函数结果(边缘检测结果)复制到cedge(背景为黑色)
    image.copyTo(cedge, edge);

     7.5显示图像
    imshow("Edge map", cedge);


Example代码
#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"

#include <stdio.h>

using namespace cv;
using namespace std;

int edgeThresh = 1;
Mat image, gray, edge, cedge;

// define a trackbar callback
static void onTrackbar(int, void*)
{
    blur(gray, edge, Size(3,3));

    // Run the edge detector on grayscale
    Canny(edge, edge, edgeThresh, edgeThresh*3, 3);
    cedge = Scalar::all(0);

    image.copyTo(cedge, edge);
    imshow("Edge map", cedge);
}

static void help()
{
    printf("\nThis sample demonstrates Canny edge detection\n"
           "Call:\n"
           "    /.edge [image_name -- Default is ../data/fruits.jpg]\n\n");
}

const char* keys =
{
    "{@image |../data/fruits.jpg|input image name}"
};

int main( int argc, const char** argv )
{
    help();

    CommandLineParser parser(argc, argv, keys);
    string filename = parser.get<string>(0);

    image = imread(filename, 1);
    if(image.empty())
    {
        printf("Cannot read image file: %s\n", filename.c_str());
        help();
        return -1;
    }
    cedge.create(image.size(), image.type());
    cvtColor(image, gray, COLOR_BGR2GRAY);

    // Create a window
    namedWindow("Edge map", 1);

    // create a toolbar
    createTrackbar("Canny threshold", "Edge map", &edgeThresh, 100, onTrackbar);

    // Show the image
    onTrackbar(0, 0);

    // Wait for a key stroke; the same function arranges events processing
    waitKey(0);

    return 0;
}


参考资料:
4.《 Canny 边缘检测
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值