mean shift 图像分割 (一)

article/2025/8/22 23:13:13

mean shift 图像分割

Reference:

[1] Mean shift: A robust approach toward feature space analysis, PAMI, 2002

[2] mean shift,非常好的ppt ,百度文库链接

[3] Pattern Recognition and Machine Learning, Bishop, 2006,Sec 2.5

[4] Computer Vision Algorithms and Applications, Richard Szeliski, 2010, Sec 5.3

[5] Kernel smoothing,MP Wand, MC Jones ,1994, Chapter 4


mean shift 图像分割 (一)1 总体思想,2 算法步骤

mean shift 图像分割 (二): 3 算法原理,4 延伸

mean shift 图像分割 (三): 5 非参数密度估计

图像分割—mean shift(OpenCV源码注解)


写在前头的话:这篇笔记看起来公式巨多,实际上只是符号表示,没啥公式推导,不过,多了就难免有差错,欢迎指正。

    Mean shitf的故事说来挺励的,早在1975年就诞生了,接着就是漫长的黑暗岁月,黑暗到几乎淡出了人们的视野,不过,命运总是善良的,95年又重新焕发生机,各种应用喷薄而出,包括目标跟踪,边缘检测,非极大值抑制等。这次就只介绍在图像分割中的应用吧,其它的我也没看。Mean shitf过程也充满正能量,描绘的是如何通过自己的努力,一步一步爬上顶峰的故事。

1 总体思想

图 1 特征空间映射:RGB图片 -> L-u特征空间

    首先meanshift是一种特征空间分析方法,要利用此方法来解决特定问题,需要将该问题映射到特征空间。对于图像分割,我们可以映射到颜色特征空间,比如将RGB图片,映射到Luv特征空间,图1是L-u二维可视化的效果。

    图像分割就是求每一个像素点的类标号。类标号取决于它在特征空间所属的cluster。对于每一个cluster,首先得有个类中心,它深深地吸引着一些点,就形成了一个类,即类中心对类中的点构成一个basin of attraction ,好比咱们的太阳系。如此,图像分割问题,就可以看成对每个像素点,找它的类中心问题,因为找到类中心就知道它是属于那一类啦,即类中心一样的点就是一类。

图2标准化后的概率密度可视化效果 -> 聚类分割结果

    密度估计的思路需要解决两个问题,what:中心是什么?how:怎么找?mean shift认为中心是概率密度(probalility density function )的极大值点,如图2中的红色点,原文称之为mode,我这暂且用模点吧(某篇论文是如此称呼)。对于每个点怎样找到它的类中心呢?只要沿着梯度方向一步一步慢慢爬,就总能爬到极值点,图2中黑色的线,就是爬坡的轨迹。这种迭代搜索的策略在最优化中称之为 multiple restart gradient descent。不过,一般的gradient descent并不能保证收敛到局部极值,但mean shift 可以做到,因为它的步长是自适应调整的,越靠近极值点步长越小。

    也就是说meanshift的核心就两点,密度估计(Density Estimation) 和mode 搜索。对于图像数据,其分布无固定模式可循,所以密度估计必须用非参数估计,选用的是具有平滑效果的核密度估计(Kernel density estimation,KDE)。

2 算法步骤

截取这一块可视化

(a)灰度图可视化à(b)mean shift模点路径à(c)滤波后效果à(d)分割结果

    分三步走:模点搜索/图像平滑、模点聚类/合并相似区域、兼并小区域(可选)。模点搜索是为了找到每个数据点的到类中心,以中心的颜色代替自己的颜色,从而平滑图像。但模点搜索得到的模点太多,并且很多模点挨得很近,若果将每个模点都作为一类的话,类别太多,容易产生过分割,即分割太细,所以要合并掉一些模点,也就是合并相似区域。模点聚类后所得到的分割区域中,有些区域所包含的像素点太少,这些小区域也不是我们想要的,需要再次合并。

2.1 模点搜索/图像平滑

    建议先看[2]中的演示(P4-12)

    图像中的点包括两类信息:坐标空间(spatial,),颜色空间(range ,)。这些就构成了特征空间。

    模点搜索(OpenCV):某一个点它在联合特征空间迭代搜索它的mode/模点

    图像平滑: 将模点的颜色值赋给它自己,即.对应原文中的图像平滑,实质上是通过模点搜索,达到图像平滑的效果, 所以我合并为以一步。

    设点依次爬过的脚印为:

    出发时,它所收敛到的模点为,c代表convergence。

    第一步:如果迭代次数超过最大值(默认最多爬5次),结束搜索跳到第四步,否则,在坐标空间,筛选靠近的数据点进入下一步计算。

    OpenCV是以的坐标 为中心,边长为的方形区域内的数据点。

    其实,本应用为中心,为半径的圆形区域,那样效果更好,但是循环计算时并不方便,所以用方形区域近似。

    第二步:使用第一步幸存下来的点计算重心,并向重心移动。

    写得有点复杂了,下面解释下。是某种核函数,比如高斯分布, 是颜色空间的核平滑尺度。OpenCV使用的是最简单的均匀分布:

二维可视化效果

    是一个以(第步位置的颜色值)为球心,半径为的球体,球体内部值为1,球体外部值为0。对于经过上一步筛选后幸存的数据点,如果其颜色值满足,也就是颜色值落也在球内,那么求重心时,就要算上,否则落在球外,算重心时,就不带上它。实际上,上一步是依据坐标空间距离筛选数据点,是依据颜色距离进一步筛选数据点,上一步的筛子是矩形,这一步是球体

    简而言之,设满足的点依次为,那么重心计算公式可以进一步化简为:

    是不是很简单呢,初中知识吧。

    注意:上文中的两个参数,是Mean shift最核心的两个参数(还有一个可选的M),具有直观的意义,分别代表坐标空间和颜色空间的核函数带宽。

    第三步:判断是否到模点了,到了就停止。

    如果,移动后颜色或者位置变化很小,则结束搜索,跳到第四步,否则重返第一步,从继续爬。

OpenCV停止搜索的条件:

    (1)坐标距离不变

    (2)颜色变化值很小

    满足一条就可以功成身退,否则继续努力。

    第四步:将模点的颜色赋给出发点/,即

    注意:原文这一步,不仅将模点的颜色值赋给,顺带把坐标值也赋给了,也就是说

2.2 合并相似区域/模点聚类

    合并上一步平滑后的图像。OpenCV采用flood fill函数实现,原理很简单,看下wiki的动画就知道了,模拟洪水浸满峡谷的效果。基本上就是区域生长,从某一点出发,如果和它附近的点(4/8邻域)的颜色值相似就合并,同时再从新合并的点出发继续合并下去,直到碰到不相似的点或者该点已经属于另一类了,此时,就退回来,直到退无可退(所有的4/8邻域搜索空间都已经搜索完毕)。

    虽然很简单,但是不同的方法还是有很多需要注意的细节问题。这里假设滤波后的图像用表示。

    滤波后的两个像素点,是否合并,可以使用颜色相似度和空间位置相似性判定。

    OpenCV只考虑颜色相似性,而忽略模点的坐标是否相似。而原算法综合了二者的信息。如果像素点,满足或者, 则这两个像素点就合并。不过OpenCV也是有考虑坐标位置的,它是只考虑原空间的4/8邻域,而原文是考虑特征空间模点的 ,相当于说OpenCV的(原空间)。

    此外,floodfill有一个特点,它不能越过已经被分类的区域,再加上没有第三步,使得OpenCV的结果,真的是惨不忍睹。原文的合并算法,具体怎么合并的还得看源代码。不过,应该不是用flood fill。

    《Computer Vision A Modern Approach》中是使用类平均距离判定是否合并。比如,能否合并成,取决于类平均距离:

    这样做我觉得效果会更好,因为它不是单独依据边界上的两个点来判定是否合并,它是依据两个区域内部所有的点的信息综合判断。所以,它能合并两个区域,而原算法和OpenCV只能是两个点合并成一个区域,该区域又不断地合并点,一旦一个区域已经完成生长,那么它就不会和别的区域合并了。可以反证。假设先形成,区域生长的时候把给合并了,那么必定有两个点满足相似关系,连接了二者,假设这两个点为相似,那么生长的时候就肯定已经把点合并进来了,接着把所拥有的区域全盘接收,根本不会让区域自成一类。

    当然考虑Outlier,使用中值更好。

    假设合并之后得到m类。对于原文的算法,每个像素点的标号就是其模点所属的模点集合的类标号,比如。不过,OpenCV是所属集合的类标号。

    不过,从原文结果来看,得到的结果并不是类标号,因为类标号一般都是序号,比如1,2,……,然后显示分割结果的时候,就给每一类随机分配一种独有的颜色。但原文的分割结果貌似是这一类的总体颜色值,我猜测原算法可能是用(加权)求平均的方式得到类的颜色值,然后属于这一类的像素点就用这个颜色代替。

    注意:这一步实现的是合并相似区域,但本质上还是而是合并模点,或者说模点聚类,因为每个像素点的值,就是它所属模点的颜色值/模点的联合信息

2.3 兼并小区域

 

OpenCV的分割结果

    上一步合并了一些模点,但是,对于一些小区域,如果它和周围的颜色差异特别大,那么它们也会自成一类,这些小家伙让需要进一步合并。不过,OpenCV的实现中,并没有包含这一步,所以分割出的结果中包含了太多芝麻大点的区域,本人很不满意,有时间再加进去,还得优化下代码,这个实现实在是太慢了。怎么兼并小的区域呢?原文没说,我也没看他的源代码,我们可以直接将包含像素点少于的区域与它最相似的区域合并,实际中,小区域往往是被大区域兼并了。


http://chatgpt.dhexx.cn/article/91ouZnFT.shtml

相关文章

【图像处理】图像分割之(一~四)GraphCut,GrabCut函数使用和源码解读(OpenCV)

图像分割之(一)概述 http://blog.csdn.net/zouxy09 所谓图像分割指的是根据灰度、颜色、纹理和形状等特征把图像划分成若干互不交迭的区域,并使这些特征在同一区域内呈现出相似性,而在不同区域间呈现出明显的差异性。我们先对目前…

Mac 安装使用 OpenCV 图像处理神器

大家好,我是青空。 最近在折腾图像处理相关的事情,今天就给大家分享一下,Mac 上如何安装和使用 OpenCV。 安装 方法一 使用homebrew安装 其实 Mac 上安装 OpenCV 很简单,一个命令行就能搞定。 brew install opencv等待完成即…

sec和asec--正割和反正割函数

【功能简介】求变量的正割和反正割。 【语法格式】 1.Ysec (X) 计算X的正割,sec(x)1/cos(x)。X可以为向量、矩阵或多维数组,X中的元素可以为复数,所有表示角度的变量都采用弧度来表示。 2.Yasec (X) 计算X的反正割。对…

Graph Cut(图割算法)

转载自:http://blog.csdn.net/zouxy09/article/details/8532111 Graph cuts是一种十分有用和流行的能量优化算法,在计算机视觉领域普遍应用于前背景分割(Image segmentation)、立体视觉(stereo vision)、抠…

sech和asech--双曲正割和反双曲正割函数

【功能简介】求变量的双曲正割和反双曲正割。 【语法格式】 1.Ysech(X) 计算X的双曲正割,sech(x)1/cosh(x)。X可以为向量、矩阵或多维数组,X中的元素可以为复数,所有表示角度的变量都采用弧度来表示。 2.Yasech (X) 计…

三角函数中的正弦、余弦、正切、余切、正割、余割函数性质及常用公式

三角函数 三角函数包括正弦、余弦、正切、余切、正割、余割函数 0 基础知识 正弦(Sine):sin A CB/CA 余弦(Cosine) :cos A AB/CA 正切(Tangent):tan A CB/BA 余切&a…

数学 三角函数 sin 正弦、cos 余弦、tan 正切、cot 余切、sec 正割、csc 余割 简介

目录 图解定义 文字定义 三角函数诱导公式 1.三角函数诱导公式记忆方法 2.三角函数诱导公式 诱导公式一:终边相同的角的同一三角函数的值相等 诱导公式二:πα的三角函数值与α的三角函数值之间的关系 诱导公式三:任意角α与-α的三角…

sinx、cscx、cosx、secx以及tanx、cotx图像详解

今天在复习三角函数一章中对正切正割等图像感觉比较有意思,仔细梳理了以下内容: sin:sine cos:cosine sec:secant csc:cosecant 首先明确定义:让我们解释一下sec(x)和cos(x)之间的关系。sec(x)是…

正割函数(sec)

1. 定义 正割与余弦互为倒数,余割与正弦互为倒数。即: ⎧⎩⎨⎪⎪⎪⎪secθ1cosθcscθ1sinθ \left\{ \begin{split}\secθ=\frac1{\cosθ} \\\cscθ=\frac1{\sinθ} \end{split} \right.也即在几何上,设 △ABC ,∠C90&#xff…

printf 输出格式、域宽

printf: 函数原型:int printf("格式控制串",输出表); 返回值:成功则返回输出的字节数(按终端统计) 格式控制符: %d ---- 有符号的十进制整型数 %u ---- 无符号的十进制整型数 %hd --- short …

C语言之printf输出各种格式

基础的东西总是很容易忘,要经常回顾: printf函数调用的一般形式为: printf(“格式控制字符串”, 输出表列) 其中格式控制字符串用于指定输出格式。格式控制串可由格式字符串和非格式字符串两种组成。格式字符串是以%开头的字符串&#xf…

C语言scanf怎么输入字母,C语言scanf输入格式printf输出格式

1. 转化说明符 %a(%A)浮点数,十六进制数字和p-(P-)表示法(C99)%c个字符 %d个有符号十进制整数 %f浮点数(包括浮点数和doulbe)%e(%E)浮点指数输出[e-(E-)表示法]%g(%G)浮点数不显示无意义的零“ 0”“ %i有符号十进制整数(与%d相同)%u无符号十进制整数 %o八进制整…

matlab printf格式化输出,如何使用 printf 来格式化输出

当我开始学习 Unix 时,我很早就接触到了 echo 命令。同样,我最初的 Python 课程也涉及到了 print 函数。再想起学习 C++ 和 Java 时学到 cout 和 systemout。似乎每种语言都骄傲地宣称拥有一种方便的单行输出方法,并生怕这种方式要过时一样宣传它。 但是当我翻开中级教程的第…

printf输出格式

1.printf()简介 printf()是C语言标准库函数,用于将格式化后的字符串输出到标准输出。标准输出,即标准输出文件,对应终端的屏幕。printf()申明于头文件stdio.h。 函数原型: int printf ( const char * format, ... );1 返回值&…

【Python笔记】SciPy的统计模块:scipy.stats

【Python笔记】NumPy数组 【DA】数据可视化matplotlib 【Python笔记】pandas常用函数图码总结 SciPy的统计模块是scipy.stats,其中有一个类是连续分布的实现,一个类是离散分布的实现。此外,该模块中还有很多用于统计检验的函数。 # 导入包 f…

使用scipy.signal函数进行信号滤波

目录 1、scipy.signal.filtfilt()函数介绍2、滤波器构造函数(巴特沃斯滤波器)3、如何进行高通、低通、带通、带阻滤波 1、scipy.signal.filtfilt()函数介绍 在信号的滤波过程中,因为scipy.signal.filtfilt()函数可以方便快捷得实现常见的多种滤波功能,所…

SciPy简单应用

SciPy简单应用 SciPy是在NumPy的基础上增加了大量用于数学计算,科学计算以及工程计算的模块,包括线性代数,常微分方程求解,信号处理,图像处理于稀疏矩阵等。参考文档 目录 SciPy简单应用文件输入/输出:scip…

使用scipy来进行曲线拟合

导读 曲线拟合的应用在生活中随处可见,不知道大家是否还记得物理实验中的自由落体运动中下降高度与时间关系之间的探究,在初速度为0的情况下,我们想要探究下降高度与时间的关系。 我们当时采用的方法是通过设置不同的下降时间来记录下降的高…

SciPy 优化

章节 SciPy 介绍SciPy 安装SciPy 基础功能SciPy 特殊函数SciPy k均值聚类SciPy 常量SciPy fftpack(傅里叶变换)SciPy 积分SciPy 插值SciPy 输入输出SciPy 线性代数SciPy 图像处理SciPy 优化SciPy 信号处理SciPy 统计 优化是指在某些约束条件下,求解目标函数最优解的…

Python scipy拟合分布

scipy 拟合分布文档:https://docs.scipy.org/doc/scipy/reference/tutorial/stats.html#fitting-distributions 代码: import numpy as np from scipy import statsnumber np.random.normal(10, 5, 4000) # 生成均值为10,方差为5的正态分布…