前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android OpenCV(四十四):图像分割(均值漂移)

Android OpenCV(四十四):图像分割(均值漂移)

作者头像
Vaccae
发布2021-07-30 16:07:06
9400
发布2021-07-30 16:07:06
举报
文章被收录于专栏:微卡智享

图像分割

图像分割就是把图像分成若干个特定的、具有独特性质的区域并提出感兴趣目标的技术和过程。它是由图像处理到图像分析的关键步骤。现有的图像分割方法主要分以下几类:基于阈值的分割方法、基于区域的分割方法、基于边缘的分割方法以及基于特定理论的分割方法等。从数学角度来看,图像分割是将数字图像划分成互不相交的区域的过程。图像分割的过程也是一个标记过程,即把属于同一区域的像素赋予相同的编号。

均值漂移(Mean-Shift)

MeanShfit 均值漂移算法是一种通用的聚类算法,通常可以实现彩色图像分割。

基本思想为:首先随便选择一个中心点,然后计算该中心点一定范围之内所有点到中心点的距离向量的平均值,计算该平均值得到一个偏移均值,然后将中心点移动到偏移均值位置,通过这种不断重复的移动,可以使中心点逐步逼近到最佳位置。这种思想类似于梯度下降方法,通过不断的往梯度下降的方向移动,可以到达梯度上的局部最优解或全局最优解。

算法原理参考:https://www.biaodianfu.com/mean-shift.html#Mean_Shift%E7%AE%97%E6%B3%95%E7%90%86%E8%AE%BA

Mean Shift

算法过程

API

pyrMeanShiftFiltering函数其实也是一种滤波,只能达到平滑图像的效果,无法直接分割图像。但是平滑后的图像更方便我们进行图像分割。

代码语言:javascript
复制
public static void pyrMeanShiftFiltering(Mat src, Mat dst, double sp, double sr, int maxLevel, TermCriteria termcrit)
  • 参数一:src,输入图像,类型为8位三通道。
  • 参数二:dst,输出图像,与src大小类型相同。
  • 参数三:sp,漂移的物理空间半径大小。
  • 参数四:sr,漂移的颜色空间半径大小。
  • 参数五:maxLevel,用于分割的金字塔的最大级别。
  • 参数六:termcrit,终止标准:何时停止均值漂移迭代。

sp,sr越大,平滑效果越明显,处理时间越长

操作

由于Mean-Shift均值漂移无法直接分割图像,我们配合漫水填充法执行分割操作。

代码语言:javascript
复制
/**
 * Mean-Shift 均值漂移
 *
 * @author yidong
 * @date 11/25/20
 */
class MeanShiftActivity : AppCompatActivity() {

    private val mBinding: ActivityMeanShiftBinding by lazy {
        ActivityMeanShiftBinding.inflate(layoutInflater)
    }
    private lateinit var mRgb: Mat

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(mBinding.root)
        mRgb = Mat()
        val bgr = Utils.loadResource(this, R.drawable.number)
        Imgproc.cvtColor(bgr, mRgb, Imgproc.COLOR_BGR2RGB)
        mBinding.ivLena.showMat(mRgb)
        mBinding.isLoading = true
        GlobalScope.launch(Dispatchers.IO) {
            doMeanShift()
        }
    }

    private fun doMeanShift() {
        val dst = Mat()
        Imgproc.pyrMeanShiftFiltering(mRgb, dst, 40.0, 40.0)

        val maskers = Mat(dst.rows() + 2, dst.cols() + 2, CvType.CV_8UC1, Scalar.all(0.0))
        Imgproc.floodFill(
            dst,
            maskers,
            Point(7.0, 7.0),
            Scalar(65.0, 105.0, 225.0),
            Rect(),
            Scalar.all(10.0),
            Scalar.all(10.0),
            Imgproc.LINE_4 or Imgproc.FLOODFILL_FIXED_RANGE or (250 shl 8)
        )

        GlobalScope.launch(Dispatchers.Main) {
            mBinding.isLoading = false
            mBinding.ivResult.showMat(dst)
        }
    }
}

效果

图片分割

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-07-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 微卡智享 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 图像分割
  • 均值漂移(Mean-Shift)
  • API
  • 操作
  • 效果
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档