概述
文章目录
- Sobel算子
- 相关理论
- 2. 代码 & 效果
Sobel算子
相关理论
-
卷积应用-图像边缘提取
- 边缘是什么?是像素值发生跃迁的地方,是图像的显著特征之一,在图像特征提取、对象检测、模式识别等方面都有重要的作用。
- 如何捕捉/提取边缘 – 对图像求它的一阶导数
d e l t a = f ( x ) – f ( x − 1 ) delta = f(x) – f(x-1) delta=f(x)–f(x−1), delta越大,说明像素在X方向变化越大,边缘信号越强, - 如果已经忘记求导如何计算,不要担心,用Sobel算子就好!卷积操作!边缘提取 。
-
Sobel算子
- 是离散微分算子(discrete differentiation operator),用来计算图像灰度的近似梯度
- Soble算子功能集合高斯平滑和微分求导
- 又被称为一阶微分算子,求导算子,在水平和垂直两个方向上求导,得到图像X方法与Y方向梯度图像。拉普拉斯算子是二阶微分算子。
-
Sobel算子
-
水平梯度
- G x = [ − 1 0 + 1 − 2 0 + 2 − 1 0 + 1 ] ∗ I mathrm{G}_{mathrm{x}}=left[begin{array}{ccc}{-1} & {0} & {+1} \ {-2} & {0} & {+2} \ {-1} & {0} & {+1}end{array}right] * mathrm{I} Gx=⎣⎡−1−2−1000+1+2+1⎦⎤∗I
-
垂直梯度
- G y = [ − 1 − 2 − 1 0 0 0 + 1 + 2 + 1 ] ∗ I mathrm{G}_{mathrm{y}}=left[begin{array}{ccc}{-1} & {-2} & {-1} \ {0} & {0} & {0} \ {+1} & {+2} & {+1}end{array}right] * mathrm{I} Gy=⎣⎡−10+1−20+2−10+1⎦⎤∗I
-
最终图像梯度,2种计算方法:
- G = G x 2 + G y 2 mathbf{G}=sqrt{mathbf{G}_{mathbf{x}}^{2}+mathbf{G}_{mathbf{y}}^{2}} G=Gx2+Gy2
- G = ∣ G x ∣ + ∣ G y ∣ mathbf{G}=left|mathbf{G}_{mathbf{x}}right|+left|mathbf{G}_{mathbf{y}}right| G=∣Gx∣+∣Gy∣
-
-
Sobel算子
- 求取导数的近似值,kernel=3时不是很准确,OpenCV使用改进版本Scharr函数,算子如下:
- G x = [ − 3 0 + 3 − 10 0 + 10 − 3 0 + 3 ] G_{x}=left[begin{array}{ccc}{-3} & {0} & {+3} \ {-10} & {0} & {+10} \ {-3} & {0} & {+3}end{array}right] Gx=⎣⎡−3−10−3000+3+10+3⎦⎤
- G y = [ − 3 − 10 − 3 0 0 0 + 3 + 10 + 3 ] G_{y}=left[begin{array}{ccc}{-3} & {-10} & {-3} \ {0} & {0} & {0} \ {+3} & {+10} & {+3}end{array}right] Gy=⎣⎡−30+3−100+10−30+3⎦⎤
- 求取导数的近似值,kernel=3时不是很准确,OpenCV使用改进版本Scharr函数,算子如下:
-
API说明 -
Sobel
cv::Sobel ( InputArray Src // 输入图像 OutputArray dst// 输出图像,大小与输入图像一致 int depth // 输出图像深度. Int dx. // X方向,几阶导数 int dy // Y方向,几阶导数. int ksize, // SOBEL算子kernel大小,必须是1、3、5、7、 double scale = 1 double delta = 0 int borderType = BORDER_DEFAULT )
其中input_depth
和output_depth
的取值
-
Sobel类似API -
Scharr
- 对边缘得到了更大的加强,一点点扰动是不用担心的,但Sobel算子一点扰动是不行的
cv::Scharr ( InputArray Src // 输入图像 OutputArray dst// 输出图像,大小与输入图像一致 int depth // 输出图像深度. Int dx. // X方向,几阶导数 int dy // Y方向,几阶导数. double scale = 1 double delta = 0 int borderType = BORDER_DEFAULT )
-
使用Sobel算子,计算步骤
- 高斯平滑处理
- 转灰度
- 求梯度 X和Y
- 整幅图像
-
其他需要使用到的API
GaussianBlur( src, dst, Size(3,3), 0, 0, BORDER_DEFAULT );
cvtColor( src, gray, COLOR_RGB2GRAY );
addWeighted( A, 0.5,B, 0.5, 0, AB);
convertScaleAbs(A, B)// 计算图像A的像素绝对值,输出到图像B
2. 代码 & 效果
完整代码:
#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/types_c.h>
using namespace std;
using namespace cv;
#ifndef P17
#define P17 16
#endif
int main() {
std::string path = "../fei.JPG";
cv::Mat img = cv::imread(path, 5);
string str_input = "input image";
string str_output = "output image";
if(img.empty())
{
std::cout << "open file failed" << std::endl;
return -1;
}
#if P18 //Sobel算子
Mat gray;
GaussianBlur(img, img,Size(3,3),0,0);
cvtColor(img,gray, COLOR_BGR2GRAY);
Mat xgrad, ygrad;
Sobel(gray,xgrad,CV_16S, 1,0,3);
Sobel(gray,ygrad,CV_16S, 0,1,3);
convertScaleAbs(xgrad,xgrad);
convertScaleAbs(ygrad,ygrad);
namedWindow("xgrad",WINDOW_AUTOSIZE);
namedWindow("ygrad",WINDOW_AUTOSIZE);
imshow("xgrad",xgrad);
imshow("ygrad",ygrad);
Mat xygrad = Mat(xgrad.size(), xgrad.type());
Mat xygrad_cv = Mat(xgrad.size(), xgrad.type());
printf("type: %dn",xgrad.type());
int width = xgrad.cols;
int height = ygrad.rows;
for(int row=0;row < height; row++)
{
for(int col = 0; col < width; col++)
{
int xg = xgrad.at<uchar>(row,col);
int yg = ygrad.at<uchar>(row,col);
int xy = xg + yg;
xygrad.at<uchar>(row,col) = saturate_cast<uchar>(xy);
}
}
// 求得整体的Sobel,和上面的作用一样。效果比上面的差一些
addWeighted(xgrad,0.5, ygrad, 05, 0, xygrad_cv);
namedWindow("final", WINDOW_AUTOSIZE);
imshow("final",xygrad);
namedWindow("final by cv", WINDOW_AUTOSIZE);
imshow("final by cv",xygrad_cv);
#endif
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}
上面的for循环是逐像素计算梯度,以此求得梯度。addWeighted
和两个for循环的作用一样,效果比addWeighted
好一些。
效果图:
addWeighted
和两个for循环的效果对比,这里是一样的计算原理,为啥不一样有待研究。
改进版本Scharr函数代码,使用Scharr
替换Sobel
即可,其余部分一致:
Scharr(gray,xgrad,CV_16S,1,0);
Scharr(gray,ygrad,CV_16S,0,1);
//Sobel(gray,xgrad,CV_16S, 1,0,3);
//Sobel(gray,ygrad,CV_16S, 0,1,3);
效果如下:
最后
以上就是落后水杯为你收集整理的【OpenCV图像处理】1.17 Sobel算子的全部内容,希望文章能够帮你解决【OpenCV图像处理】1.17 Sobel算子所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复