目录
1.概述
1.1K-means方法
?1.2基本流程
?2.K-means图像分割
2.1图像分割
?2.2K-means算法原理
2.3实验案例
1.概述
图像分割主要有四种方法:
K-means和GMM是基于聚类的方式进行图像分割,分水岭方法是基于图像的拓扑结构进行图像分割的,还有GrabCut是基于交互方式的图像分割与抠图的方法。
1.1K-means方法
K-means是无监督学习方法,对于分类问题需要输入分类数目,初始化中心位置。对于硬分类问题,以距离度量。
主要用处有两个:
?1.2基本流程
?2.K-means图像分割
2.1图像分割
????????图像分割是图像处理中的一种方法,图像分割是指将一幅图像分解成若干互不相交区域的集合,其实质可以看成是一种像素的聚类过程。通常使用到的图像分割的方法可以分为:
基于聚类算法的图像分割属于基于区域的技术????????
?2.2K-means算法原理
????????K-Means算法是基于距离相似性的聚类算法,通过比较样本之间的相似性,将形式的样本划分到同一个类别中,K-Means算法的基本过程为:
- 初始化常数 ,随机初始化k个聚类中心
- 重复计算以下过程,直到聚类中心不再改变
? ? ? ?(1) 计算每个样本与每个聚类中心之间的相似度,将样本划分到最相似的类别中 ? ? ? ? (2)计算划分到每个类别中的所有样本特征的均值,并将该均值作为每个类新的聚类中心 输出最终的聚类中心以及每个样本所属的类别 ????????在K-Means算法中,需要随机初始化k个聚类中心,而K-Means算法对初始聚类中心的选取较为敏感,若选择的聚类中心不好,则得到的聚类结果会非常差,因此,对K-Means算法提出了很多的改进的方法,如K-Means++算法,在K-Means++算法中,希望初始化的k个聚类中心之间的距离尽可能的大,其具体过程为:
- 在数据集中随机选择一个样本点作为第一个初始化的聚类中心
- 选择出其余的聚类中心:
????????计算样本中的每一个样本点与已经初始化的聚类中心之间的距离,并选择其中最短的距离 ????????以概率选择距离最大的样本作为新的聚类中心,重复上述过程,直到 个聚类中心都被确定 ????????对k个初始化的聚类中心,利用K-Means算法计算最终的聚类中心。
2.3实验案例
Mat MyApi::k_meansCluster(Mat& image)
{
Scalar colorTab[] =
{
Scalar(0,0,255),
Scalar(0,255,0),
Scalar(255,0,0),
Scalar(0,255,255),
Scalar(255,0,255)
};
int width = image.cols;
int height = image.rows;
int dims = image.channels();
//初始化定义
int sampleCount = width * height;//有多少像素点就有多少sample
int clusterCount = 2;
Mat points(sampleCount, dims, CV_32F, Scalar(10));
Mat labels;
Mat centers(clusterCount,1,points.type());//有多少clusterCount就有多少centers
//RGB数据转换到样本数据
int index = 0;
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
index = row * width + col;
Vec3b bgr = image.at<Vec3b>(row, col);
points.at<float>(index, 0) = static_cast<int>(bgr[0]);
points.at<float>(index, 1) = static_cast<int>(bgr[1]);
points.at<float>(index, 2) = static_cast<int>(bgr[2]);
}
}
//运行K-means
TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 0.1);
kmeans(points, clusterCount, labels, criteria, 3, KMEANS_PP_CENTERS, centers);
//显示图像分割结果
Mat result = Mat::zeros(image.size(), image.type());
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
index = row * width + col;
int label = labels.at<int>(index, 0);
result.at<Vec3b>(row, col)[0] = colorTab[label][0];
result.at<Vec3b>(row, col)[1] = colorTab[label][1];
result.at<Vec3b>(row, col)[2] = colorTab[label][2];
}
}
return result;
}
?左边为原图,右边为分为两类的图
|