Kmeans——图像分割
程序员文章站
2022-03-16 17:44:35
...
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat SrcImage = imread("C:/Users/zhang/Desktop/1.png");
imshow("原图", SrcImage);
int width = SrcImage.cols;//图像宽
int height = SrcImage.rows;//图像高
int dims = SrcImage.channels();//图像通道数
//kmeans的输入数据:对于图像而言,每一个像素点都是一个数据,
int sampleCount = width * height;//图像数据点的个数
int clusterCount = 3;//分类数目
Mat points(sampleCount, dims, CV_32F, Scalar(10));//输入数据,与原图像有着相同通道
Mat labels;//输出数据,为各个数据点最终的分类索引
Mat centers(clusterCount, 1, points.type());//每个分类的中心点
Scalar colorbar[] =//每个分类的颜色
{
Scalar(0,0,255),
Scalar(203,192,255),
Scalar(255,0,255),
Scalar(0,255,0)
};
////RGB数据转换到样本数据
int index = 0;
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
index = row * width + col;//每个像素点
//把RGB图像的三个通道的各个像素点值分别赋给points的三个通道
Vec3b rgb = SrcImage.at<Vec3b>(row, col);
points.at<float>(index, 0) = static_cast<int>(rgb[0]);
points.at<float>(index, 1) = static_cast<int>(rgb[1]);
points.at<float>(index, 2) = static_cast<int>(rgb[2]);
}
}
TermCriteria criteria = TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0);
//10代表最大循环数目,1.0代表阈值
kmeans(points, clusterCount, labels, criteria, 3, KMEANS_PP_CENTERS, centers);
//第一个参数:表示输入的数据集合,可以一维或者多维数据,类型是Mat类型,
//比如Mat points(count, 2, CV_32F)表示数据集合是二维,浮点数数据集;
//第二个参数:表示分类的数目,K = 2时即表示二分类;
//第三个参数:表示计算之后各个数据点的最终的分类索引,是一个INT类型的Mat对象,类型和长宽与原图像一致
//第四个参数:表示算法终止的条件,达到最大循环数目或者指定的精度阈值算法就停止继续分类迭代计算;
//第五个参数:表示为了获得最佳的分类效果,算法要不同的初始分类尝试次数;
//第六个参数:表示表示选择初始中心点选择方法用哪一种方法:
//KMEANSRANDOMCENTERS 表示随机选择中心点
//KMEANSPPCENTERS 基于中心化算法选择
//KMEANSUSEINITIAL_LABELS第一次分类中心点用输入的中心点;
//第七个参数:表示输出的每个分类的中心点数据;
//显示图像分割结果//
Mat result = Mat::zeros(SrcImage.size(), SrcImage.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] = colorbar[label][0];
result.at<Vec3b>(row, col)[1] = colorbar[label][1];
result.at<Vec3b>(row, col)[2] = colorbar[label][2];
}
}
imshow("聚类结果", result);
imwrite("C:/Users/zhang/Desktop/xiannv5.png", result);
//centers按行保存着每个分类的终点坐标,每一行有一个坐标
for (int i = 0; i<centers.rows; i++)
{
int x = centers.at<float>(i, 0);
int y = centers.at<float>(i, 1);
cout << "x="<<x << "," << "y=" << y << endl;
}
waitKey(0);
return 0;
}
上一篇: tiny-yoloV3消化之旅(前言)
下一篇: GMM图像分割