C# 的计算机视觉应用 - 模糊 C 均值聚类






4.88/5 (23投票s)
此代码执行彩色图像的模糊 C-means 聚类和分割,并可用于特征提取。
引言
图像分割,即根据一组特征将图像划分为同质区域,是图像分析和计算机视觉的关键要素。聚类是可用于此目的的方法之一。聚类是一个过程,可用于根据像素的颜色或灰度强度相似性来对像素进行分类。
K-means 算法已被用于快速而明确的“硬”分割。模糊集理论通过允许部分隶属度的概念,改进了这一过程,其中图像像素可以属于多个簇。这种“软”聚类允许更精确地计算簇成员资格,并已成功用于图像聚类以及医学、地质和卫星图像的无监督分割。
算法
模糊 C-means (FCM) 算法遵循与 K-means 算法相同的原理,即它将每个像素的 RGB 值与簇中心的进行比较。主要区别在于,它不是对像素应该属于哪个簇做出硬性决定,而是为每个簇分配一个介于 0 和 1 之间的值,描述“该像素在多大程度上属于该簇”。模糊规则指出,像素对所有簇的隶属值之和必须为 1。隶属值越高,该像素属于该簇的可能性越大。FCM 聚类是通过最小化方程 (1) 中所示的目标函数获得的。
(1)
其中
- J 是目标函数
- n 是图像 E 中的像素数
- c 是簇的数量
- µ 是来自表格的模糊隶属值
- m 是模糊因子(大于 1 的值)
- pi 是 E 中的第 i 个像素
- vk 是第 k 个簇的质心
- |pi – vk| 是 pi 和 vk 之间的欧几里得距离,由方程 (2) 定义
(2)
第 k 个簇的质心计算使用方程 (3) 完成
(3)
模糊隶属表使用原始方程 (4) 计算
(4)
该算法已扩展用于 RGB 颜色空间中彩色图像的聚类。因此,方程 (2) 中计算 pi 和 vk 值之间欧几里得距离的计算被修改为包含 RGB 颜色,并显示在方程 (5) 中。
(5)
伪代码
如前所述,这是一个迭代过程。伪代码如下:
- 步骤 1:设置簇的数量、模糊参数(大于 1 的常数)和停止条件
- 步骤 2:初始化模糊分区矩阵
- 步骤 3:设置循环计数器 k = 0
- 步骤 4:计算簇质心,计算目标值 J
- 步骤 5:对于每个像素,对于每个簇,计算矩阵中的隶属值
- 步骤 6:如果连续迭代之间 J 的值小于停止条件,则停止;否则,设置 k=k+1 并转到步骤 4
- 步骤 7:去模糊化和分割
Using the Code
GUI 非常直观,但计算量可能非常大。因此,处理是在工作线程中完成的,这使得与 GUI 的交互复杂化。
首先,使用“文件”菜单加载图像。请注意,大图像将花费很长时间!
可以从 GUI 更改的选项是簇的数量、最大迭代次数(这样程序就不会一直运行下去)和精度。如果达到精度,算法将在最大迭代次数之前停止。
单击“Fuzzy C-means Clustering”按钮将启动计算。程序将首先为图像中的每个像素创建一个ClusterPoint
对象。
List<ClusterPoint> points = new List<ClusterPoint>();
for (int row = 0; row < originalImage.Width; ++row)
{
for (int col = 0; col < originalImage.Height; ++col)
{
Color c2 = originalImage.GetPixel(row, col);
points.Add(new ClusterPoint(row, col, c2));
}
}
然后,创建所请求数量的ClusterCentroid
簇对象。
List<ClusterCentroid> centroids = new List<ClusterCentroid>();
//Create random points to use a the cluster centroids
Random random = new Random();
for (int i = 0; i < numClusters; i++)
{
int randomNumber1 = random.Next(sourceImage.Width);
int randomNumber2 = random.Next(sourceImage.Height);
centroids.Add(new ClusterCentroid(randomNumber1, randomNumber2,
filteredImage.GetPixel(randomNumber1, randomNumber2)));
}
簇中心(或质心)在第一次传递时是随机选择的,并且将由算法进行调整。
最后,创建FCM
对象并开始迭代。
FCM alg = new FCM(points, centroids, 2, filteredImage, (int)numericUpDown2.Value);
k++;
alg.J = alg.CalculateObjectiveFunction();
alg.CalculateClusterCentroids();
alg.Step();
double Jnew = alg.CalculateObjectiveFunction();
Console.WriteLine("Run method i={0} accuracy = {1} delta={2}",
k, alg.J, Math.Abs(alg.J - Jnew));
backgroundWorker.ReportProgress((100 * k) / maxIterations, "Iteration " + k);
if (Math.Abs(alg.J - Jnew) < accuracy) break;
进度显示在状态栏上。
迭代完成后,算法将执行去模糊化过程,将像素分配给它具有最高隶属值的簇。对于每个簇,程序将保存一个包含原始图像中属于该簇的像素的分割图像。
例如,对以下测试图像进行 2 个簇的聚类
将产生以下聚类图像
通过使用簇信息和原始图像中的像素,可以提取以下区域
由于此算法计算量非常大,它有“锁定”GUI 并且不刷新状态和工作图像的倾向。因此,我必须使用工作线程。
关注点
这是我的第一篇帖子,也是我的第一个 C# 程序,所以 I'm sure 还有很多改进的空间。但总的来说,I hope you will find this project fun and interesting!
参考文献
- Java 图像处理手册,模糊 C-means 算法,作者:Rafael Santos。
- 带与重力中心的空间距离的改进模糊 C-means 聚类算法,2010 年 IEEE 国际多媒体会议,中国台湾台中,2010 年 12 月 13 日至 12 月 15 日。