opencv 梯度幅值_20、 OpenCV导数和梯度
在图像处理中,导数和梯度的概念有点类似,或者说有些关联。梯度在图像处理中非常重要,可以有说,几乎所有的图像处理算法都与梯度有关。梯度包括方向和幅值两部分。最常见的利用梯度的算法就是边缘检测算法。如sobel算法等。在OpenCV中,可以利用sobel、Scharr计算一阶导数或梯度,利用Laplacian计算二阶导数或梯度。
1、Sobel算子
用于表示微分的最常用算子是Sobel算子。 Sobel算子存在任何导数阶以及混合偏导数(例如,∂2/∂x∂y)。sobel算子如下。
void cv::Sobel(
cv::InputArray src,
cv::OutputArray dst,
int ddepth,
int xorder,
int yorder,
cv::Size ksize = 3,
double scale = 1,
double delta = 0,
int borderType = cv::BORDER_DEFAULT
);
src和dst是图像的输入和输出。参数ddepth允许选择输出的深度(例如,CV_32F)。如果src是一个8位图像,那么dst的深度应至少为CV_16S以避免溢出。xorder和yorder是导数的阶数。通常,使用0,1或至多2;0值表示该方向上没有导数。ksize参数应该是奇数,是要使用的滤波器的宽度(和高度)。borderType参数的功能与其他卷积操作的描述完全相同。
Sobel算子具有可以为任意大小的内核定义的性质,而且这些内核可以快速迭代构建。较大的内核可以更好地逼近导数,因为它们对噪声不太敏感。但是,如果导数不能在空间上保持不变,那么显然一个太大的内核将不再提供有用的结果。
必须认识到,Sobel算子不是一个真正的导数,因为它是在离散空间上定义的。Sobel算子实际表示的是对多项式的拟合。也就是说,x方向二阶Sobel算子不是二阶导数,它是一种适合于抛物线功能的局部特征。这解释了为什么人们可能想要使用更大的内核:更大的内核计算适合大量像素。
2、 Scharr算子
事实上,在离散网格的情况下,有许多方法来逼近导数。用于Sobel算子的近似值的缺点是它对于小内核来说不太准确。对于大的内核,在近似中使用更多的点。这种不准确性并不直接针对Sobel()中使用的X和y滤波,因为它们与x轴和y轴完全对齐。当想要进行近似于方向导数的图像时(即通过使用两个方向滤波器响应的比率y / x的反正切来反映图像梯度的方向)将会出现困难。
为了说明这一点,可能想要通过组合对象周围的梯度直方图来收集来自对象的形状信息。这样的直方图是许多常见形状分类器被训练和操作的基础。在这种情况下,不准确的梯度角测量会降低分类器的识别性能。
对于3×3 的Sobel滤波器,梯度角度与水平或垂直角度越远,误差越明显。OpenCV通过在Sobel()函数中使用特殊的ksize值cv :: SCHARR来解决小但快速3×3的Sobel导数滤波器的这种不准确性。Scharr滤波器与Sobel滤波器一样快但精度更高,因此如果想使用3×3滤波器进行图像检测,应使用它。Scharr滤波器的滤波器系数如图1所示图1。 使用标志为cv :: SCHARR的3×3 Scharr滤波器
3、 拉普拉斯算子
OpenCV拉普拉斯函数实现了拉普拉斯算子的离散逼近:
由于拉普拉斯算符可以用二阶导数来定义,所以可能会认为离散的实现类似于二阶Sobel导数。事实上,拉普拉斯算子的OpenCV实现直接在其计算中使用Sobel算子:
void cv::Laplacian(
cv::InputArray src,
cv::OutputArray dst,
int ddepth,
cv::Size ksize = 3,
double scale = 1,
double delta = 0,
int borderType = cv::BORDER_DEFAULT
);
Laplacian()函数与Sobel()函数具有相同的参数。该ksize与Sobel完全相同,并且实际上给出了在计算二阶导数时对像素进行采样的区域的大小。在实际实现中,对于ksize除1以外的其他值,拉普拉斯算子直接根据相应的Sobel算子的总和计算。在ksize = 1的特殊情况下,拉普拉斯算子通过与图2所示的单个内核进行卷积运算。
图2。 当ksize = 1时Laplacian()使用的单个内核
拉普拉斯算子可用于各种情况。一个常见的应用是检测“斑点”。拉普拉斯算子的形式是沿着x和y的二阶导数的总和。这意味着单个点或任何由较高值包围的小斑点将倾向于最大化该函数。相反,被较低值包围的点或小块会趋向于最大化该函数的负值。
考虑到这一点,拉普拉斯算子也可以用作一种边缘检测器。为了理解这是怎么完成的,考虑函数的一阶导数,在函数快速变化的任何地方它都会很大。同样重要的是,当接近边缘状的不连续点时,它将迅速增长,而当越过不连续点时,它将迅速缩小。因此,在这个范围内,导数将处于某个地方的最大值。因此,可以看到二阶导数的这个局部极大值的位置。原始图像中的边缘将为拉普拉斯算子的0。但是,拉普拉斯算子的实质和有意义的边都将为0,但这不是问题,因为可以简单地滤除也具有一阶(Sobel)导数的那些像素。
例1 Sobel、Scharr、Laplacian算子使用示例
#include "iostream"
#include "opencv2\opencv.hpp"
using namespace std;
using namespace cv;
int main(int argc, char ** argv)
{
Mat src = imread("E:/ 1.jpg", 1);
namedWindow("原图", 0);
imshow("原图", src);
Mat srcGray;
cvtColor(src, srcGray, COLOR_BGR2GRAY);
namedWindow("原图转成灰度图", 0);
imshow("原图转成灰度图", srcGray);
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y, sobelDst;
//求 X方向梯度
Sobel(srcGray, grad_x, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT);
convertScaleAbs(grad_x, abs_grad_x);
namedWindow("Sobel_x", 0);
imshow("Sobel_x", abs_grad_x);
//求Y方向梯度
Sobel(srcGray, grad_y, CV_16S, 0, 1, 3, 1, 1, BORDER_DEFAULT);
convertScaleAbs(grad_y, abs_grad_y);
namedWindow("Sobel_y", 0);
imshow("Sobel_y", abs_grad_y);
//合并梯度(近似)
addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, sobelDst);
namedWindow("整体Sobel", 0);
imshow("整体Sobel", sobelDst);
Mat schDst;
Scharr(srcGray, grad_x, CV_16S,1, 0);
convertScaleAbs(grad_x, abs_grad_x);
namedWindow("Scharr_x", 0);
imshow("Scharr_x", abs_grad_x);
Scharr(srcGray, grad_y, CV_16S, 0, 1);
convertScaleAbs(grad_y, abs_grad_y);
namedWindow("Scharr_y", 0);
imshow("Scharr_y", abs_grad_y);
addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, schDst);
namedWindow("整体sch", 0);
imshow("整体sch", schDst);
Mat LapDst;
// 拉普拉斯变换
Laplacian(src, LapDst, CV_16S, 3);
convertScaleAbs(LapDst, LapDst);
namedWindow("Laplacian", 0);
cv::imshow("Laplacian", LapDst);
waitKey(0);
return 0;
}
图3运算结果
opencv 梯度幅值_20、 OpenCV导数和梯度相关推荐
- opencv 梯度幅值_基于OpenCV的图像梯度与边缘检测!
严格的说,梯度计算需要求导数.但是图像梯度的计算,是通过计算像素值的差得到梯度的近似值.图像梯度表示的是图像变化的速度,反映了图像的边缘信息. 边缘是像素值快速变化的地方.所以对于图像的边缘部分,其灰 ...
- opencv 梯度幅值_OpenCV边缘检测的详细参数调节
findContours函数,这个函数的原型为: void findContours( InputOutputArray image, OutputArrayOfArrayscontours, Out ...
- 对梯度幅值进行非极大值抑制
图象的边缘是指图象局部区域亮度变化显著的部分,该区域的灰度剖面一般可以看作是一个阶跃,既从一个灰度值在很小的缓冲区域内急剧变化到另一个灰度相差较大的灰度值.图象的边缘部分集中了图象的大部分信息,图象边 ...
- opencv 梯度幅值_opencv3/C++ HOG特征提取方式
opencv3/C++ HOG特征提取方式 发布时间:2020-08-23 16:24:01 来源:脚本之家 阅读:111 HOG特征 HOG(Histograms of Oriented Gradi ...
- opencv打卡66: 方向梯度直方图(HOG)第一步:梯度幅值・梯度方向
1.介绍 2.代码 import cv2 import numpy as np import matplotlib.pyplot as plt# get HOG step1 def HOG_step1 ...
- opencv 边缘平滑_基于OpenCV的车道检测实现(一)
无人驾驶的话题日趋起热,而车道线检测对于无人驾驶的路径规划来讲特别重要.要遵守交通规则,首先的要求便是对车道线检测,而且通过检测车道线可以进一步的检测地面指示标志.进行前碰撞预警策略设计等. 早早就对 ...
- Abaqus中常用的幅值曲线
ABAQUS常用的幅值曲线-技术邻社区 (jishulink.com) https://www.jishulink.com/content/post/434578 本篇文章旨在分享推广,如有侵权,若侵 ...
- 在OpenCV环境下写的灰度图像二维傅里叶换,幅值计算,频谱平移和将数值归一化到0到255区间的四个函数
图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 灰度图像的二维傅里叶变换(cv_gray_fft ...
- opencv 计算二维矢量的幅值—magnitude()函数
计算二维矢量的幅值:magnitude()函数 该函数用来计算二维矢量的幅值 void magnitude(InputArray x,InputArray y,OutputArray magnitud ...
- OpenCV基于Python霍夫圆检测—基于梯度的霍夫圆检测
基于梯度的霍夫圆检测 1. 回顾与目标 2. 基于梯度的霍夫圆检测 2.1 问题分析 2.2 基于梯度的霍夫圆检测步骤 3. 基于梯度的霍夫圆检测函数HoughCircles 3.1 函数HoughC ...
最新文章
- 世界地板大会姚红鹏的三问
- 运维自动化之使用PHP+MYSQL+SHELL打造私有监控系统(一)
- 学生社团管理系统java_基于JavaEE的学生社团管理系统的设计与实现
- 【JVM】jvm jmap 使用
- Embedding技术在房产推荐中的应用(文末附PPT下载链接)
- 化敌为友,微软出手优化 Chrome!
- 最新linux搭建gfs系统--iscsi+GFS实现网络存储
- PAT (Basic Level) Practice1011 A+B 和 C
- 【讲座预告】Processing Learner Texts: from Annotation to ...
- switchyomega规则列表备份_一键备份微博并导出生成PDF,顺便用Python分析微博账号数据...
- 大数据技术原理与应用(第八章HBase测试)
- php 连接芒果数据库,芒果数据库配置文件
- HDFView安装及使用教程
- SQL查询分析器单文件绿色版
- 关于idea中的maven索引异常问题(在idea中创建maven项目时,在pom.xml文件中加入依赖,提示出现的很慢)
- 87键盘怎么用小键盘功能
- Emacs的日常生活
- 元宇宙终极目标是打造六界
- 全球每日被黑站点一览表!
- android airplay音乐播放器,您需要知道的关于使用AirPlay播放音乐的一切 | MOS86