图像分割
基友上的人工智能课上,老师留了基于聚类算法的图像分割作业。正好图像处理课的老师也在讲这部分,所以自己拿来尝试一哈。
问题描述:针对下面这副图片,将其分为两部分:山与河流。
Kmeans
事先确定常数k,常数k意味着最终的聚类类别数。将事先输入的n个数据对象划分为k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。聚类相似度是利用各聚类中对象的均值所获得一个“中心对象”(引力中心)来进行计算的。
算法描述
假设要把样本集分为c个类别,算法描述如下:
(1)适当选择c个类的初始中心;
(2)在第k次迭代中,对任意一个样本,求其到c个中心的距离,将该样本归到距离最短的中心所在的类;
(3)利用均值等方法更新该类的中心值;
(4)对于所有的c个聚类中心,如果利用(2)(3)的迭代法更新后,值保持不变,则迭代结束,否则继续迭代。
该算法的最大优势在于简洁和快速。算法的关键在于初始中心的选择和距离公式。
自己动手实现KMeans
function [ans] = KMeans(k, data)
ans = zeros(size(data,1),1);
initialPoint = randint(k,1,size(data,1));
centerData = []
for i=1:k
centerData = [centerData;data(initialPoint(i,1),:)];
end
while 1
t1 = zeros(size(data,1),1);
t2 = zeros(k,1);
t3 = zeros(k,2);
for i=1:size(t1,1)
for j=1:k
t2(j,1) = CalDistance(data(i,1),centerData(j));
end
[val index] = min(t2);
t1(i,1) = index;
t3(index,1) = t3(index,1) + val;
t3(index,2) = t3(index,2) + 1;
end
for i=1:k
t3(i,1) = t3(i,1) / t3(i,2);
end
centerData = t3(:,1);
ans = t1;
if isequal(t1,ans)
break
end
end
end
实验结果
讨论
实验过程中确实发现了一些问题。比如:有时处理的过程很快,可是右下角的森林部分与河流混在了一起;而有时,分割的效果就很好,较好地区分出山体与河流。上网翻了一些博客、论文,找到了KMeans算法的一些优缺点分析。
缺点:
(1)K值需要初始化,不同的K值得到的处理结果不一样;
(2)对于初始中心点是敏感的,这也就解释了我们处理结果的不唯一性。
(3)特殊值对处理结果有很大的影响
针对上述问题,还有更好的Kmeans ++算法,有时间研究一哈。还有,老师今天讲到了Mean Shift算法,能够自动确定聚类中心点,处理效果很不错。之后有机会尝试一哈。