《实用OpenCV》<五> 图像滤波(3)
2013-12-30 15:22
239 查看
有效检测图像边缘和拐角
之前的水平和垂直边缘可以很轻易地使用滤波器来检测。如果建立一个合适固定朝向的核,你也可以检测其他方向上的边缘。然而事实上一般需要检测图像里所有朝向的边缘。我们将讨论一些智能的方法来做到这一点。当然,拐角也是可以用一些合适的核来检测的。
边缘
边缘是图像里那些梯度非常高的点。我们说的梯度是指像素亮度值变化。图像梯度是通过计算x和y方向上的梯度然后使用毕达哥拉斯定理(注:勾股定理)结合得到。虽然通常不需要该值,你可以分别通过y与x的比例的反正切来得到梯度角度值。
x和y方向上的梯度可以分别用下面的核做卷积计算得到:
-3 0 3
-10 0 10
-3 0 3 (X 方向)
-3 -10 -3
0 0 0
3 10 3 (Y 方向)
总梯度,G = sqrt(Gx2 + Gy2)
梯度的角度,Ф = arctan(Gy / Gx)
上面展示的两个核 被称为Scharr操作,OpenCV也提供了一个叫Scharr()的函数可以对一张图像做指定大小和指定方向(X或Y)上的Scharr操作。
例 5-4 使用Scharr操作来检测图像边缘
图5-8 Scharr边缘检测
可以看得出来边缘图里会有一些噪声,可以对其做一些阈值处理来移除掉(注:threshold()方法)。
Canny边缘
Canny算法使用了许多后处理清理来得到薄的、锐利的边缘。计算Canny边缘涉及到的步骤有:
• 对图像用一个大小为5的归一化高斯核做卷积来移除边缘噪声
• 使用两个不同的核来计算X和Y梯度
-1 0 1
-2 0 2
-1 0 1 X方向
-1 -2 -1
0 0 0
1 2 1 Y 方向
•通过毕达哥拉斯定理(注:勾股定理)找到总梯度强度和之前提到的反正切得到梯度角度。四个角度是四舍五入的:0°,45°,90°和135°。
•非极大值抑制:只有当梯度的幅度大于其梯度方向上相邻的像素才被认为是在边缘上。这样可以得到锐利和薄的边缘。
•滞后阈值化:这一步需要两个阈值。梯度幅度高于上阈值的像素被接受,而梯度幅度低于下阈值的像素被拒绝。在两阈值之间的像素如果与边缘像素相连才被认为是一个边缘像素。
你可以运行OpenCV Canny边缘demo来看看Canny边缘和Scharr边缘的区别。
图 5-10 Canny边缘检测
之前的水平和垂直边缘可以很轻易地使用滤波器来检测。如果建立一个合适固定朝向的核,你也可以检测其他方向上的边缘。然而事实上一般需要检测图像里所有朝向的边缘。我们将讨论一些智能的方法来做到这一点。当然,拐角也是可以用一些合适的核来检测的。
边缘
边缘是图像里那些梯度非常高的点。我们说的梯度是指像素亮度值变化。图像梯度是通过计算x和y方向上的梯度然后使用毕达哥拉斯定理(注:勾股定理)结合得到。虽然通常不需要该值,你可以分别通过y与x的比例的反正切来得到梯度角度值。
x和y方向上的梯度可以分别用下面的核做卷积计算得到:
-3 0 3
-10 0 10
-3 0 3 (X 方向)
-3 -10 -3
0 0 0
3 10 3 (Y 方向)
总梯度,G = sqrt(Gx2 + Gy2)
梯度的角度,Ф = arctan(Gy / Gx)
上面展示的两个核 被称为Scharr操作,OpenCV也提供了一个叫Scharr()的函数可以对一张图像做指定大小和指定方向(X或Y)上的Scharr操作。
例 5-4 使用Scharr操作来检测图像边缘
// Program to detect edges in an image using the Scharr operator // Author: Samarth Manoj Brahmbhatt, University of Pennyslvania #include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace std; using namespace cv; int main() { Mat image = imread("lena.jpg"), image_blurred; // Blur image with a Gaussian kernel to remove edge noise GaussianBlur(image, image_blurred, Size(3, 3), 0, 0); // Convert to gray Mat image_gray; cvtColor(image_blurred, image_gray, CV_RGB2GRAY); // Gradients in X and Y directions Mat grad_x, grad_y; Scharr(image_gray, grad_x, CV_32F, 1, 0); Scharr(image_gray, grad_y, CV_32F, 0, 1); // Calculate overall gradient pow(grad_x, 2, grad_x); pow(grad_y, 2, grad_y); Mat grad = grad_x + grad_y; sqrt(grad, grad); // Display namedWindow("Original image"); namedWindow("Scharr edges"); // Convert to 8 bit depth for displaying Mat edges; grad.convertTo(edges, CV_8U); imshow("Original image", image); imshow("Scharr edges", edges); while(char(waitKey(1)) != 'q') {} return 0; }
图5-8 Scharr边缘检测
可以看得出来边缘图里会有一些噪声,可以对其做一些阈值处理来移除掉(注:threshold()方法)。
Canny边缘
Canny算法使用了许多后处理清理来得到薄的、锐利的边缘。计算Canny边缘涉及到的步骤有:
• 对图像用一个大小为5的归一化高斯核做卷积来移除边缘噪声
• 使用两个不同的核来计算X和Y梯度
-1 0 1
-2 0 2
-1 0 1 X方向
-1 -2 -1
0 0 0
1 2 1 Y 方向
•通过毕达哥拉斯定理(注:勾股定理)找到总梯度强度和之前提到的反正切得到梯度角度。四个角度是四舍五入的:0°,45°,90°和135°。
•非极大值抑制:只有当梯度的幅度大于其梯度方向上相邻的像素才被认为是在边缘上。这样可以得到锐利和薄的边缘。
•滞后阈值化:这一步需要两个阈值。梯度幅度高于上阈值的像素被接受,而梯度幅度低于下阈值的像素被拒绝。在两阈值之间的像素如果与边缘像素相连才被认为是一个边缘像素。
你可以运行OpenCV Canny边缘demo来看看Canny边缘和Scharr边缘的区别。
图 5-10 Canny边缘检测
相关文章推荐
- 《实用OpenCV》<五> 图像滤波(4)
- 《实用OpenCV》<五> 图像滤波(1)
- 《实用OpenCV》<五> 图像滤波(2)
- 《实用OpenCV》<四> 图像和GUI窗口的基本操作(3)
- 《实用OpenCV》<四> 图像和GUI窗口的基本操作(4)
- 《实用OpenCV》<六> 图像中的形状(2)
- 《实用OpenCV》<六> 图像中的形状(1)
- 《实用OpenCV》<四> 图像和GUI窗口的基本操作(1)
- 《实用OpenCV》<四> 图像和GUI窗口的基本操作(2)
- 在WPF中使用Emgu加载Image<,>图像的两种方法
- 自定义组件<五>
- 如何将遥感图像读为Emgucv的Image<gray,float>形式
- Android实战简易教程<五>(ListView用法研究)
- Core Animation - 变换<五>
- 设置<a>元素的背景图像
- 四级核心词汇表<五>
- Android 源码系列之<五>从源码的角度深入理解LayoutInflater.Factory之主题切换(中)
- 原创:oracle中单行函数介绍 <五>
- 黑马程序员 Java基础<五>---> 多线程
- 【MySql】使用记录<五>