OpenCV边缘检测与视频读写

原理

OpenCV中的边缘检测原理主要基于图像梯度的计算,包括一阶梯度和二阶梯度。

  • 一阶梯度:它反映了图像亮度变化的速度。Sobel算法就是一种以一阶梯度为基础的边缘检测算法。它通过计算图像在水平和垂直方向上的梯度来检测边缘。这种方法简单有效,但对于噪声较为敏感。
  • 二阶梯度:它描述了图像亮度变化率的变化,可以用于检测图像中的细线和角落。Laplacian算法就是基于二阶梯度的边缘检测算法,它对边缘的定位非常准确,但同样对噪声比较敏感。

边缘检测的目的是标识数字图像中亮度变化明显的点。图像属性中的显著变化通常反映了属性的重要事件和变化。边缘的表现形式:

 图像边缘检测大幅度地减少了数据量,并且剔除了可以认为不相关的信息,保留了图像重要的结构属性。边缘检测可以划分为两类:基于搜索和基于零穿越

  • 基于搜索:通过寻找图像一阶导数中的最大值来检测边界,然后利用计算结果估计边缘的局部方向,通常采用梯度的方向,并利用此方向找到局部梯度模的最大值,代表算法是Sobel算子和Scharr算子。
  • 基于零穿越:通过寻找图像二阶导数零穿越来寻找边界,代表算法是Laplacian算子。

Sobel检测算子

Sobel边缘检测算法比较简单,实际应用中效率比canny边缘检测效率要高,但是边缘不如Canny检测的准确,但是很多实际应用的场合,sobel边缘却是首选,Sobel算子是高斯平滑与微分操作的结合体,所以其抗噪声能力很强,用途较多。尤其是效率要求较高,而对细纹理不太关心的时候。

OpenCV中常用的边缘检测算法包括Sobel、Scharr、Laplacian和Canny等。

  1. Sobel算法:通过计算图像亮度的空间梯度来检测边缘,通常用于水平和垂直边缘的检测。
  2. Scharr算法:与Sobel类似,但使用了不同的核来计算梯度,通常能提供更精确的边缘检测结果。
  3. Laplacian算法:通过计算图像的二阶导数来检测边缘,对边缘的定位非常准确,但对噪声也比较敏感。
  4. Canny算法:是一个多阶段的边缘检测算法,包括使用高斯滤波器平滑图像、计算梯度幅度和方向、应用非最大抑制以及使用双阈值法进行边缘跟踪。Canny算法被认为是一种最优的边缘检测方法,因为它试图最小化误检和漏检的边缘。

API 

 利用OpenCV进行sobel边缘检测的API是cv2.Sobel() 函数。

Sobel_x_or_y = cv2.Sobel(src, ddepth, dx, dy, ksize) 

  • src:传入的图像

  • ddepth: 图像的深度

  • dx和dy: 求导的阶数,0表示这个方向上没有求导,取值为0、1。

  • ksize: Sobel算子的大小,必须为奇数1、3、5、7,默认为3。

Sobel函数求完导数后会有负值,还有会大于255的值。而原图像是uint8,即8位无符号数,所以Sobel建立的图像位数不够,会有截断。因此要使用16位有符号的数据类型,即cv2.CV_16S。处理完图像后,再使用cv2.convertScaleAbs()函数将其转回原来的uint8格式,否则图像无法显示。

Sobel算子是在两个方向计算的,最后还需要用cv2.addWeighted( )函数将其组合起来

Scale_abs = cv2.convertScaleAbs(x)  
result = cv2.addWeighted(src1, alpha, src2, beta)

 案例:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as pltimg = cv.imread('/h.jpg',0)x = cv.Sobel(img, cv.CV_16S, 1, 0)
y = cv.Sobel(img, cv.CV_16S, 0, 1)Scale_absX = cv.convertScaleAbs(x)  
Scale_absY = cv.convertScaleAbs(y)result = cv.addWeighted(Scale_absX, 0.5, Scale_absY, 0.5, 0)plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('原图')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(result,cmap = plt.cm.gray),plt.title('Sobel')
plt.xticks([]), plt.yticks([])
plt.show()

 

Laplacian算子 

Laplacian算子,也称为拉普拉斯算子,是数学中的一个二阶微分算子,用于描述函数在邻域平均值与差的平均值之间的关系

Laplacian算子在多个领域有着广泛的应用,包括但不限于:

  • 数学领域:在数学中,Laplacian算子被用于定义在欧几里得空间中的二阶微分算子,它可以表示为梯度(grad)的散度(div)。这个算子可以用来描述保守场或有势场的性质,例如静电场或引力场。
  • 物理领域:在物理学中,Laplacian算子经常出现在描述物理系统的偏微分方程中,如电磁学中的Poisson方程,它用来求解静电势分布问题。

此外,在图像处理中,Laplacian算子可以用于边缘检测,通过计算图像的二阶导数来检测图像中的边缘,这对于图像识别和计算机视觉任务非常重要。

API:

laplacian = cv2.Laplacian(src, ddepth, ksize) 

 

  • Src: 需要处理的图像,
  • Ddepth: 图像的深度,-1表示采用的是原图像相同的深度,目标图像的深度必须大于等于原图像的深度;
  • ksize:算子的大小,即卷积核的大小,必须为1,3,5,7。

案例:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as pltimg = cv.imread('ho.jpg',0)result = cv.Laplacian(img,cv.CV_16S)
Scale_abs = cv.convertScaleAbs(result)plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('原图')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(Scale_abs,cmap = plt.cm.gray),plt.title('Laplacian')
plt.xticks([]), plt.yticks([])

 Canny边缘检测

Canny边缘检测是一种基于灰度突变的边缘检测算法,主要用于提取图像中不连续部分的特征,以便将图像分割成不同的子区域或轮廓线

Canny边缘检测算法包括以下几个关键步骤:

  1. 高斯滤波:使用高斯滤波器对图像进行平滑处理,以减少图像噪声对边缘检测的影响。
  2. 像素梯度计算:计算图像中每个像素的梯度幅度和方向,这有助于确定边缘的强度和方向。
  3. 非极大值抑制:只保留梯度幅度最大的像素,抑制其他非极大值像素,这样可以减少边缘检测中的伪边缘。
  4. 滞后阈值处理:使用两个阈值(高阈值和低阈值)来确定真正的边缘,强边缘通过高阈值被直接标记,而弱边缘只有在连接到强边缘时才被标记。
  5. 孤立弱边缘抑制:去除那些没有连接到强边缘的孤立弱边缘,以得到更加清晰的边缘检测结果。

在OpenCV中要实现Canny检测使用的API:

canny = cv2.Canny(image, threshold1, threshold2)  

 

  • image:灰度图,
  • threshold1: minval,较小的阈值将间断的边缘连接起来
  • threshold2: maxval,较大的阈值检测图像中明显的边缘
import cv2 as cv
import numpy as np
from matplotlib import pyplot as pltimg = cv.imread('ho.jpg',0)lowThreshold = 0
max_lowThreshold = 100
canny = cv.Canny(img, lowThreshold, max_lowThreshold) plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('原图')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(canny,cmap = plt.cm.gray),plt.title('Canny')
plt.xticks([]), plt.yticks([])

 视频读写

创建读取视频的对象:

cap = cv.VideoCapture(filepath)

 

  • filepath: 视频文件路径

  • 视频的属性信息

获取视频的某些属性:

retval = cap.get(propId) 

  • propId: 从0到18的数字,每个数字表示视频的属性 

修改视频的属性信息:

cap.set(propId,value)  

  • proid: 属性的索引,与上面的表格相对应
  • value: 修改后的属性值

isornot = cap.isOpened() 

  • 若读取成功则返回true,否则返回False

  • 获取视频的一帧图像

 ret, frame = cap.read()

  • ret: 若获取成功返回True,获取失败,返回False
  • Frame: 获取到的某一帧的图像

  • 调用cv.imshow()显示图像,在显示图像时使用cv.waitkey()设置适当的持续时间,如果太低视频会播放的非常快,如果太高就会播放的非常慢,通常情况下我们设置25ms就可以了。

  • 最后,调用cap.realease()将视频释放掉

创建视频写入的对象:

out = cv2.VideoWriter(filename,fourcc, fps, frameSize)

  • filename:视频保存的位置
  • fourcc:指定视频编解码器的4字节代码
  • fps:帧率
  • frameSize:帧大小

 eg:

import cv2 as cv
import numpy as npcap = cv.VideoCapture("cat.wmv")frame_width = int(cap.get(3))
frame_height = int(cap.get(4))out = cv.VideoWriter('outpy.avi',cv.VideoWriter_fourcc('M','J','P','G'), 10, (frame_width,frame_height))
while(True):# 获取视频的每一帧图像ret, frame = cap.read()if ret == True: # 将每一帧图像写入到输出文件        out.write(frame)else:break cv.destroyAllWindows()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/479830.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java学习心得感悟

在我踏入Java学习的道路之前,我对编程只是一知半解,对于代码的世界充满了好奇和向往。然而,当我真正开始学习Java时,我才意识到,学习Java不仅仅是学习一门编程语言,更是一种思维方式和解决问题的能力的培养…

MySQL的优化

一:概念 在应用的开发过程中,由于初期数据量小,开发人员写SQL语句时更重视功能上的实现,但是当应用系统正式上线后,随着生产数据量的急剧增长,很多SQL语句开始逐渐暴露出性能问题,对生产的影响…

[word] 如何将word文本转换成表格? #知识分享#学习方法#媒体

如何将word文本转换成表格? 如何将word文本转换成表格?不管是Word入门新手还是老手,相信这个技巧会让你更加熟练Word,操作起来得心应手! 1.文本转换成表格 同样的要怎么把一堆凌乱的数据转换成表格呢?这里…

Leetcode日记 226. 翻转二叉树 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

Leetcode日记 226. 翻转二叉树 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 二叉树简介二叉树分类解题方法制作不易,感谢三连,谢谢啦 二叉树简介 二叉树(Binary Tree)是一种特殊的树形…

脚本项目一

第一题 1、判断当前磁盘剩余空间是否有20G,如果小于20G,则将报警邮件发送给管理员,每天检查一次磁盘剩余空间。 第一步安装邮件服务 [rootserver ~]# yum install mailx -y [rootserver ~]# vim /etc/mail.rc set from2282475145qq.com se…

C++结合Lambda表达式在函数内部实现递归

529. 扫雷游戏 已解答 中等 相关标签 相关企业 让我们一起来玩扫雷游戏! 给你一个大小为 m x n 二维字符矩阵 board ,表示扫雷游戏的盘面,其中: M 代表一个 未挖出的 地雷,E 代表一个 未挖出的 空方块&#xff…

Elasticsearch:创建自定义 ES Rally tracks 的分步指南

作者:Alejandro Snchez 按照这个综合教程学习如何制作个性化的 Rally tracks ES Rally 是什么?它的用途是什么? ES Rally 是一个用于在 Elasticsearch 上测试性能的工具,允许你运行和记录比较测试。 做出决策可能很困难&#x…

Spring两大核心思想:IOC和AOP

目录 IOC:控制反转 Ioc概念 Ioc的优点 Spring Ioc AOP:面向切面编程 AOP的优点 Spring AOP 1.添加依赖 2.核心概念 3.通知的类型 4.切点表达式 5.公共切点 pointCut 6.切面优先级 Order 7.使用自定义注解完成AOP的开发 Spring AOP实现有几种方式? S…

Linux 驱动开发基础知识——APP 怎么读取按键值(十二)

个人名片: 🦁作者简介:学生 🐯个人主页:妄北y 🐧个人QQ:2061314755 🐻个人邮箱:2061314755qq.com 🦉个人WeChat:Vir2021GKBS 🐼本文由…

Qt|大小端数据转换(补充)

Qt|大小端数据转换-CSDN博客 之前这篇文章大小端数据转换如果是小数就会有问题。 第一个方法&#xff1a; template <typename T> static QByteArray toData(const T &value, bool isLittle) {QByteArray data;for (int i 0; i < sizeof(T); i) {int bitOffset…

如何在本地服务器部署TeslaMate并远程查看特斯拉汽车数据无需公网ip

文章目录 1. Docker部署TeslaMate2. 本地访问TeslaMate3. Linux安装Cpolar4. 配置TeslaMate公网地址5. 远程访问TeslaMate6. 固定TeslaMate公网地址7. 固定地址访问TeslaMate TeslaMate是一个开源软件&#xff0c;可以通过连接特斯拉账号&#xff0c;记录行驶历史&#xff0c;统…

Kotlin中的内置函数-apply、let

在使用Kotlin的过程中会经常用到其内置函数&#xff0c;包括apply&#xff0c;let&#xff0c;run&#xff0c;with&#xff0c;also&#xff0c;takeIf,takeUnless函数等&#xff0c;想要更好熟悉Kotlin&#xff0c;这些函数必须烂熟于心&#xff0c;接下来让我们来逐步了解&a…