iOS 基于Open CV的边缘检测

来源:互联网 发布:阿里云服务器开通端口 编辑:程序博客网 时间:2024/05/15 06:14

图像的边缘检测

边缘检测是图像处理和计算机视觉中的基本问题,其目的是标识数字图像中亮度变化明显的点。图像属性中的显著变化通常反映了属性的重要事件和变化

边缘检测的一般步骤

滤波

边缘检测的算法主要是基于图像强度的一阶和二阶导数,但导数通常对噪声很敏感,因此必须采用滤波器来改善与噪声有关的边缘检测器的性能。常见的滤波方法主要是高斯滤波,即采用离散化的高斯函数产生一组归一化的高斯核,然后基于高斯核哈数对图像灰度矩阵的每一点进行加权求和。

增强

增强边缘的基础是确定图像各点邻域强度变化的变化值。增强算法可以将图像灰度点邻域强度值有显著变化的点凸显出来。在开发中,可以通过计算梯度幅值来确定。

检测

经过增强的图像,往往邻域中有很多点的梯度值比较大,而在特定的应用中,这些点并不是要找的边缘点,所以应该采用某种方法对这些点进行取舍。在实际的工程中,常用的方法是阈值化检测。

Canny算子

Canny算子的简介

Canny边缘检测算子是一个多级边缘检测算法,在当今被推崇为最优的边缘检测方法。具有低错误率、高定位性、最小响应。

Canny边缘检测的步骤

消除噪声

一般情况下,使用高斯平滑滤波器卷积降噪

计算梯度幅值和方向
非极大值抑制

排除非边缘像素,仅仅保留了一些细线条(候选边缘)。

滞后阈值

滞后阈值需要两个阈值(高阈值和低阈值)。
若某一像素位置的幅值超过了高阈值,该像素被保留为边缘像素
若某一像素位置的幅值低于低阈值,该像素则被排除。
若某一像素位置的幅值在两个阈值之间,该像素仅仅在连接一个高于高阈值的像素时保留。

Canny()函数

/*@param image 8-bit input image.@param edges output edge map; single channels 8-bit image, which has the same size as image .@param threshold1 first threshold for the hysteresis procedure.@param threshold2 second threshold for the hysteresis procedure.@param apertureSize aperture size for the Sobel operator.@param L2gradient a flag, indicating whether a more accurate \f$L_2\f$ norm\f$=\sqrt{(dI/dx)^2 + (dI/dy)^2}\f$ should be used to calculate the image gradient magnitude (L2gradient=true ), or whether the default \f$L_1\f$ norm \f$=|dI/dx|+|dI/dy|\f$ is enough (L2gradient=false ). */// 这个函数的阈值1和阈值2 两者中较小的值用于边缘连接,而较大的值用来控制边缘的初始段。 推荐高低阈值比在2131之间CV_EXPORTS_W void Canny( InputArray image, OutputArray edges,                         double threshold1, double threshold2,                         int apertureSize = 3, bool L2gradient = false );

示例程序

    UIImage * image1 = [UIImage imageNamed:@"lena.png"];    Mat src_image;    UIImageToMat(image1, src_image);    Mat dst,edge,gray;    //创建与src同类型 同大小的矩阵    dst.create(src_image.size(), src_image.type());    //将原图像 转换为 灰度像    cvtColor(src_image, gray, COLOR_BGR2GRAY);    //使用3X3内核降噪    blur(gray, edge, cv::Size(3,3));    //运行canny算子    Canny(edge, edge, 3, 9);    //将dst内的所有元素设置为0    dst = Scalar::all(0);    //使用Canny算子输出的边缘图    src_image.copyTo(dst, edge);    //输出图片    UIImage * tmpImage = MatToUIImage(edge);    self.imageV.image = tmpImage;

输出效果图:
这里写图片描述

Sobel算子

Sobel算子的基本概念

Sobel算子是一个主要用于边缘检测的离散微分算子。它结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度。在图像的任何一点使用此算子,都将会产生对应的梯度矢量或是其法矢量。

Sobel算子的计算过程

分别在x和y两个方向上求导。

1、水平变化:将图像I与一个奇数大小的内核Gx进行卷积。例如:
这里写图片描述

2、垂直变化:将I与一个奇数大小的内核进行卷积。例如:
这里写图片描述

在图像的每一点,结合以上两个结果求出梯度

这里写图片描述

Sobel()函数

/*@param src input image.   输入图像,Mat类型即可@param dst output image of the same size and the same number of channels as src .输出图像,需要和源图片有一样的尺寸和类型。@param ddepth output image depth, see @ref filter_depths "combinations"; in the case of 8-bit input images it will result in truncated derivatives. int类型的ddepth,输出图像的深度,支持如下 src.depth() 和ddepth的组合。 若src.depth() = CV_8U 取ddepth = -1/CV_16S/CV_32F/CV_64F 若src.depth() = CV_16U/CV_16S 取 ddepth = -1/CV_32F/CV_64F 若src.depth() = CV_32F, 取ddepth = -1/CV_32F/CV_64F 若src.depth() = CV_64F 取ddepth = -1/CV_64F@param dx order of the derivative x. x方向上的差分阶数@param dy order of the derivative y. y方向上的差分阶数@param ksize size of the extended Sobel kernel; it must be 1, 3, 5, or 7.表示Sobel的核的大小 取奇数。@param scale optional scale factor for the computed derivative values; by default, no scaling isapplied (see cv::getDerivKernels for details).计算导数值时可选的缩放因子,默认值时1.表示默认情况下是没有应用缩放的。@param delta optional delta value that is added to the results prior to storing them in dst.表示结果存入目标图之前可选的delta的值 有默认值0.@param borderType pixel extrapolation method, see cv::BorderTypes 边界模式,默认值为BORDER_DEFAULT。@sa  Scharr, Laplacian, sepFilter2D, filter2D, GaussianBlur, cartToPolar */CV_EXPORTS_W void Sobel( InputArray src, OutputArray dst, int ddepth,                         int dx, int dy, int ksize = 3,                         double scale = 1, double delta = 0,                         int borderType = BORDER_DEFAULT );

示例程序

   //原始图片    UIImage * image1 = [UIImage imageNamed:@"lena.png"];    Mat src_image;    UIImageToMat(image1, src_image);    Mat grad_x,grad_y;    Mat abs_grad_x,abs_grad_y,dst;    //求X方向的梯度    Sobel(src_image, grad_x, CV_16S, 1, 0,3,1,1,BORDER_DEFAULT);    convertScaleAbs(grad_x, abs_grad_x);    //求Y方向的梯度    Sobel(src_image, grad_y, CV_16S, 0,1,3,1,1,BORDER_DEFAULT);    convertScaleAbs(grad_y, abs_grad_y);    //求合并梯度    addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dst);    //输出图片        UIImage * tmpImage = MatToUIImage(abs_grad_x);        self.imageV.image = tmpImage;        self.orgianImageV.image =   image1;//    UIImage * tmpImage = MatToUIImage(abs_grad_y);//    self.imageV.image = tmpImage;//    self.orgianImageV.image =   MatToUIImage(dst);

效果示例:
这里写图片描述

这里写图片描述

Laplacian 算子

Laplacian 算子简介

Laplacian 算子是n维欧几里德空间中的一个二阶微分算子,定义为梯度grad的散度div。因此如果f是二阶可微的实函数,则f的拉普拉斯算子定义如下。
Laplacian算子的定义:
这里写图片描述

需要说明的是,由于Laplacian 使用了图像梯度,它的内部的代码其实是调用了Sobel算子。

Laplacian()函数

Laplacian 函数可以计算出图像经过拉普拉斯变换后的结果。

/*@param src Source image. 源图像@param dst Destination image of the same size and the same number of channels as src . 输出的边缘图,需要和源图片有一样的尺寸和通道数@param ddepth Desired depth of the destination image. 目标图像的深度@param ksize Aperture size used to compute the second-derivative filters. See getDerivKernels fordetails. The size must be positive and odd.int 类型的ksize 用于计算二阶导数的滤波器的孔径尺寸 大小必须为奇数 且默认值是1@param scale Optional scale factor for the computed Laplacian values. By default, no scaling isapplied. See getDerivKernels for details.计算拉普拉斯值的时候 可选的比例因子@param delta Optional delta value that is added to the results prior to storing them in dst .表示结果存入目标图之前可选的delta的值 有默认值0.@param borderType Pixel extrapolation method, see cv::BorderTypes 边界模式,默认值为BORDER_DEFAULT。@sa  Sobel, Scharr */CV_EXPORTS_W void Laplacian( InputArray src, OutputArray dst, int ddepth,                             int ksize = 1, double scale = 1, double delta = 0,                             int borderType = BORDER_DEFAULT );

示例代码

    //原始图片    UIImage * image1 = [UIImage imageNamed:@"lena.png"];    Mat src_image;    UIImageToMat(image1, src_image);    Mat src_gray,dst,abs_dst;    //高斯模糊 消除噪声    GaussianBlur(src_image, src_image, cv::Size(3,3), 0);    //转换为灰度图    cvtColor(src_image, src_gray, COLOR_RGB2GRAY);    //使用Laplacian函数    Laplacian(src_gray, dst, CV_16S);    //计算绝对值 并且转换为8位图    convertScaleAbs(dst, abs_dst);    //输出图片    UIImage * tmpImage = MatToUIImage(abs_dst);    self.imageV.image = tmpImage;    self.orgianImageV.image =   image1;

效果图示:
这里写图片描述

原创粉丝点击