[OpenCV学习日记-java]-09-梯度计算和拉普拉斯算子

梯度计算和拉普拉斯算子

计算机图像梯度是很多重要特征提取的关键步骤之一,OpenCV提供了两个非常重要的计算梯度函数Sobel与Scharr

对于图像边缘部分,梯度值会比较大,对于图像的平坦区域梯度值一般比较小

Sobel梯度

Sobel梯度算子可以计算X方向和Y方向Api如下:

Sobel(Mat src, Mat dst, int ddepth, int dx, int dy)
  • src:输入图像

  • dst:输出图像

  • ddepth:输出图像深度
    通常为 CV_32F 或者 CV_32SC
     
    这里需要注意的是 不能让输入如下与输入图像深度相同,当输入图像是8bit时候计算数据会有所溢出,从而导致梯度计算错误

  • dx:表示x方向计算
    1是 2不是

  • dy:表示y方向计算
    1是 2不是

  • int ksize:为进行边缘检测时的模板大小为ksizeksize,取值为1、3、5和7,其中默认值为3。特殊情况:ksize=1时,采用的模板为31或1*3。
    当ksize=3时,Sobel内核可能产生比较明显的误差;

下面通过代码演示

Mat m1 = Imgcodecs.imread("C:\\test\\256_256_t1.png" );

HighGui.imshow("原图",m1);

Imgproc.cvtColor(m1,m1,Imgproc.COLOR_BGR2GRAY);

Mat s1 = new Mat();
Imgproc.Sobel(m1,s1, CvType.CV_32F,1,0);//x方向

//Mat转换成8位,如果不写将不能展示
Core.convertScaleAbs(s1,s1);

Mat s2 = new Mat();
Imgproc.Sobel(m1,s2, CvType.CV_32F,0,1);//y方向
Core.convertScaleAbs(s2,s2);

Mat s3 = new Mat();
Core.add(s1,s2,s3); //图像相加

HighGui.imshow("X方向",s1);
HighGui.imshow("Y方向",s2);
HighGui.imshow("相加后",s3);

这样就把边缘提取出来了

这里需要注意的是下面这一个代码

Core.convertScaleAbs(Mat src, Mat dst);

这个方法就是转换成8位图像

在这里插入图片描述


Scharr梯度

Scharr是Sobel的升级加强版本

Api如下:

Scharr(Mat src, Mat dst, int ddepth, int dx, int dy)

这里和Sobel方法一样 ,所以这里就不一个个解释了

完全可以直接把Sobel直接改成Scharr

Mat m1 = Imgcodecs.imread("C:\\test\\256_256_t1.png" );

HighGui.imshow("原图",m1);

Imgproc.cvtColor(m1,m1,Imgproc.COLOR_BGR2GRAY);

Mat s1 = new Mat();
Imgproc.Scharr(m1,s1, CvType.CV_32F,1,0);//x方向

//Mat转换成8位,如果不写将不能展示
Core.convertScaleAbs(s1,s1);

Mat s2 = new Mat();
Imgproc.Scharr(m1,s2, CvType.CV_32F,0,1);//y方向
Core.convertScaleAbs(s2,s2);

Mat s3 = new Mat();
Core.add(s1,s2,s3); //图像相加

HighGui.imshow("X方向",s1);
HighGui.imshow("Y方向",s2);
HighGui.imshow("相加后",s3);

在这里插入图片描述


拉普拉斯算子

拉普拉斯算子可以用在图片增强,也可以用扎边缘检测,但是会很麻烦

Laplacian(Mat src, Mat dst, int ddepth, int ksize, double scale, double delta) 
  • src:输入图像
  • dst:输出图像
  • ddepth:输出图像深度,常见的是CV_32F
  • ksize:常见的是3x3 ksize = 3
  • scale:是否缩放 默认=1
  • delta:是否调整图像 默认 = 0

下面通过代码演示

Mat m1 = Imgcodecs.imread("C:\\test\\256_256_t1.png" );
 
HighGui.imshow("原图",m1);

Mat s1 = new Mat();
Imgproc.Laplacian(m1,s1, CvType.CV_32F);

Core.convertScaleAbs(s1,s1);

Mat s2 = new Mat();
Imgproc.Laplacian(m1,s2, CvType.CV_32F,3,1,0);//ksize = 3

Core.convertScaleAbs(s2,s2);

HighGui.imshow("默认ksize",s1);
HighGui.imshow("ksize=3",s2);

在这里插入图片描述


上一篇[OpenCV学习日记-java]-08-阈值化和阈值

发布了34 篇原创文章 · 获赞 32 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_18604209/article/details/104074549
今日推荐