Sobel算子-边界检测
OpenCV官方教程
原理
Sobel算子
- 近似计算图像梯度
- Horizontal 方向的变化: I I I是输入图像,算出的 G x : G_x: Gx: [ − 1 0 + 1 − 2 0 + 2 − 1 0 + 1 ] ∗ I \left[ \begin{matrix} -1 & 0 & +1 \\ -2& 0 & +2 \\ -1 & 0 & +1 \end{matrix} \right]*I ⎣⎡−1−2−1000+1+2+1⎦⎤∗I
Vertical 方向的变化: I I I是输入图像, G y : G_y: Gy:
[ − 1 − 2 − 1 0 0 0 + 1 + 2 + 1 ] ∗ I \left[ \begin{matrix} -1 & -2 & -1 \\ 0 &0 & 0 \\ +1& +2 & +1 \end{matrix} \right] *I ⎣⎡−10+1−20+2−10+1⎦⎤∗I
输入图像每个像素点的梯度 G = G x 2 + G y 2 G=\sqrt{G_x^2+G_y^2} G=Gx2+Gy2
- 有时候使用以下来近似: G = ∣ G x ∣ + ∣ G y ∣ G=|G_x|+|G_y| G=∣Gx∣+∣Gy∣
Scharr
- 比Sobel更加精确
例程
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat image, src,src_gray;
Mat grad;
const String window_name = "Sobel Demo";
int ksize = 1;
int scale = 1;
int delta = 0;
int ddepth = CV_16S; //进行Sobel操作可能有负值,所以改变深度
String ImageName = "../res/lena.jpg";
image = imread(ImageName,cv::IMREAD_COLOR);
if(image.empty())
{
cout << "can't load the image" << endl;
return -1;
}
for(;;)
{
cv::GaussianBlur(image,src,Size(3,3),0,0); //先滤波,去除噪声
cv::cvtColor(src,src_gray,cv::COLOR_BGR2GRAY);// 转成灰度图像
Mat grad_x, grad_y;
Mat abs_grad_x,abs_grad_y;
Sobel(src_gray,grad_x,ddepth,1,0,ksize,scale,delta); //对x方向进行Sobel操作
Sobel(src_gray,grad_y,ddepth,0,1,ksize,scale,delta);// 对y方向进行 Sobel操作
cv::convertScaleAbs(grad_x,abs_grad_x); //得到结果的绝对值,
cv::convertScaleAbs(grad_y,abs_grad_y);
cv::addWeighted(abs_grad_x,0.5,abs_grad_y,0.5,0,grad); //再将x和y方向的结果结合到一起
imshow(window_name,grad);
char key =(char)waitKey(0);
if(key == 27)
{
return 0 ;
}
if(key =='K' || key == 'k')
{
ksize = ksize < 30 ? ksize+2 :-1;
}
if(key == 's' || key == 'S')
{
scale ++;
}
if(key == 'd' || key == 'D')
{
delta++;
}
if(key == 'r' || key == 'R') //默认参数
{
scale = 1;
ksize = -1;
delta = 0;
}
}
return 0;
};
结果:
OpenCV API
- void cv::Sobel
(
InputArray src, //输入图像
OutputArray dst, //输出图像(和src一样大小、通道数)
int ddepth, //输出图像的深度,见下图
int dx, // 为1 则是 x方向上的求导,否则为0
int dy, //为1 则是 y方向上的求导,否则为0
int ksize = 3, //Sobel核的大小 ,必须是1,3,5,7
double scale = 1, //算出结果 乘以这个值,比例因子
double delta = 0, // 最后处理结果,加上这个值
int borderType = BORDER_DEFAULT //边界处理
)
- void cv::convertScaleAbs :计算绝对值再转成8位
(
InputArray src, //
OutputArray dst, //
double alpha = 1, //
double beta = 0 //
)
计算公式: d s t ( I ) = s a t u r a t e _ c a s t < u c h a r > ( ∣ s r c ( I ) ∗ a l p h a + b e t a ∣ ) dst(I)=saturate\_cast(|src(I)∗alpha+beta|) dst(I)=saturate_cast (∣src(I)∗alpha+beta∣)
- void cv::addWeighted:按权重计算两个图像的和
(
InputArray src1, //
double alpha, //
InputArray src2, //
double beta, //
double gamma, //
OutputArray dst, //
int dtype = -1 // optional depth of the output array
)
计算公式: d s t = s a t u r a t e ( s r c 1 ∗ a l p h a + s r c 2 ∗ b e t a + g a m m a ; ) dst = saturate(src1*alpha + src2*beta + gamma;) dst=saturate(src1∗alpha+src2∗beta+gamma;)
还没有评论,来说两句吧...