国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > php开源 > php教程 > OpenCV3.0 Examples学习笔记(6)-edge.cpp

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

来源:程序员人生   发布时间:2017-02-05 13:52:18 阅读次数:3963次
这个系列的目的是通过对OpenCV示例,进1步了解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年开发出来的1个多级边沿检测算法,也被很多人认为是边沿检测的 最优算法, 最优边沿检测的3个主要评价标准是:
  • 低毛病率: 标识出尽量多的实际边沿,同时尽量的减少噪声产生的误报。
  • 高定位性: 标识出的边沿要与图象中的实际边沿尽量接近。
  • 最小响应: 图象中的边沿只能标识1次。

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


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

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


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


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

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

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

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

    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: 第1个滞后阈值。
threshold2: 第2个滞后阈值。
apertureSize: Sobel算子的孔径大学。
L2gradient : 计算图象梯度值的标识,1般使用默许值false。

PS: 参数threshold1和threshold2中使用小的1个进行边沿连接,大的用来控制强边沿的初始段,1般比例为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 ⑴;
    }

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 ⑴;
    }
    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;
}


参考资料:
1.《【opencv 1日1练】 api 之 blur
2.《【OpenCV入门指南】第3篇Canny边沿检测
3.《【OpenCV】Canny 边沿检测
4.《Canny 边沿检测
5.《
图象边沿检测--OpenCV之cvCanny函数
生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生