Sobel算子的理解
sobel算子主要用于获得数字图像的一阶梯度,常见的应用和物理意义是边缘检测。
原理
算子使用两个33的矩阵(图1)算子使用两个33的矩阵(图1)去和原始图片作卷积,分别得到横向G(x)和纵向G(y)的梯度值,如果梯度值大于某一个阈值,则认为该点为边缘点
Gx方向的相关模板:
Gy方向的相关模板:
看了网上的很多资料,都把卷积和相关的概念给弄糊了,书上给的Sobel的模板不是卷积模板,而是相关模板,因为卷积的话要先将模板旋转180度以后再与图像做相关的操作。
所以Sobel的卷积模板是:
Gx=
1 |
0 |
-1 |
2 |
0 |
-2 |
1 |
0 |
-1 |
具体计算如下:
图像的每一个像素的横向及纵向灰度值通过以下公式结合,来计算该点灰度的大小:
通常,为了提高效率使用不开平方的近似值:
然后可用以下公式计算梯度方向:
opencv还提供了一个scharr函数,比Sobel算子更为精准,也是3x3的模板。
下面放上源代码:
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <cmath>
using namespace cv;
using namespace std;
bool sobelEdge(Mat& srcImage, Mat& resultImageX, Mat& resultImageY, uchar threshold)
{CV_Assert(srcImage.channels() == 1);// 初始化水平核因子Mat sobelx = (Mat_<double>(3, 3) << -1, 0,1, -2, 0, 2, -1, 0, 1);// 初始化垂直核因子Mat sobely = (Mat_<double>(3, 3) << -1, -2, -1,0, 0, 0, 1, 2, 1);resultImageX = Mat::zeros(srcImage.rows - 2,srcImage.cols - 2, srcImage.type());resultImageY = Mat::zeros(srcImage.rows - 2,srcImage.cols - 2, srcImage.type());double edgeX = 0;double edgeY = 0;double graMagX = 0;// 垂直方向上的梯度模长double graMagY = 0;// 水平方向上的梯度模长for (int k = 1; k < srcImage.rows - 1; ++k) {for (int n = 1; n < srcImage.cols - 1; ++n) {edgeX = 0;edgeY = 0;// 遍历计算水平与垂直梯度for (int i = -1; i <= 1; ++i) {for (int j = -1; j <= 1; ++j){edgeX += srcImage.at<uchar>(k + i, n + j) *sobelx.at<double>(1 + i, 1 + j);edgeY += srcImage.at<uchar>(k + i, n + j) *sobely.at<double>(1 + i, 1 + j);}}// 计算垂直方向上的梯度模长graMagX = sqrt(pow(edgeX, 2));// 计算水平方向上的梯度模长graMagY = sqrt(pow(edgeY, 2));// 二值化resultImageX.at<uchar>(k - 1, n - 1) =((graMagX > threshold) ? 255 : 0);// 二值化resultImageY.at<uchar>(k - 1, n - 1) =((graMagY > threshold) ? 255 : 0);}}return true;
}int OTSU(Mat &srcImage)
{int nRows = srcImage.rows;int nCols = srcImage.cols;int threshold = 0;double max = 0.0;double AvePix[256];int nSumPix[256];double nProDis[256];double nSumProDis[256];for (int i = 0; i < 256; i++){AvePix[i] = 0.0;nSumPix[i] = 0;nProDis[i] = 0.0;nSumProDis[i] = 0.0;}for (int i = 0; i < nRows; i++){for (int j = 0; j < nCols; j++){nSumPix[(int)srcImage.at<uchar>(i, j)]++;}}for (int i = 0; i < 256; i++){nProDis[i] = (double)nSumPix[i] / (nRows*nCols);}AvePix[0] = 0;nSumProDis[0] = nProDis[0];for (int i = 1; i < 256; i++){nSumProDis[i] = nSumProDis[i - 1] + nProDis[i];AvePix[i] = AvePix[i - 1] + i*nProDis[i];}double mean = AvePix[255];for (int k = 1; k < 256; k++){double PA = nSumProDis[k];double PB = 1 - nSumProDis[k];double value = 0.0;if (fabs(PA) > 0.001 && fabs(PB) > 0.001){double MA = AvePix[k];//前一半的平均double MB = (mean - PA*MA) / PB;//后一半的平均value = value = (double)(PA * PB * pow((MA - MB), 2));//类间方差 //或者这样value = (double)(PA * PB * pow((MA-MB),2));//类间方差//pow(PA,1)* pow((MA - mean),2) + pow(PB,1)* pow((MB - mean),2)if (value > max){max = value;threshold = k;}}}return threshold;
}
int main()
{Mat srcImage = cv::imread("building.jpg");if (!srcImage.data)return -1;Mat srcGray;cvtColor(srcImage, srcGray, CV_BGR2GRAY);imshow("srcGray", srcGray);//调用二值化函数得到最佳阈值int otsuThreshold = OTSU(srcGray);cout << otsuThreshold << endl;Mat XresultImage;Mat YresultImage;sobelEdge(srcGray, XresultImage, YresultImage, otsuThreshold);Mat resultImage;//水平垂直边缘叠加addWeighted(XresultImage, 0.5, YresultImage, 0.5, 0.0, resultImage);imshow("resx", XresultImage);imshow("resy", YresultImage);imshow("res", resultImage);waitKey(0);return 0;
}
原图灰度图:
垂直边缘图像:
水平边缘图像:
水平垂直合一起:
从上图可以看出 边缘图还有很多不是边缘点的也被取出来了,下一步就是做非极大值抑制
Sobel算子的理解相关推荐
- 梯度,sobel算子的理解
本文转于:https://blog.csdn.net/u014020344/article/details/50196635 若用侵权 请联系删除 ? 在这一讲中我们来学习一下opencv中最基本的边 ...
- 学习sobel算子对图像求导自我理解
sobel算子,其实也就是近似把对函数进行偏导数计算,转化为适合图像计算的矩阵, 把整个图像当做为二元函数,然后分别对二元(x和y)求偏导数. 偏导数其实高数考试里面的形象解释不多,个人就当导数理解, ...
- Sobel算子及cvSobel
转自:http://blog.sina.com.cn/s/blog_4bdbec750100mufo.html 由于项目里要用到边缘检测,所以今天研究了一下最简单的梯度的方法. 首先,我们来开一下计算 ...
- 【OpenCV 4开发详解】Sobel算子
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 灰度图像--图像增强 Robert算子、Sobel算子
灰度图像--图像增强 Robert算子.Sobel算子 目录(?)[+] 开篇废话 图像梯度介绍 Robert算子 Sobel算子 代码 结果 总结 学习DIP第36天 转载请标明本文 ...
- OpenCV-Python教程(6)(7)(8): Sobel算子 Laplacian算子 Canny边缘检测
OpenCV-Python教程(6.Sobel算子) 本篇文章介绍如何用OpenCV-Python来使用Sobel算子. 提示: 转载请详细注明原作者及出处,谢谢! 本文介绍使用OpenCV-Pyth ...
- python高斯滤波和降噪_python添加高斯噪声和椒盐噪声,实现中值滤波和均值滤波,实现Roberts算子和Sobel算子...
写在前面 HIT大三上学期视听觉信号处理课程中视觉部分的实验一,经过和学长们实验的对比发现每一级实验要求都不一样,因此这里标明了是2019年秋季学期的视觉实验一. 由于时间紧张,代码没有进行任何优化, ...
- 【Pytorch神经网络理论篇】 11 卷积网络模型+Sobel算子原理
1 视觉角度理解卷积神经网络 1.1 卷积神经网络与生物视觉系统的关系 卷积神经网络的工作流程与生物大脑的处理视觉信号的流程相似,即:将图像从基础像素到局部信息再到整体信息的转化.大脑在对图像进行分级 ...
- OpenCV中的Sobel算子
OpenCV中的Sobel算子 刚开始第一次接触这个东西的时候也是感觉一脸懵逼,这是什么鬼.完全看不懂.今天再次接触到,感觉理解的透彻了一点. 首先来看一下Sobel算子是个什么东西: -1 0 1 ...
最新文章
- mysql 查看运行级别_Linux的运行级别和chkconfig用法
- C#学员信息管理试题
- 看新排美国话剧《哗变》
- TPL 和传统 .NET Framework 异步编程
- Mybatis一二级缓存的理解
- ubuntu sudo apt-get update 失败 解决方法
- Mybatis_day2_Mybatis的CRUD操作
- 【CVPR 2019】Strong-Weak Distribution Alignment for Adaptive Object Detection
- 关于CVE-2020-14882,你需要知道的都在这里
- 基于Python-Pygame:200行代码实现完整的俄罗斯方块
- 北京互联网人寒冬求职记
- susmote个人网站博客论坛(TexTec | 关注互联网技术,传播极客精神)
- 如何使用Spring Bean Configuration File调用构造方法并给参数赋值
- AES加密算法|密码学|网络空间安全
- 文件同步工具BT Sync介绍和使用说明
- T检验和F检验\自由度
- git diff的简单使用
- 多媒体集中控制系统 (4600版)
- 【问题解决】win服务器磁盘初始化
- 使用十六进制设置颜色