Scharr算子
Scharr算子是对Sobel算子差异性的增强,因此两者之间的在检测图像边缘的原理和使用方式上相同。Scharr算子的边缘检测滤波的尺寸为3×3,因此也有称其为Scharr滤波器。可以通过将滤波器中的权重系数放大来增大像素值间的差异,弥补Sobel算子对图像中较弱的边缘提取效果较差的缺点。
API
public static void Scharr(Mat src, Mat dst, int ddepth, int dx, int dy, double scale, double delta, int borderType)
- 参数一:src,输入图像。
- 参数二:dst,输出图像,与输入图像具有相同的尺寸和通道数。
- 参数三:ddepth,输出图像的数据类型(深度),根据输入图像的数据类型不同拥有不同的取值范围。当赋值为-1时,输出图像的数据类型自动选择。
- 参数四:dx,X方向的差分阶数。
- 参数五:dy,Y方向的差分阶数
- 参数六:scale,对导数计算结果进行缩放的缩放因子,默认系数为1,不进行缩放
- 参数七:delta,偏值,在计算结果中加上偏值。
- 参数八:borderType,像素外推法选择标志。默认参数为BORDER_DEFAULT,表示不包含边界值倒序填充。
函数第四个和五个参数是提取X方向边缘还是Y方向边缘的标志,该函数要求这两个参数只能有一个参数为1,并且不能同时为0,否则函数将无法提取图像边缘,该函数默认的滤波器尺寸为3×3,并且无法修改因此相比Sobel算子少一个参数
操作
/**
* Scharr算子-边缘检测
*
* @author yidong
* @date 2020-05-17
*/
class ScharrEdgeDetectionActivity : 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)
}
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)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_scharr, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.scharr_edge_detection_x -> {
edgeDetectionX()
}
R.id.scharr_edge_detection_y -> {
edgeDetectionY()
}
R.id.scharr_edge_detection_x_y -> {
edgeDetectionXAndY()
}
}
return true
}
private fun edgeDetectionX() {
title = "X轴方向边缘检测"
val resultX = Mat()
Imgproc.Scharr(mRgb, resultX, CvType.CV_16S, 1, 0)
Core.convertScaleAbs(resultX, resultX)
showMat(mBinding.ivResult, resultX)
}
private fun edgeDetectionY() {
title = "Y轴方向边缘检测"
val resultY = Mat()
Imgproc.Scharr(mRgb, resultY, CvType.CV_16S, 0, 1)
Core.convertScaleAbs(resultY, resultY)
showMat(mBinding.ivResult, resultY)
}
private fun edgeDetectionXAndY() {
title = "X和Y轴方向边缘检测"
val resultX = Mat()
Imgproc.Scharr(mRgb, resultX, CvType.CV_16S, 1, 0)
Core.convertScaleAbs(resultX, resultX)
showMat(mBinding.ivResult, resultX)
val resultY = Mat()
Imgproc.Scharr(mRgb, resultY, CvType.CV_16S, 0, 1)
Core.convertScaleAbs(resultY, resultY)
showMat(mBinding.ivResult, resultY)
val resultXY = Mat()
Core.add(resultX, resultY, resultXY)
showMat(mBinding.ivResult, resultXY)
resultX.release()
resultY.release()
resultXY.release()
}
}
效果
源码
https://github.com/onlyloveyd/LearningAndroidOpenCV
扫码关注,持续更新
回复【计算机视觉】获取计算机视觉相关必备学习资料
回复【Android】获取Android,Kotlin必备学习资料
个人公众号【OpenCV or Android】,热爱Android、Kotlin、Flutter和OpenCV。毕业于华中科技大学计算机专业,曾就职于华为武汉研究所。目前在三线小城市生活,专注Android、OpenCV、Kotlin、Flutter等有趣的技术。