OpenCV入门(十四)快速学会OpenCV 13 边缘检测

这篇具有很好参考价值的文章主要介绍了OpenCV入门(十四)快速学会OpenCV 13 边缘检测。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

作者:Xiou

1.边缘检测概述

边缘检测是图像处理和计算机视觉中的基本问题,边缘检测的目的是标识数字图像中亮度变化明显的点。图像属性中的显著变化通常反映了属性的重要事件和变化,包括深度不连续、表面方向不连续、物质属性变化和场景照明变化。边缘检测特征是提取中的一个研究领域。图像边缘检测大幅度地减少了数据量,并且剔除了可以认为不相关的信息,保留了图像重要的结构属性。

有许多方法可以用于边缘检测,绝大部分可以划分为两类:基于查找的一类和基于零穿越的一类。基于查找的方法通过寻找图像一阶导数中的最大值和最小值来检测边界,通常是将边界定位在梯度最大的方向上。基于零穿越的方法通过寻找图像二阶导数零穿越来寻找边界,通常是Laplacian过零点或者非线性差分表示的过零点。

人类视觉系统认识目标的过程分为两步:首先,把图像边缘与背景分离出来;然后,到图像的细节,辨认出图像的轮廓。计算机视觉正是模仿人类视觉的过程。

因此,在检测物体边缘时先对轮廓点进行粗略检测,然后通过链接规则把原来检测到的轮廓点连接起来,同时检测和连接遗漏的边界点及去除虚假的边界点。图像的边缘是图像的重要特征,是计算机视觉、模式识别等的基础,因此边缘检测是图像处理中一个重要的环节。
然而,边缘检测是图像处理中的一个难题,因为实际景物图像的边缘往往是各种类型的边缘及它们模糊化后结果的组合,且实际图像信号存在噪声。噪声和边缘都属于高频信号,很难用频带做取舍。

边缘是指图像周围像素灰度有阶跃变化或屋顶状变化的像素集合,存在于目标与背景、目标与目标、区域与区域、基元与基元之间。边缘具有方向和幅度两个特征,沿边缘走向,像素值变化比较平缓;垂直于边缘走向,像素值变化比较剧烈,可能呈现阶跃状,也可能呈现斜坡状。

因此,边缘可以分为两种:一种为阶跃性边缘,两边的像素灰度值有着明显的不同;另一种为屋顶状边缘,位于灰度值从增加到减少的变化转折点。对于阶跃性边缘,二阶方向导数在边缘处呈零交叉;对于屋顶状边缘,二阶方向导数在边缘处取极值。

图像边缘检测技术是图像处理和计算机视觉等领域最基本的问题,也是经典的技术难题之一。如何快速、精确地提取图像边缘信息,一直是国内外的研究热点,同时边缘的检测也是图像处理中的一个难题。早期的经典算法包括边缘算子方法、曲面拟合的方法、模板匹配方法、阈值法等。

近年来,随着数学理论与人工智能技术的发展,出现了许多新的边缘检测方法,如Roberts、Laplacan、Canny等图像的边缘检测方法。这些方法的应用对于高水平的特征提取、特征描述、目标识别和图像理解有重大的影响。然而,在成像处理的过程中投影、混合、失真和噪声等会导致图像模糊和变形,这使得人们一直致力于构造具有良好特性的边缘检测算子。

图像边缘检测主要包括以下5个步骤:

(1)图像获取
(2)图像滤波
(3)图像增强
(4)图像检测
(5)图像定位

测试原图:

边缘检测,OpenCV,opencv,计算机视觉,图像处理

2.Roberts算子边缘检测

Roberts算子又称为交叉微分算法,是基于交叉差分的梯度算法,通过局部差分计算检测边缘线条。常用来处理具有陡峭的低噪声图像,当图像边缘接近于正45度或负45度时,该算法处理效果更理想。其缺点是对边缘的定位不太准确,提取的边缘线条较粗。

实现Roberts算子主要通过OpenCV中的filter2D函数来完成。这个函数的主要功能是通过卷积核实现对图像的卷积运算,声明如下:

    def filter2D(src, ddepth, kernel, dst=None, anchor=None, delta=None,
borderType=None)

参数
src为输入图像,
ddepth表示目标图像所需的深度,
kernel表示卷积核。

代码实例:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt 
 
# 读取图像
img = cv.imread('test.jpg', cv.COLOR_BGR2GRAY)
rgb_img = cv.cvtColor(img, cv.COLOR_BGR2RGB)

# 灰度化处理图像
grayImage = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# Roberts 算子
kernelx = np.array([[-1, 0], [0, 1]], dtype=int)
kernely = np.array([[0, -1], [1, 0]], dtype=int)

x = cv.filter2D(grayImage, cv.CV_16S, kernelx)
y = cv.filter2D(grayImage, cv.CV_16S, kernely)

# 转 uint8 ,图像融合
absX = cv.convertScaleAbs(x)
absY = cv.convertScaleAbs(y)
Roberts = cv.addWeighted(absX, 0.5, absY, 0.5, 0)

# 显示图形
titles = ['src', 'Roberts operator']
images = [rgb_img, Roberts]

for i in range(2):
    plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

在上述代码中,我们定义了函数Roberts,用来实现Roberts算子,其方法通过公式来实现。在调用Roberts之前,先利用库函数GaussianBlur进行高斯滤波。

输出结果:

边缘检测,OpenCV,opencv,计算机视觉,图像处理

3.Sobel算子边缘检测

Sobel算子是通过离散微分方法求取图像边缘的边缘检测算子,Sobel算子(索贝尔算子)利用像素上、下、左、右邻域的灰度加权算法,根据在边缘点处达到极值这一原理进行边缘检测。该方法不但产生较好的检测效果,而且对噪声具有平滑作用,可以提供较为精确的边缘方向信息。在技术上,它以离散型的差分算子来运算图像亮度函数的梯度近似值,缺点是Sobel算子并没有将图像的主题和背景严格区分开。

换句话说,Sobel算子并不是基于图像灰度进行处理的,因为Sobel算子并没有严格地模拟人的视觉生理特性,因此图像轮廓的提取有时并不能让人满意。

OpenCV提供了对图像提取Sobel边缘的Sobel函数,该函数声明如下:

    Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]]) 

代码实例:

import cv2 as cv
import matplotlib.pyplot as plt

# 读取图像
img = cv.imread('test.jpg', cv.COLOR_BGR2GRAY)
rgb_img = cv.cvtColor(img, cv.COLOR_BGR2RGB)

# 灰度化处理图像
grayImage = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# Sobel 算子
x = cv.Sobel(grayImage, cv.CV_16S, 1, 0)
y = cv.Sobel(grayImage, cv.CV_16S, 0, 1)

# 转 uint8 ,图像融合
absX = cv.convertScaleAbs(x)
absY = cv.convertScaleAbs(y)
Sobel = cv.addWeighted(absX, 0.5, absY, 0.5, 0)

# 用来正常显示中文标签
plt.rcParams['font.sans-serif'] = ['SimHei']

# 显示图形
titles = ['原始图像', 'Sobel 算子']
images = [rgb_img, Sobel]

for i in range(2):
    plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

输出结果:
边缘检测,OpenCV,opencv,计算机视觉,图像处理

4.Prewitt算子边缘检测

Prewitt边缘算子是一种边缘样板算子。样板算子由理想的边缘算子图像构成,依次用边缘样板去检测图像,与被检测区域最为相似的样板给出最大值,Prewitt算子和Sobel差不多,利用像素点上下、左右邻点灰度差,在边缘处达到极值检测边缘。其对噪声具有平滑作用,定位精度不够高。

Prewitt_X算子实际上是先对图像进行垂直方向的非归一化的均值平滑,然后进行水平方向的差分;然而Prewitt_Y算子实际上是先对图像进行水平方向的非归一化的均值平滑,然后进行垂直方向的差分。这就是Prewitt算子能够抑制噪声的原因。同理,我们也可以得到对角上的Prewitt算子。

代码实例:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

# 读取图像
img = cv.imread('test.jpg', cv.COLOR_BGR2GRAY)
rgb_img = cv.cvtColor(img, cv.COLOR_BGR2RGB)

# 灰度化处理图像
grayImage = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# Prewitt 算子
kernelx = np.array([[1,1,1],[0,0,0],[-1,-1,-1]],dtype=int)
kernely = np.array([[-1,0,1],[-1,0,1],[-1,0,1]],dtype=int)

x = cv.filter2D(grayImage, cv.CV_16S, kernelx)
y = cv.filter2D(grayImage, cv.CV_16S, kernely)

# 转 uint8 ,图像融合
absX = cv.convertScaleAbs(x)
absY = cv.convertScaleAbs(y)
Prewitt = cv.addWeighted(absX, 0.5, absY, 0.5, 0)

# 用来正常显示中文标签
plt.rcParams['font.sans-serif'] = ['SimHei']

# 显示图形
titles = ['原始图像', 'Prewitt 算子']
images = [rgb_img, Prewitt]

for i in range(2):
    plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

输出结果:

边缘检测,OpenCV,opencv,计算机视觉,图像处理

5.LoG算子边缘检测

LoG边缘检测算子是由David Courtnay Marr和Ellen Hildreth(1980)共同提出的。因此,也称为边缘检测算法或Marr & Hildreth算子。该算法首先对图像做高斯滤波,然后求其拉普拉斯(Laplacian)二阶导数,即图像与Laplacian of the Gaussian function进行滤波运算。

最后,通过检测滤波结果的零交叉(Zero crossings)可以获得图像或物体的边缘。因而,也被业界简称为Laplacian-of-Gaussian(LoG)算子。

代码实例:

import cv2 as cv
import matplotlib.pyplot as plt

# 读取图像
img = cv.imread("test.jpg")
rgb_img = cv.cvtColor(img, cv.COLOR_BGR2RGB)

gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# 先通过高斯滤波降噪
gaussian = cv.GaussianBlur(gray_img, (3, 3), 0)

# 再通过拉普拉斯算子做边缘检测
dst = cv.Laplacian(gaussian, cv.CV_16S, ksize=3)
LOG = cv.convertScaleAbs(dst)

# 用来正常显示中文标签
plt.rcParams['font.sans-serif'] = ['SimHei']

# 显示图形
titles = ['原始图像', 'LOG 算子']
images = [rgb_img, LOG]

for i in range(2):
    plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()
 

该算法首先对图像做高斯滤波,然后求拉普拉斯(Laplacian)二阶导数,根据二阶导数的过零点来检测图像的边界,即通过检测滤波结果的零交叉(Zero crossings)来获得图像或物体的边缘。LoG算子实际上是把Gauss滤波和Laplacian滤波结合了起来,先平滑掉噪声,再进行边缘检测。

输出结果:

边缘检测,OpenCV,opencv,计算机视觉,图像处理

6.Canny算子边缘检测

Canny边缘检测是一种使用多级边缘检测算法检测边缘的方法。1986年,John F. Canny发表了著名的论文A Computational Approach to Edge Detection,在该论文中详述了如何进行边缘检测。OpenCV提供了函数cv2.Canny()实现Canny边缘检测。

步骤:

使用高斯滤波器, 平滑图像, 消除噪声;
计算图像中每个像素点的梯度强度和方向;
使用没极大值抑制 (Non-Maximum Suppression) 消除边缘检测带来的杂散响应;
使用双阈值检测 (Double Threshold) 来确定真实和潜在的边缘;
通过抑制孤立的弱边缘最终完成边缘检测。

6.1应用高斯滤波去除图像噪声

由于图像边缘非常容易受到噪声的干扰,因此为了避免检测到错误的边缘信息,通常需要对图像进行滤波以去除噪声。滤波的目的是平滑一些纹理较弱的非边缘区域,以便得到更准确的边缘。在实际处理过程中,通常采用高斯滤波去除图像中的噪声。

边缘检测,OpenCV,opencv,计算机视觉,图像处理
边缘检测,OpenCV,opencv,计算机视觉,图像处理

6.2计算梯度

在这里,我们关注梯度的方向,梯度的方向与边缘的方向是垂直的。边缘检测算子返回水平方向的Gx和垂直方向的Gy。梯度的幅度G和方向Θ(用角度值表示)为:

边缘检测,OpenCV,opencv,计算机视觉,图像处理
梯度的方向总是与边缘垂直的,通常就近取值为水平(左、右)、垂直(上、下)、对角线(右上、左上、左下、右下)等8个不同的方向。

因此,在计算梯度时,我们会得到梯度的幅度和角度(代表梯度的方向)两个值。

边缘检测,OpenCV,opencv,计算机视觉,图像处理

6.3非极大值抑制

在获得了梯度的幅度和方向后,遍历图像中的像素点,去除所有非边缘的点。在具体实现时,逐一遍历像素点,判断当前像素点是否是周围像素点中具有相同梯度方向的最大值,并根据判断结果决定是否抑制该点。通过以上描述可知,该步骤是边缘细化的过程。

边缘检测,OpenCV,opencv,计算机视觉,图像处理
边缘检测,OpenCV,opencv,计算机视觉,图像处理

6.4应用双阈值确定边缘

完成上述步骤后,图像内的强边缘已经在当前获取的边缘图像内。但是,一些虚边缘可能也在边缘图像内。这些虚边缘可能是真实图像产生的,也可能是由于噪声所产生的。对于后者,必须将其剔除。

设置两个阈值,其中一个为高阈值maxVal,另一个为低阈值minVal。根据当前边缘像素的梯度值(指的是梯度幅度,下同)与这两个阈值之间的关系,判断边缘的属性。

边缘检测,OpenCV,opencv,计算机视觉,图像处理

6.5 代码实例

import cv2
import numpy as np
# 读取图片, 并转换成灰度图
img = cv2.imread("test.jpg", cv2.IMREAD_GRAYSCALE)

# Canny边缘检测
out1 = cv2.Canny(img, 50, 150)
out2 = cv2.Canny(img, 100, 150)

# 合并
canny = np.hstack((out1, out2))

# 展示图片
cv2.imshow("src", img)
cv2.imshow("canny", canny)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果:

边缘检测,OpenCV,opencv,计算机视觉,图像处理文章来源地址https://www.toymoban.com/news/detail-762220.html

到了这里,关于OpenCV入门(十四)快速学会OpenCV 13 边缘检测的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • OpenCV 入门教程:Laplacian算子和Canny边缘检测

    边缘检测在图像处理和计算机视觉领域中起着重要的作用。 Laplacian 算子和 Canny 边缘检测是两种常用的边缘检测方法,它们能够帮助我们准确地检测图像中的边缘信息。 OpenCV 提供了这

    2024年02月13日
    浏览(42)
  • OpenCV中更稳更快的边缘检测方法,快速查找线、圆、椭圆--EdgeDrawing-C++代码

    计算机视觉之家看到快速圆检测Edge Drawing,其效果比霍夫要好,速度更快(具体效果可以参考视觉之家的文章),上面C++代码不全,那么好的检测效果国内资料竟然那么少,后在opencv的开发文档中找到了C++代码,在此分享学习交流。 实战 | OpenCV中更稳更快的找圆方法--EdgeDr

    2024年02月02日
    浏览(32)
  • OpenCV快速入门:移动物体检测和目标跟踪

    在当今的数字化世界中,计算机视觉技术正在迅速发展并被广泛应用于各种场合。特别是在移动物体检测和目标跟踪领域,这项技术不仅对于安全监控系统至关重要,也在自动驾驶、交互式媒体、机器人技术等多个领域发挥着重要作用。 本文将介绍使用OpenCV进行移动物体检测

    2024年02月04日
    浏览(31)
  • 【课程介绍】OpenCV 基础入门教程:图像读取、显示、保存,图像处理和增强(如滤波、边缘检测、图像变换),特征提取和匹配,目标检测和跟踪

    [ 专栏推荐 ] 😃 《视觉探索: OpenCV 基础入门教程》 😄 ❤️【简介】: Opencv 入门课程适合初学者,旨在介绍 Opencv 库的基础知识和核心功能。课程包括图像读取、显示、保存,图像处理和增强(如滤波、边缘检测、图像变换),特征提取和匹配,目标检测和跟踪等内容。学

    2024年02月16日
    浏览(45)
  • OpenCV快速入门:目标检测——轮廓检测、轮廓的距、点集拟合和二维码检测

    在当今数字化时代,计算机视觉的崛起使得目标检测成为科技领域中的一项关键技术。本文将带您快速入门OpenCV中的目标检测,深入探讨轮廓检测、轮廓的距、点集拟合以及二维码检测等核心概念。 OpenCV,作为一种强大的开源计算机视觉库,为开发者提供了丰富的工具和算法

    2024年01月16日
    浏览(41)
  • 《opencv实用探索·十二》opencv之laplacian(拉普拉斯)边缘检测,Scharr边缘检测,Log边缘检测

    1、Laplacian算子 Laplacian(拉普拉斯)算子是一种二阶导数算子,其具有旋转不变性,可以满足不同方向的图像边缘锐化(边缘检测)的要求。同时,在图像边缘处理中,二阶微分的边缘定位能力更强,锐化效果更好,因此在进行图像边缘处理时,直接采用二阶微分算子而不使

    2024年04月10日
    浏览(33)
  • 《opencv实用探索·十一》opencv之Prewitt算子边缘检测,Roberts算子边缘检测和Sobel算子边缘检测

    1、前言 边缘检测: 图像边缘检测是指在图像中寻找灰度、颜色、纹理等变化比较剧烈的区域,它们可能代表着物体之间的边界或物体内部的特征。边缘检测是图像处理中的一项基本操作,可以用于人脸识别、物体识别、图像分割等多个领域。 边缘检测实质上是计算当前点和

    2024年02月22日
    浏览(42)
  • Opencv-C++笔记 (13) : opencv-图像卷积一(均值、中值、高斯、双边滤波)与 边缘处理

    头文件 quick_opencv.h:声明类与公共函数 主函数调用 src:输入图像 。 dst:输出图像 。 ksize:内核大小 ,一般用 Size(w,h),w 为宽度,h 为深度。 anchor:被平滑的点,表示取 内核中心 ,默认值 Point(-1,-1)。 boderType:推断图像外部像素的某种边界模式。默认值 BORDER_DEFAULT 目的:

    2024年02月16日
    浏览(36)
  • opencv#34 边缘检测(二)

    前面介绍的Sobel算子和Scharr算子存在的问题: 1.要分别计算两个方向(x,y)的边缘,之后将两方向的边缘进行叠加。 2.边缘与方向相关性较大。当我们通过Sobel算子提取x方向检测时,它所能够检测到的边缘都是一个沿着y轴方向的边缘,与检测的方向相反(垂直方向),当进行y方向

    2024年01月25日
    浏览(24)
  • OpenCV——Scharr边缘检测

    OpenCV——Scharr边缘检测由CSDN点云侠原创,爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。    Scharr边缘检测算法是对Sobel算子差异性的增强,因此两者在检测图像边缘的原理和使用方式上相同。Scharr算子的边缘检测滤波尺寸为3x3,因此也

    2024年01月23日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包