Laplacian 算子
Laplacian算子具有各方向同性的特点,能够对任意方向的边缘进行提取,具有无方向性的优点,因此使用Laplacian算子提取边缘不需要分别检测X方向的边缘和Y方向的边缘,只需要一次边缘检测即可。Laplacian算子是一种二阶导数算子,对噪声比较敏感,因此常需要配合高斯滤波一起使用。
如果邻域系统是4邻域,Laplacian 算子的模板为:
如果邻域系统是8邻域,Laplacian 算子的模板为:
API
public static void Laplacian(Mat src, Mat dst, int ddepth, int ksize, double scale, double delta, int borderType)
- 参数一:src,输入图像。
- 参数二:dst,输出图像,与输入图像具有相同的尺寸和通道数。
- 参数三:ddepth,输出图像的数据类型(深度),根据输入图像的数据类型不同拥有不同的取值范围。当赋值为-1时,输出图像的数据类型自动选择。
- 参数四:ksize,滤波器的大小,必须为正奇数。
- 参数五:scale,对导数计算结果进行缩放的缩放因子,默认系数为1,不进行缩放
- 参数六:delta,偏值,在计算结果中加上偏值。
- 参数七:borderType,像素外推法选择标志。默认参数为BORDER_DEFAULT,表示不包含边界值倒序填充。
函数的前两个参数分别为输入图像和输出图像,第三个参数为输出图像的数据类型,这里需要注意由于提取边缘信息时有可能会出现负数,因此不要使用CV_8U数据类型的输出图像,否则会使得图像边缘提取不准确。函数第四个参数是滤波器尺寸的大小,必须是正奇数,当该参数的值大于1时,该函数通过Sobel算子计算出图像X方向和Y方向的二阶导数,将两个方向的导数求和得到Laplacian算子。
操作
/**
* Laplacian算子-边缘检测
*
* @author yidong
* @date 2020-05-18
*/
class LaplacianEdgeDetectionActivity : AppCompatActivity() {
private lateinit var mBinding: ActivityEdgeDetectionBinding
private lateinit var mRgb: Mat
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_edge_detection)
val bgr = Utils.loadResource(this, R.drawable.lena)
mRgb = Mat()
Imgproc.cvtColor(bgr, mRgb, Imgproc.COLOR_BGR2RGB)
showMat(mBinding.ivLena, mRgb)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_laplacian, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.without_blur_edge_detection -> {
edgeDetection()
}
R.id.with_blur_edge_detection -> {
edgeDetectionAfterBlur()
}
}
return true
}
private fun showMat(view: ImageView, source: Mat) {
val bitmap = Bitmap.createBitmap(source.width(), source.height(), Bitmap.Config.ARGB_8888)
bitmap.density = 360
Utils.matToBitmap(source, bitmap)
view.setImageBitmap(bitmap)
}
private fun edgeDetection() {
title = "Laplacian边缘检测"
val result = Mat()
Imgproc.Laplacian(mRgb, result, CvType.CV_16S, 3, 1.0, 0.0)
Core.convertScaleAbs(result, result)
showMat(mBinding.ivResult, result)
}
private fun edgeDetectionAfterBlur() {
title = "高斯滤波后Laplacian边缘检测"
val resultG = Mat()
val result = Mat()
Imgproc.GaussianBlur(mRgb, resultG, Size(3.0, 3.0), 5.0, 0.0)
Imgproc.Laplacian(resultG, result, CvType.CV_16S, 3, 1.0, 0.0)
Core.convertScaleAbs(result, result)
showMat(mBinding.ivResult, result)
}
}
效果