opencv 学习笔记六 边缘检测

在进行图像识别时,常需要检测图像的边缘信息。即边缘灰度值急剧变化的地方,一般是北京和前景物体的交界处。由于边缘处的灰度值急剧变化特性,可以利用离散数列的差分(相当于连续函数的导数)来识别边缘。目前常用的边缘检测算法大多数是通过梯度方向导数求卷积的方法,常用的卷积算子有

常用卷积算子:Roberts算子、Prewitt算子、Sobel算子、Scharr算子、canny边缘检测算法

非常用卷积算子:Laplacian算子、高斯拉普拉斯(LOG)边缘检测、高斯差分(DOG)边缘检测

1、Roberts算子

Roberts边缘检测算法:图像分别与下面两个卷积核进行卷积运算。第一个为135°方向像素差分,第二个为45°方向像素值差分,卷积后,图像内部相近的像素值为变为0,即黑色北京,二边缘由于像素值相差打,相减的差分值作为新的像素值。因此能够将图像边缘处的像素值识别出来,活得图像边缘轮廓;

通过上述两个卷积会得到145°和45°的卷积结果,将两者合并得到最后的输出结果。有如下四种合并方式:

a.取两个矩阵相对位置的绝对值的和;

b.取两个矩阵对应位置的平方和的开方;

c.取两个矩阵对应位置绝对值的最大值;

d.插值法;

以上4中方法,b方案为效果最优方案,但同时也是最耗时的方案;

2、Canny边缘检测算法

Sobel,Scharr算子等边缘检测算法,只是对检测到的边缘进行了超阈值处理(超过255的像素点截断等), Canny边缘算法,是在sobel算法的基础上,对边缘像素进行更细致的后处理,过滤掉部分非边缘点,从而使得到便边缘更加细致准确。

      Canny边缘检测可以细分为三步:

  • 采用Sobel卷积核进行卷积运算

  • 基于边缘梯度方向的非极大值抑制

  • 双阈值的滞后阈值处理

  (1)  Sobel卷积核进行卷积运算

      分别采用水平方向和垂直方向的sobel算子,卷积计算出水平方向梯度  和竖直方向梯度  ,然后我们可以计算图像中每个像素的梯度大小为  

梯度方向为  ,梯度方向通常垂直于边缘方向。

  (2) 基于边缘梯度方向的非极大值抑制

    在得到每个像素的梯度大小和方向后,我们遍历每个像素,判断该像素的梯度大小在该像素梯度方向上是否是其邻域中的局部最大值。如下图所示:

在上图中,假设一张5*5的image,左边为sobel算子计算的梯度大小,右边为计算的梯度方向,位于(1, 1)像素位置处的梯度大小为912, 梯度方向为120。上图左边画出了坐标轴和梯度方向,可以发现,沿着梯度方向的梯度值为(0,2)处的292和(2,0)处的276,由于912大于这两个梯度值,所以912为极大值。 按照这样的规则遍历每一个像素点,对于非极大值的像素点,需要将其梯度大小置为0;

(3) 双阈值的滞后阈值处理

这一步我们设置两个阈值 和  ,遍历所有像素:

  1.  梯度大小大于  的像素点被归为“确定边缘”像素,被保留;
  2. 梯度大小小于的像素点被认为一定不属于边缘,被丢弃。

  3. 梯度大小介于 和 之间的像素点,如果它们连接到“确定边缘”像素,则它们被视为边缘的一部分。否则,它们也会被丢弃

    3.Prewitt算子 

prewitt边缘检测算子如下图所示,分别为水平方向和垂直方向的卷积核(锚点为中心点),再进行边缘检测时,也是先分别进行水平和垂直方向的差分计算,最后再进行合并。

prewitt算子的来个卷积核是可分离的,如下图所示。对于水平方向的卷积核,可以拆分为一个垂直方向上的均值平滑卷积核和水平方向的差分卷积核,因此prewitt水平算子,相当于先进行了垂直方向的均值平滑,然后再进行水平方向的差分卷积运算。同样prewitt垂直算子,相当于先进行水平方向的均值平滑,再进行垂直方向的差分卷积。  所以相比于Robert算子,Prewitt算子多了一个平滑操作,所以其受噪声干扰小。

4.sobel算子

sobel算子的两个卷积核如下,也分为水平方向和垂直方向的卷积核(锚点为中心点),其卷积核也是可以差分,相比于prewitt算子,只是其平滑卷积核由均值平滑变成了高斯平滑,差分卷积核还是一样的。 

 sobel卷积核除了三阶,还可以是高阶的,通过其两个分离卷积核,进行矩阵乘法可以得到,下面是两个5*5的sobel卷积核:

5.Scharr算子

scharr算子和3阶的Sobel边缘检测算子类似,其对应两个卷积核如下: 

opencv提供了cv2.Scharr()函数进行Scharrr边缘检测,其对应参数如下:(注意没有szie参数)

dst= cv2.Scharr(src,ddepth,dx,dy,scale,delta,borderType)
        src: 输入图像对象矩阵,单通道或多通道
        ddepth:输出图片的数据深度,注意此处最好设置为cv.CV_32F或cv.CV_64F
        dx:dx不为0时,img与差分方向为水平方向的Sobel卷积核卷积
        dy: dx=0,dy!=0时,img与差分方向为垂直方向的Sobel卷积核卷积
        
            dx=1,dy=0: 与差分方向为水平方向的Sobel卷积核卷积
            dx=0,dy=1: 与差分方向为垂直方向的Sobel卷积核卷积
       (注意必须满足: dx >= 0 && dy >= 0 && dx+dy == 1)
        
        scale: 放大比例系数
        delta: 平移系数
        borderType:边界填充类型

 下面我用canny边缘提取和Roberts边缘提取做个例子

程序范例:


#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <stdio.h>

using namespace cv;
using namespace std;               


RNG rng(12345);
Scalar color[7] = {
    (Scalar(0,0,255)),//红色
    (Scalar(0,255,0)),//绿色
    (Scalar(255,0,0)),//蓝色
    (Scalar(255,255,0)),//浅蓝色
    (Scalar(255,0,255)),//紫色
    (Scalar(0,255,255)),//黄色
    (Scalar(128,128,192)),//浅粉色
};
int main()
{
    Mat image,gray_img,thread_img, dst2_img, dst3_img, dst_img;

    image = imread("../basketball.jpg", 1);
    if (image.empty()) {
        cout << "无此图片" << endl;
        return 0;
    }
    cvtColor(image, gray_img,COLOR_RGB2GRAY,0);//将图像转换为灰度图

    threshold(gray_img, thread_img, 100, 255, THRESH_BINARY_INV);//将灰度图转换为二值图

   
    while (1) 
    {
        imshow("原图", image);
        waitKey(1);
        

        Mat robert135 = (Mat_<char>(2, 2) <<  1,0,
                                               0,-1);
        filter2D(thread_img, dst2_img, image.depth(), robert135);

        Mat robert45 = (Mat_<char>(2, 2) << 0,1,
                                             -1,0);
        filter2D(thread_img, dst3_img, image.depth(), robert45);

        addWeighted(dst2_img, 1, dst3_img, 1, 0, dst_img);
        imshow("robert", dst_img);
        waitKey(1);

        Canny(thread_img, dst_img, 80, 160, 3);
        imshow("Canny", dst_img);
        waitKey(1);
    }
    return 1;
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
根据提供的引用内容,OpenCV是一个开源计算机视觉和机器学习软件库,用于开发图像和视频处理应用程序。通过使用OpenCV,您可以读取摄像头并显示实时图像,打开视频文件或摄像头文件,并获取视频的相关信息,例如帧宽度、帧高度、帧率和总帧数。 对于学习OpenCV,你可以按照以下步骤进行: 1. 安装OpenCV库:在开始学习OpenCV之前,您需要从OpenCV官方网站下载和安装OpenCV库。根据您的操作系统和编程语言选择合适的版本。 2. 学习基本概念:熟悉OpenCV的基本概念和术语,例如图像和视频的加载、显示、保存以及常用的图像处理操作,如滤波、边缘检测和特征提取等。 3. 掌握OpenCV函数和类:深入了解OpenCV提供的函数和类,例如cv::Mat用于图像和矩阵操作,cv::VideoCapture用于读取和处理视频,以及cv::imshow和cv::waitKey等用于显示图像的函数。 4. 实践项目:通过完成一些实践项目来应用您所学到的知识。例如,利用OpenCV实现人脸检测、目标追踪、图像识别等。 5. 学习资料和资源:查找和阅读OpenCV的官方文档、教程和示例代码,参与开源社区讨论和交流,加入相关的论坛和邮件列表等。 总结起来,学习OpenCV包括安装OpenCV库、学习基本概念、掌握OpenCV函数和类、实践项目以及查找和阅读相关资料和资源。通过不断实践和学习,您将能够更好地理解和应用OpenCV库来开发图像和视频处理应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

逐梦者-未来

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

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

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

打赏作者

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

抵扣说明:

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

余额充值