边缘检测概述
作用
边缘检测可以提取图像重要轮廓信息, 减少图像内容, 可以用于分割图像、做特征提取等
一般步骤
滤波—-(滤出噪声対检测边缘的影响)
增强—-(可以将像素邻域强度变化凸显出来—梯度算子)
检测—-(阈值方法确定边缘)
边缘检测算子
Canny算子
Sobel算子
Scharr算子
Laplacian算子
Roberts 算子、Prewitt算子… …
Canny边缘检测
Canny边缘检测算子是John F.Canny于1986 年开发出来的一个多级边缘检测算法, Canny边缘检测算法以Canny的名字命名, 被很多人推崇为当今最优的边缘检测的算法。
步骤
- 消除噪声
一般情况使用高斯平滑滤波器卷积降噪 - 计算梯度幅值和方向
安装Sobel滤波器的步骤操作 - 非极大值抑制
排除非边缘像素 - 滞后阈值
滞后阈值需要两个阈值(高阈值和低阈值)
Canny()
函数原型
void Canny( InputArray image, OutputArray edges,
double threshold1, double threshold2,
int apertureSize = 3, bool L2gradient = false );
- src: 输入原图像(一般为单通道8位图像)
- dst: 输出边缘图像要求和src一样的尺寸和类型(单通道)
- threshold1: 滞后阈值低阈值(用于边缘连接)
- threshold2: 滞后阈值高阈值(控制边缘初始段)
推荐高低阈值比值在2:1到3:1之间 - apertureSize: 表示Sobel算子孔径大小, 默认值3
- L2gradient: 计算图像梯度幅值的标识
代码
Mat srcImg = imread("1.jpg", 0);
/*均值滤波---可以平滑图像,进行降噪处理,去除图像内部变化比较突兀的点*/
blur(srcImg, srcImg, Size(5, 5));
imshow("src", srcImg);
Mat dstImg;
/*边缘检测---设置两个阈值*/
Canny(srcImg, dstImg, 30, 80);
imshow("Canny", dstImg);
waitKey(0);
运行结果
注意
在实际应用中,可以使用trackbar来控制canny的两个参数,动态观察变化
sobel边缘检测
基本概念
Sobel算子是一个主要用于边缘检测的离散微分算子, 它结合了高斯平滑和微分求导, 用来计算图像灰度函数的近似梯度。
步骤
分别在x和y两个方向求导
sobel()函数
函数原型
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 );
src: 输入原图像
dst: 输出图像要求和src一样的尺寸和类型
ddepth: 输出图像的深度, 支持如下组合:
dx: X方向上的差分阶数
dy: Y方向上的差分阶数
ksize: 默认值3, 表示Sobel核大小, 1,3,5,7
scale: 计算导数值时的缩放因子, 默认值1, 表示不缩放
delta(δ): 表示在结果存入目标图之前可选的delta值, 默认值0
borderType: 边界模式, 一般采用默认
代码
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y , dst;
Mat src = imread("2.png", 0);
imshow("src", src);
Sobel(src, grad_x, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT);
convertScaleAbs(grad_x, abs_grad_x);
imshow("X", abs_grad_x);
Sobel(src, grad_y, CV_16S, 0, 1, 3, 1, 1, BORDER_DEFAULT);
convertScaleAbs(grad_y, abs_grad_y);
imshow("Y", abs_grad_y);
addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dst);
imshow("ALL ", dst);
waitKey(0);
destroyAllWindows();
知识点
1.CV_16S
Sobel(src, grad_x, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT);
convertScaleAbs(grad_x, abs_grad_x);
imshow("X", abs_grad_x);
将图片的sobel检测以16位有符号的来进行存储,然后再将16位有符号数转为16位无符号数
2.读入以灰度图读入
Mat src = imread("2.png", 0);
运行结果
原图像
X方向
Y方向
X+Y方向
应用
计算摄像头聚焦程度
int FocusDetect0(Mat image){
Mat gray;
Mat grad_x,grad_y;
Mat abs_grad_x,abs_grad_y;
dst=img.clone();
int rowNumber=image.rows();
int colNumber=image.cols();
float result=0;
cvtColor(image,gray,COLOR_BGR2GRAY);//灰度转换
/*X方向梯度*/
Sobel(gray,grad_x,CV_16S,1,0,3,1,1,BORDER_DEFAULT);
convertScaleAbs(grad_x,abs_grad_x);
/*Y方向梯度*/
Sobel(gray,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);
imshow("Sobel",dst);
/*访问像素*/
for(int i=0;i<rowNumber;i++){
uchar* data=dst.ptr<uchar>(i);//获取第i行的首地址
for(int j=0;j<colNumber;j++){
result+=float(data[j]);
}
}
res_num=result/(rowNumber*colNumber);
result=0;
}
对上面函数的引用
FocusDetect0(img);
sprintf(Num,"%0.2f",res_num);
Point org(35,35);
putText(frame,Num,org,CV_FONT_HERSHEY_SIMPLEX,1.2f,CV_RGB(0,255,0),2);
Laplacian边缘检测
基本概念
Laplacian算子是n维欧几里德中的一个二阶微分算子。
Laplacian算子的定义
Laplacian函数
函数原型
void Laplacian( InputArray src, OutputArray dst, int ddepth,
int ksize = 1, double scale = 1, double delta = 0,
int borderType = BORDER_DEFAULT );
src: 输入原图像(单通道8位图像)
dst: 输出边缘图像要求和src一样的尺寸和通道数
ddepth: 目标图像的深度
Ksize: 用于计算二阶导数的滤波器孔径大小, 须为正奇数, 默认值1
scale: 可选比例因子, 默认值1
delta: 可选参数δ, 默认值0
borderType: 边界模式, 一般采用默认值
代码
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y, dst;
Mat abs_dst;
Mat src = imread("1.jpg", 0);
imshow("src", src);
Laplacian(src, dst, CV_16S, 3, 1, 0, BORDER_DEFAULT);
convertScaleAbs(dst, abs_dst);
imshow("Laplacian", abs_dst);
waitKey(0);
destroyAllWindows();
运行结果