OpenCV函数
Sobel(src_gray,grad_x/grad_y,ddepth,x_order,y_order,scale,delta,BORDER_DEFAULT )
Scharr( )
边缘检测
为何要求导,如下图:
假设需要检测图中的边缘,可以看到在边缘像素值显著改变,灰度值跃升
利用一阶导数可以清晰喊道跃升(高峰值)
从以上推论,检测边缘可以通过定位梯度值大于邻域的像素的方法找到(或者推广到大于一个阈值)
Sobel算子
Sobel算子是一个邻域微分算子(discrete differentiation operator)。它用来计算图像灰度函数的近似梯度。
Sobel算子结合了高斯平滑和微分求导。
计算
假设源图像为I
在两个方向求导
水平变化:将I与一个奇数内核Gx进行卷积。比如,当内核大小为3时,Gx的计算结果为:
垂直变化:将I与一个奇数大小的内核Gy进行卷积:
在图像的每一点,结合以上两个结果求出近似梯度。
当内核大小为3时,Sobel内核可能产生比较明显的误差(毕竟Sobel算子只求取了倒数的近似值),为解决这一个问题,
OpenCV提供了另一个Scharr函数,该函数仅作用于大小为3的内核。该函数的运算与Sobel函数一样快,但结果更精确。
其内核为:
#include <opencv2/opencv.hpp> #include <iostream> #include<windows.h> #include<stdio.h> #include<stdlib.h> using namespace std; using namespace cv; int main() { Mat src, src_gray; Mat grad; char* window_name =(char*)"Sobel Demo-Simple Edge Detector"; int scale = 1; int delta = 0; int ddepth = CV_16S; int c; //装载图像 src = imread("D:\Pic\4141.jpg"); if (!src.data) { return -1; } GaussianBlur(src, src, Size(3, 3), 0, 0, BORDER_DEFAULT); //转为灰度图 cvtColor(src, src_gray, CV_RGB2GRAY); //创建显示窗口 Mat grad_x, grad_y; Mat abs_grad_x, abs_grad_y; //求x方向梯度 Sobel(src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT); convertScaleAbs(grad_x, abs_grad_x); //求y方向梯度 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); imshow(window_name, grad); waitKey(0); return 0; }