sobel滤波器(sobel)

导读 你们好,最近小活发现有诸多的小伙伴们对于sobel滤波器,sobel这个问题都颇为感兴趣的,今天小活为大家梳理了下,一起往下看看吧。1、思想

你们好,最近小活发现有诸多的小伙伴们对于sobel滤波器,sobel这个问题都颇为感兴趣的,今天小活为大家梳理了下,一起往下看看吧。

1、思想:

2、算子使用两个3*3的矩阵算子分别和原始图片作卷积,分别得到横向Gx和纵向Gy的梯度值,如果梯度值大于某一个阈值,则认为该点为边缘点;

3、矩阵转换:

4、事实上卷积矩阵也可以由两个一维矩阵卷积而成,在opencv源码中就是用两个一维矩阵卷积生成一个卷积矩阵:

5、梯度值:

6、图像的梯度值由以下公式计算:

7、图像近似梯度值如下:

8、对于原始图像,P5的梯度值为:

9、OpenCV2410,sobel算子函数原型:

10、void Sobel(InputArray src,

11、OutputArray dst,

12、int ddepth,

13、int dx,

14、int dy,

15、int ksize=3,

16、double scale=1,

17、double delta=0,

18、int borderType=BORDER_DEFAULT )

19、函数参数解释:

20、InputArray src:输入的原图像,Mat类型

21、OutputArray dst:输出的边缘检测结果图像,Mat类型,大小与原图像相同。

22、int ddepth:输出图像的深度,针对不同的输入图像,输出目标图像有不同的深度,具体组合如下:

23、- 若src.depth() = CV_8U, 取ddepth =-1/CV_16S/CV_32F/CV_64F

24、- 若src.depth() = CV_16U/CV_16S, 取ddepth =-1/CV_32F/CV_64F

25、- 若src.depth() = CV_32F, 取ddepth =-1/CV_32F/CV_64F

26、- 若src.depth() = CV_64F, 取ddepth = -1/CV_64F

27、注:ddepth =-1时,代表输出图像与输入图像相同的深度。

28、int dx:int类型dx,x 方向上的差分阶数,1或0

29、int dy:int类型dy,y 方向上的差分阶数,1或0

30、其中,dx=1,dy=0,表示计算X方向的导数,检测出的是垂直方向上的边缘;

31、dx=0,dy=1,表示计算Y方向的导数,检测出的是水平方向上的边缘。

32、int ksize:为进行边缘检测时的模板大小为ksize*ksize,取值为1、3、5和7,其中默认值为3。特殊情况:ksize=1时,采用的模板为3*1或1*3。

33、当ksize=3时,Sobel内核可能产生比较明显的误差;

34、double scale:默认1。

35、double delta:默认0。

36、int borderType:默认值为BORDER_DEFAULT。

37、Sobel调用格式:

38、sobel算法代码实现过程为:

39、// 求 X方向梯度

40、Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT );

41、// 求 Y方向梯度

42、Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );

43、convertScaleAbs( grad_x, abs_grad_x );

44、convertScaleAbs( grad_y, abs_grad_y );

45、addWeighted( dst_x, 0.5, dst_y, 0.5, 0, dst); //一种近似的估计

46、Sobel算子实现:

47、#include <opencv2\opencv.hpp>

48、using namespace std;

49、using namespace cv;

50、int main( int argc, char** argv )

51、{

52、 Mat in_img = imread("raw.jpg",0);

53、 if (!in_img.data)

54、 {

55、 return -1;

56、 }

57、 Mat out_img_dx = Mat::zeros(in_img.size(),CV_16SC1);

58、 Mat out_img_dy = Mat::zeros(in_img.size(),CV_16SC1);

59、 Mat out_img_dxy = Mat::zeros(in_img.size(),CV_16SC1);

60、 GaussianBlur(in_img,in_img,Size(3,3),0);

61、 unsigned char* p_data = (unsigned char*)in_img.data;

62、 unsigned char* p_data_dx = (unsigned char*)out_img_dx.data;

63、 unsigned char* p_data_dy = (unsigned char*)out_img_dy.data;

64、 int step = in_img.step;

65、 for (int i=1;i<in_img.rows-1;i++)

66、 {

67、 for (int j=1;j<in_img.cols-1;j++)

68、 {

69、 //通过指针遍历图像上每一个像素

70、 p_data_dx[i*out_img_dx.step+j*(out_img_dx.step/in_img.step)]=abs(p_data[(i-1)*in_img.step+j+1]+2*p_data[i*in_img.step+j+1]+p_data[(i+1)*in_img.step+j+1]

71、 -p_data[(i-1)*in_img.step+j-1]-2*p_data[i*in_img.step+j-1]-p_data[(i+1)*in_img.step+j-1]);

72、 p_data_dy[i*out_img_dy.step+j*(out_img_dy.step/in_img.step)]=abs(p_data[i*in_img.step+j-1]+2*p_data[i*in_img.step+j]+p_data[i*in_img.step+j+1]

73、 -p_data[(i+1)*in_img.step+j-1]-2*p_data[(i+1)*in_img.step+j]-p_data[(i+1)*in_img.step+j+1]);

74、 }

75、 }

76、 addWeighted(out_img_dx,0.5,out_img_dy,0.5,0,out_img_dxy);

77、 Mat img_dx,img_dy,img_dxy;

78、 convertScaleAbs(out_img_dx,img_dx);

79、 convertScaleAbs(out_img_dy,img_dy);

80、 convertScaleAbs(out_img_dxy,img_dxy);

81、 imshow("raw img",in_img);

82、 imshow("x direction",img_dx);

83、 imshow("y direction",img_dy);

84、 imshow("xy direction",img_dxy);

85、 Mat sobel_img;

86、 Sobel(in_img,sobel_img,CV_8UC1,1,1,3);

87、 imshow("opencv sobel",sobel_img);

88、 waitKey( 0 );

89、 return 0;

90、}

91、OpenCV内源码:

92、static void getSobelKernels( OutputArray _kx, OutputArray _ky, int dx, int dy, int _ksize, bool normalize, int ktype )

93、{

94、 int i, j, ksizeX = _ksize, ksizeY = _ksize;

95、 if( ksizeX == 1 && dx > 0 )

96、 ksizeX = 3;

97、 if( ksizeY == 1 && dy > 0 )

98、 ksizeY = 3;

99、 CV_Assert( ktype == CV_32F || ktype == CV_64F );

100、 _kx.create(ksizeX, 1, ktype, -1, true);

101、 _ky.create(ksizeY, 1, ktype, -1, true);

102、 Mat kx = _kx.getMat();

103、 Mat ky = _ky.getMat();

104、 if( _ksize % 2 == 0 || _ksize > 31 )

105、 CV_Error( CV_StsOutOfRange, "The kernel size must be odd and not larger than 31" );

106、 std::vector<int> kerI(std::max(ksizeX, ksizeY) + 1);

107、 CV_Assert( dx >= 0 && dy >= 0 && dx+dy > 0 );

108、 for( int k = 0; k < 2; k++ )

109、 {

110、 Mat* kernel = k == 0 ? &kx : &ky;

111、 int order = k == 0 ? dx : dy;

112、 int ksize = k == 0 ? ksizeX : ksizeY;

113、 CV_Assert( ksize > order );

114、 if( ksize == 1 )

115、 kerI[0] = 1;

116、 else if( ksize == 3 )

117、 {

118、 if( order == 0 )

119、 kerI[0] = 1, kerI[1] = 2, kerI[2] = 1;

120、 else if( order == 1 )

121、 kerI[0] = -1, kerI[1] = 0, kerI[2] = 1;

122、 else

123、 kerI[0] = 1, kerI[1] = -2, kerI[2] = 1;

124、 }

125、 else

126、 {

127、 int oldval, newval;

128、 kerI[0] = 1;

129、 for( i = 0; i < ksize; i++ )

130、 kerI[i+1] = 0;

131、 for( i = 0; i < ksize - order - 1; i++ )

132、 {

133、 oldval = kerI[0];

134、 for( j = 1; j <= ksize; j++ )

135、 {

136、 newval = kerI[j]+kerI[j-1];

137、 kerI[j-1] = oldval;

138、 oldval = newval;

139、 }

140、 }

141、 for( i = 0; i < order; i++ )

142、 {

143、 oldval = -kerI[0];

144、 for( j = 1; j <= ksize; j++ )

145、 {

146、 newval = kerI[j-1] - kerI[j];

147、 kerI[j-1] = oldval;

148、 oldval = newval;

149、 }

150、 }

151、 }

152、 Mat temp(kernel->rows, kernel->cols, CV_32S, &kerI[0]);

153、 double scale = !normalize ? 1. : 1./(1 << (ksize-order-1));

154、 temp.convertTo(*kernel, ktype, scale);

155、 }

156、}

以上就是sobel这篇文章的一些介绍,希望对大家有所帮助。

标签:

免责声明:本文由用户上传,如有侵权请联系删除!