OpenCV学习笔记(八) 边缘、线与圆的检测
边缘检测
对图像进行边缘检测之前,一般都需要先进行降噪(可调用GaussianBlur函数)。
Sobel算子 与 Scharr算子
都是一个离散微分算子 (discrete differentiation operator),用来计算图像灰度函数的近似梯度。结合了高斯平滑和微分求导。Sobel算子与Scharr算子的内核不同,Sobel内核产生误差比较明显,Scharr更为准确一些。
Sobel算子的计算步骤:
- 在两个方向求导:将原图分别与两个3x3的内核进行卷积计算,得到Gx与Gy
- 在图像的每一点,结合Gx与Gy求出近似 梯度 :
或者
(简单公式)
/// 求 X方向梯度
//Scharr( src_gray, grad_x, ddepth, 1, 0, scale, delta, BORDER_DEFAULT );
Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT );
convertScaleAbs( grad_x, abs_grad_x ); /// 求Y方向梯度
//Scharr( src_gray, grad_y, ddepth, 0, 1, scale, delta, BORDER_DEFAULT );
Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );
convertScaleAbs( grad_y, abs_grad_y ); /// 合并梯度(近似)
addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );
- src_gray: 在本例中为输入图像,元素类型 CV_8U
- grad_x/grad_y: 输出图像.
- ddepth: 输出图像的深度,设定为 CV_16S 避免外溢。
- x_order: x 方向求导的阶数。
- y_order: y 方向求导的阶数。
Laplace算子
计算的是二阶导数。由于 Laplacian使用了图像梯度,它内部调用了 Sobel 算子。Laplacian 算子 的定义:
Laplacian( src_gray, dst, ddepth, kernel_size, scale, delta, BORDER_DEFAULT );
convertScaleAbs( dst, abs_dst );
- src_gray: 输入图像。
- dst: 输出图像
- ddepth: 输出图像的深度。 因为输入图像的深度是 CV_8U ,这里我们必须定义 ddepth = CV_16S 以避免外溢。
- kernel_size: 内部调用的 Sobel算子的内核大小,此例中设置为3。
- scale, delta 和 BORDER_DEFAULT: 使用默认值。
Canny边缘检测
被很多人认为是边缘检测的 最优算法。在Sober算子步骤后添加以下步骤:
- 非极大值 抑制。 这一步排除非边缘像素, 仅仅保留了一些细线条(候选边缘)。
- 滞后阈值: 最后一步,Canny 使用了滞后阈值,滞后阈值需要两个阈值(高阈值和低阈值):
- 如果某一像素位置的幅值超过 高 阈值, 该像素被保留为边缘像素。
- 如果某一像素位置的幅值小于 低 阈值, 该像素被排除。
- 如果某一像素位置的幅值在两个阈值之间,该像素仅仅在连接到一个高于 高 阈值的像素时被保留。
Canny( origin_gray_image, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size );
具体使用方法见此处范例。
Hough变换
Hough线变换
执行Hough线变换之前需执行高斯模糊(降噪)+Canny边缘检测。Hough线变换以Canny边缘检测的输出(二值图)为输入。
一条直线可由参数 极径和极角表示:
当x0与y0定下来之后,rθ随着θ变化而变化,可在平面 -
中画出相应曲线(是一条正弦曲线),一对(x0, y0)确定一条曲线。(x1,y1)与(x2, y2)相交于(r0,
0)表示以这两个点作直线可由(r0,
0)表示:
一条直线能够通过在平面 -
寻找交于一点的曲线数量来 检测. 越多曲线交于一点也就意味着这个交点表示的直线由更多的点组成. 一般来说我们可以通过设置直线上点的 阈值 来定义多少条曲线交于一点我们才认为 检测 到了一条直线.
OpenCV实现了以下两种霍夫线变换:
- 标准Hough线变换 HoughLines :提供一组参数对
的集合来表示检测到的直线
- 统计概率Hough线变换 HoughLinesP :效率更高的Hough变换,输出检测到的直线的端点
// 标准Hough线变换
vector<Vec2f> lines;
HoughLines(dst, lines, 1, CV_PI/180, 100, 0, 0 );
// 画出检测的直线
for( size_t i = 0; i < lines.size(); i++ )
{
float rho = lines[i][0], theta = lines[i][1];
Point pt1, pt2;
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
pt1.x = cvRound(x0 + 1000*(-b));
pt1.y = cvRound(y0 + 1000*(a));
pt2.x = cvRound(x0 - 1000*(-b));
pt2.y = cvRound(y0 - 1000*(a));
line( cdst, pt1, pt2, Scalar(0,0,255), 3, CV_AA);
} // 统计Hough线变换
vector<Vec4i> lines;
HoughLinesP(dst, lines, 1, CV_PI/180, 50, 50, 10 );
- dst: 边缘检测的输出图像. 它应该是个灰度图 (但事实上是个二值化图)
- lines: 储存着检测到的直线的参数对
的容器
- rho : 参数极径
以像素值为单位的分辨率. 我们使用 1 像素.
- theta: 参数极角
以弧度为单位的分辨率. 我们使用 1度 (即CV_PI/180)
- threshold: 要”检测” 一条直线所需最少的的曲线交点
- 标准Hough变换:
- srn and stn: 参数默认为0. 查缺OpenCV参考文献来获取更多信息.
- 统计Hough变换:
- minLinLength: 能组成一条直线的最少点的数量. 点数量不足的直线将被抛弃.
- maxLineGap: 能被认为在一条直线上的亮点的最大距离.
Hough圆变换
原理与线变换相似,在三维的“圆心点x, y还有半径r”空间中找交点。
由于在三维空间的计算量大大增加的原因, 标准霍夫圆变化很难被应用到实际中,OpenCV实现的是一个比标准霍夫圆变换更为灵活的检测方法: 霍夫梯度法, 也叫2-1霍夫变换(21HT)。它的原理依据是圆心一定是在圆上的每个点的模向量上, 这些圆上点模向量的交点就是圆心, 霍夫梯度法的第一步就是找到这些圆心, 这样三维的累加平面就又转化为二维累加平面. 第二部根据所有候选中心的边缘非0像素对其的支持程度来确定半径.
/// Convert it to gray
cvtColor( src, src_gray, CV_BGR2GRAY ); /// Reduce the noise so we avoid false circle detection
GaussianBlur( src_gray, src_gray, Size(9, 9), 2, 2 ); vector<Vec3f> circles; /// Apply the Hough Transform to find the circles
HoughCircles( src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows/8, 200, 100, 0, 0 ); /// Draw the circles detected
for( size_t i = 0; i < circles.size(); i++ )
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
// circle center
circle( src, center, 3, Scalar(0,255,0), -1, 8, 0 );
// circle outline
circle( src, center, radius, Scalar(0,0,255), 3, 8, 0 );
}
- src_gray: 输入图像 (灰度图)
- circles: 存储下面三个参数:
集合的容器来表示每个检测到的圆.
- CV_HOUGH_GRADIENT: 指定检测方法. 现在OpenCV中只有霍夫梯度法
- dp = 1: 累加器图像的反比分辨率
- min_dist = src_gray.rows/8: 检测到圆心之间的最小距离
- param_1 = 200: Canny边缘函数的高阈值
- param_2 = 100: 圆心检测阈值.
- min_radius = 0: 能检测到的最小圆半径, 默认为0.
- max_radius = 0: 能检测到的最大圆半径, 默认为0
OpenCV学习笔记(八) 边缘、线与圆的检测的更多相关文章
- 【opencv学习笔记八】创建TrackBar轨迹条
createTrackbar这个函数我们以后会经常用到,它创建一个可以调整数值的轨迹条,并将轨迹条附加到指定的窗口上,使用起来很方便.首先大家要记住,它往往会和一个回调函数配合起来使用.先看下他的函数 ...
- OpenCV学习笔记八:opencv_photo模块
一,简介: 该库用于数码照片的处理,处于发展中,目前只包含如下算法: //! restores the damaged image areas using one of the available i ...
- OpenCV 学习笔记03 边界框、最小矩形区域和最小闭圆的轮廓
本节代码使用的opencv-python 4.0.1,numpy 1.15.4 + mkl 使用图片为 Mjolnir_Round_Car_Magnet_300x300.jpg 代码如下: impor ...
- OpenCV 学习笔记03 boundingRect、minAreaRect、minEnclosingCircle、boxPoints、int0、circle、rectangle函数的用法
函数中的代码是部分代码,详细代码在最后 1 cv2.boundingRect 作用:矩形边框(boundingRect),用于计算图像一系列点的外部矩形边界. cv2.boundingRect(arr ...
- opencv学习笔记(二)寻找轮廓
opencv学习笔记(二)寻找轮廓 opencv中使用findContours函数来查找轮廓,这个函数的原型为: void findContours(InputOutputArray image, O ...
- OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波
http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 201 ...
- OpenCV 学习笔记 07 目标检测与识别
目标检测与识别是计算机视觉中最常见的挑战之一.属于高级主题. 本章节将扩展目标检测的概念,首先探讨人脸识别技术,然后将该技术应用到显示生活中的各种目标检测. 1 目标检测与识别技术 为了与OpenCV ...
- OpenCV 学习笔记 02 使用opencv处理图像
1 不同色彩空间的转换 opencv 中有数百种关于不同色彩空间的转换方法,但常用的有三种色彩空间:灰度.BRG.HSV(Hue-Saturation-Value) 灰度 - 灰度色彩空间是通过去除彩 ...
- OpenCV学习笔记3
OpenCV学习笔记3 图像平滑(低通滤波) 使用低通滤波器可以达到图像模糊的目的.这对与去除噪音很有帮助.其实就是去除图像中的高频成分(比如:噪音,边界).所以边界也会被模糊一点.(当然,也有一些模 ...
- opencv学习笔记(七)SVM+HOG
opencv学习笔记(七)SVM+HOG 一.简介 方向梯度直方图(Histogram of Oriented Gradient,HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子 ...
随机推荐
- 北航oo作业第二单元小结
类的设计: 首先,我对我的思路进行整体的说明,由于我的三次作业,思路是继承的,所以做总体的说明 第一, Main类,Main类自身并没有功能,他的功能只是构造需要的电梯线程和输入线程. 其中,第三 ...
- JVM(二):垃圾回收
三个问题: 那些内存需要回收? -- 对象是否存活判断 什么时候回收? --垃圾回收触发条件 如何回收? --垃圾回收算法 垃圾回收应用 -- 理解GC日志.使用垃圾回收命令和工具 1. 判断 ...
- git与github的区别
一直纠结于这俩个的区别,今天有时间翻看了一些有关git的详解终于把这个问题搞得清楚了,大概就是下面的意思: Git是一款免费.开源的分布式版本控制系统 Github是用Git做版本控制的代码托管平台
- 零基础逆向工程24_C++_01_类_this指针_继承本质_多层继承
1 类内的成员函数和普通函数的对比 1.1 主要是从参数传递.压栈顺序.堆栈平衡来总结. 1.参数传递:成员函数多传一个this指针 2.压栈顺序:成员函数会将this指针压栈,在函数调用取出 3.堆 ...
- 《Unity預計算即時GI》笔记:二、光照图
说明 这篇文章是对<Unity預計算即時GI>这个系列文章的笔记. 光照图 什么是光照图 光照图在第三章中有如下的定义,读起来很是费解. 一個光照圖(Chart)是表示一個光照貼圖的區域, ...
- python3基础11(正则表达式及re模块)
#生成re对象 compile# 之后再期调用 match search 返回匹配到的字符串# findall 返回匹配结果的列表#如果要对匹配的结果进行分组,可加(),并可通过\数字 去应用
- pecl install msgpack
Before the beginning: There are two php version, php5.5, php7.1. we need to install msgpack under ph ...
- (转) HTTP Request header
HTTP Request header 当今web程序的开发技术真是百家争鸣,ASP.NET, PHP, JSP,Perl, AJAX 等等. 无论Web技术在未来如何发展,理解Web程序之间通信的基 ...
- cesium 加载shp格式的白模建筑
ceisum加载shp格式的建筑.有两种思路,目前推荐第二种. 方法一:将shp格式转换为geojson格式,然后采用cesium提供的接口加载到ceisum中. 严重缺陷:在面对大场景问题,即数据量 ...
- IOS DatePicker 和 UIBarButtonItem 常用属性
- (void)viewDidLoad { [super viewDidLoad]; // // self.inputTextField.inputView = [[UISwitch alloc ] ...