OpenCV2马拉松第14圈——边缘检测(Sobel,prewitt,roberts)

收入囊中

  • 差分在边缘检测的角色
  • Sobel算子
  • OpenCV sobel函数
  • OpenCV Scharr函数
  • prewitt算子
  • Roberts算子

葵花宝典

差分在边缘检测到底有什么用呢?先看下面的图片

作为人,我们可以很容易发现图中红圈有边界,边界处肯定是非常明显,变化陡峭的,在数学中,什么可以表示变化的快慢,自然就是导数,微分了。

想像有如下的一维图片。

红圈处变化最陡峭,再看导数图

红圈在最高值,也就是导数可以很好表示边缘,因为变化很剧烈

图像中的Sobel算子

  1. 是离散差分算子.
  2. 结合了高斯滤波.

是原始图像:

  1. 我们计算水平和竖直方向的梯度:

    1. 水平方向: Gx是我们Kernel size为3的水平sober算子,与I作卷积

    2. 竖直方向:Gy是我们Kernel size为3的水平sober算子,与I作卷积

  2. 对每个点,再计算下面的值,得到方向无关梯度

    有时候也可以这样计算:

初识API

C++: void Sobel(InputArray src,
OutputArray dst, int ddepth, int dx, int dy, int ksize=3, double scale=1, double delta=0, intborderType=BORDER_DEFAULT )
 
  • src – 输入.
  • dst – 输出
  • ddepth –
    output image depth; the following combinations of src.depth() and ddepth are
    supported:
    • src.depth() = CV_8Uddepth =
      -1/CV_16S/CV_32F/CV_64F
    • src.depth() = CV_16U/CV_16Sddepth =
      -1/CV_32F/CV_64F
    • src.depth() = CV_32Fddepth =
      -1/CV_32F/CV_64F
    • src.depth() = CV_64Fddepth =
      -1/CV_64F

    when ddepth=-1, the destination image will have the same depth as the source; in the case of
    8-bit input images it will result in truncated derivatives.这里要特别注意了,我们的depth不能为-1,因为我们的输入是uchar8类型的,而算出来的值可能>255也可能 <0 ,都会被截断,CV_16S是推荐的

  • xorder – order of the derivative x.
  • yorder – order of the derivative y.
  • ksize – sobel核大小,必须为1, 3, 5, or 7.
  • scale – 扩大系数
  • delta – 附加系数
  • borderType – 边界类型

计算的时候,利用了可分离的滤波进行加速(Ksize=1的时候,用了1*3和 3*1的算子,无法加速)

当Ksize = 3,Sobel采用的算子会不准确,因此还有特殊的值ksize = CV_SCHARR(-1) 相当于使用  Scharr
filter 比 Sobel算子能获得更准确的结果.
Scharr 算子如下

C++: void Scharr(InputArray src,
OutputArray dst, int ddepth, int dx, int dy, double scale=1, double delta=0, int borderType=BORDER_DEFAULT )
 
  • src – input image.
  • dst – output image of the same size and the same number of channels as src.
  • ddepth – output image depth (see Sobel() for
    the list of supported combination of src.depth() and ddepth).
  • dx – order of the derivative x.
  • dy – order of the derivative y.
  • scale – optional scale factor for the computed derivative values; by default, no scaling is applied (see getDerivKernels() for
    details).
  • delta – optional delta value that is added to the results prior to storing them in dst.
  • borderType – pixel extrapolation method (see borderInterpolate() for
    details).

The function computes the first x- or y- spatial image derivative using the Scharr operator. The call

is equivalent to

使用方法一样~~

荷枪实弹

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>

using namespace cv;

int main( int, char** argv )
{

  Mat src, src_gray;
  Mat grad;
  const char* window_name = "Sobel Demo - Simple Edge Detector";

  //因为以Sobel方式求完导数后会有负值,还有会大于255的值而你建的Sobel的图像是 CV_8U,也就是8位无符号数,所以Sobel建立的图像位数不够,要16位有符号的,也就是 CV_16S
  int ddepth = CV_16S;
  src = imread( argv[1] );
  if( !src.data )
    { return -1; }

  GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );
  cvtColor( src, src_gray, CV_RGB2GRAY );

  namedWindow( window_name, CV_WINDOW_AUTOSIZE );

  // Generate grad_x and grad_y
  Mat grad_x, grad_y;
  Mat abs_grad_x, abs_grad_y;

  // Gradient X
  //Scharr( src_gray, grad_x, ddepth, 1, 0);
  Sobel( src_gray, grad_x, ddepth, 1, 0, 3);
  convertScaleAbs( grad_x, abs_grad_x );

  // Gradient Y
  //Scharr( src_gray, grad_y, ddepth, 0, 1);
  Sobel( src_gray, grad_y, ddepth, 0, 1, 3);
  convertScaleAbs( grad_y, abs_grad_y );

  // Total Gradient (approximate)
  addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );

  imshow( window_name, grad );

  waitKey(0);

  return 0;
}

效果图:

举一反三

该算子与Sobel算子类似,只是权值有所变化,但两者实现起来功能还是有差距的,据经验得知Sobel要比Prewitt更能准确检测图像边缘。

Robert算子是一种梯度算子,它用交叉的差分表示梯度,是一种利用局部差分算子寻找边缘的算子,对具有陡峭的低噪声的图像效果最好:

下面我们来用prewitt算子作边缘检测,还记得我们以前在http://blog.csdn.net/abcd1992719g/article/details/24625805用过的自定义滤波不,下面我们又要用上了。

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;   

int main( int, char** argv )
{
	Mat src,gray,Kernelx,Kernely;

    src = imread( argv[1] );
    cvtColor( src, gray, CV_RGB2GRAY );
    namedWindow("srcImage", 1);
    namedWindow("dstImage", 1);  

    Kernelx = (Mat_<double>(3,3) << 1, 1, 1, 0, 0, 0, -1, -1, -1);
    Kernely = (Mat_<double>(3,3) << -1, 0, 1, -1, 0, 1, -1, 0, 1); 

    Mat grad_x, grad_y;
  	Mat abs_grad_x, abs_grad_y, grad;

    filter2D(gray, grad_x, CV_16S , Kernelx, Point(-1,-1));
    filter2D(gray, grad_y, CV_16S , Kernely, Point(-1,-1));
    convertScaleAbs( grad_x, abs_grad_x );
    convertScaleAbs( grad_y, abs_grad_y );

    addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );
    imshow("dstImage", grad);  

    waitKey();
    return 0;
} 

效果图:

计算机视觉讨论群162501053

转载请注明:http://blog.csdn.net/abcd1992719g

OpenCV2马拉松第14圈——边缘检测(Sobel,prewitt,roberts),布布扣,bubuko.com

时间: 2024-12-17 03:31:22

OpenCV2马拉松第14圈——边缘检测(Sobel,prewitt,roberts)的相关文章

OpenCV2马拉松第17圈——边缘检测(Canny边缘检测)

计算机视觉讨论群162501053 转载请注明:http://blog.csdn.net/abcd1992719g 收入囊中 利用OpenCV Canny函数进行边缘检测 掌握Canny算法基本理论 分享Java的实现 葵花宝典 在此之前,我们先阐述一下canny检测的算法.总共分为4部分. (1)处理噪声 一般用高斯滤波.OpenCV使用如下核 (2)计算梯度幅值 先用如下Sobel算子计算出水平和竖直梯度 我在OpenCV2马拉松第14圈--边缘检测(Sobel,prewitt,robert

OpenCV2马拉松第15圈——边缘检测(Laplace算子,LOG算子)

收入囊中 拉普拉斯算子 LOG算子(高斯拉普拉斯算子) OpenCV Laplacian函数 构建自己的拉普拉斯算子 利用拉普拉斯算子进行图像的锐化 葵花宝典 在OpenCV2马拉松第14圈--边缘检测(Sobel,prewitt,roberts)  我们已经认识了3个一阶差分算子 拉普拉斯算子是二阶差分算子,为什么要加入二阶的算子呢?试想一下,如果图像中有噪声,噪声在一阶导数处也会取得极大值从而被当作边缘.然而求解这个极大值也不方便,采用二阶导数后,极大值点就为0了,因此值为0的地方就是边界.

OpenCV2马拉松第14圈——边缘检測(Sobel,prewitt,roberts)

收入囊中 差分在边缘检測的角色 Sobel算子 OpenCV sobel函数 OpenCV Scharr函数 prewitt算子 Roberts算子 葵花宝典 差分在边缘检測究竟有什么用呢?先看以下的图片 作为人,我们能够非常easy发现图中红圈有边界,边界处肯定是非常明显,变化陡峭的,在数学中,什么能够表示变化的快慢,自然就是导数,微分了. 想像有例如以下的一维图片. 红圈处变化最陡峭,再看导数图 红圈在最高值,也就是导数能够非常好表示边缘,由于变化非常剧烈 图像中的Sobel算子 是离散差分

OpenCV2马拉松第16圈——边缘检测(形态学梯度)

计算机视觉讨论群162501053 转载请注明:http://blog.csdn.net/abcd1992719g 收入囊中 利用OpenCV函数进行形态学梯度操作 自定义结构矩阵进行形态学梯度操作 葵花宝典 在此之前,如果你还没接触过灰度图像形态学膨胀与腐蚀,希望你能仔细阅读灰度图像形态学膨胀与腐蚀 本质上,灰度与二值并不差异,二值不过是0与255,膨胀与腐蚀的操作都是一样的 形态学梯度的定义如下: 形态梯度 dst=morph_grad(src,element)=dilate(src,ele

OpenCV2马拉松第17圈——边缘检測(Canny边缘检測)

计算机视觉讨论群162501053 转载请注明:http://blog.csdn.net/abcd1992719g 收入囊中 利用OpenCV Canny函数进行边缘检測 掌握Canny算法基本理论 分享Java的实现 葵花宝典 在此之前,我们先阐述一下canny检測的算法.总共分为4部分. (1)处理噪声 一般用高斯滤波.OpenCV使用例如以下核 (2)计算梯度幅值 先用例如以下Sobel算子计算出水平和竖直梯度 我在OpenCV2马拉松第14圈--边缘检測(Sobel,prewitt,ro

OpenCV2马拉松第15圈——边缘检測(Laplace算子,LOG算子)

收入囊中 拉普拉斯算子 LOG算子(高斯拉普拉斯算子) OpenCV Laplacian函数 构建自己的拉普拉斯算子 利用拉普拉斯算子进行图像的锐化 葵花宝典 在OpenCV2马拉松第14圈--边缘检測(Sobel,prewitt,roberts)  我们已经认识了3个一阶差分算子 拉普拉斯算子是二阶差分算子.为什么要增加二阶的算子呢?试想一下,假设图像中有噪声,噪声在一阶导数处也会取得极大值从而被当作边缘.然而求解这个极大值也不方便.採用二阶导数后,极大值点就为0了.因此值为0的地方就是边界.

openCV2马拉松第19圈——Harris角点检测(自己实现)

计算机视觉讨论群162501053 转载请注明:http://blog.csdn.net/abcd1992719g/article/details/26824529 收入囊中 使用OpenCV的connerHarris实现角点检测 自己实现Harris算法 下面是自己实现的一个效果图 因为阀值设置比较高,所以房屋周围没有找出来 葵花宝典 在此之前,我们讲过边缘的检测,边缘检测的基本原理就是x方向或者y方向梯度变化很大,角点,顾名思义,就是两个方向的梯度变化都很大. 左1,平滑区域,没有边缘和角点

OpenCV2马拉松第10圈——直方图反向投影(back project)

收入囊中 灰度图像的反向投影 彩色图像的反向投影 利用反向投影做object detect 葵花宝典 什么是反向投影?事实上没有那么高大上! 在上一篇博文学到,图像能够获得自己的灰度直方图. 反向投影差点儿相同是逆过程,由直方图得到我们的投影图. 步骤例如以下: 依据模版图像,得到模版图像的灰度直方图. 对灰度直方图对归一化,归一化后是个概率分布,直方图的积分是1 依据概率分布的直方图,求输入图像的投影图,也就是对每个像素点,我们依据灰度值,能够得到其概率 得到的投影图是介于[0,1]之间的,为

OpenCV2马拉松第12圈——直方图比較

收入囊中 使用4种不同的方法进行直方图比較 葵花宝典 要比較两个直方图, 首先必需要选择一个衡量直方图相似度的对照标准.也就是先说明要在哪个方面做对照. 我们能够想出非常多办法,OpenCV採用了下面4种 公式也都不难,我们自己就能实现. d越小,表示差异越低,两幅图像越接近,越相似 初识API C++: double compareHist(InputArray H1, InputArray H2, int method) C++: double compareHist(const Spars