您的位置:首页 > 运维架构

《实用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操作来检测图像边缘

// 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边缘检测
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: