Opencv之kmeans图像分割
程序员文章站
2024-03-25 08:09:34
...
int imageSeg_kmeans()
{
string image_path = "D:/vs2019Proj/ConsoleApplication1/timg.jpg";
Mat src_image = imread(image_path);
if (!src_image.data)
{
cout << "could not load image.." << endl;
return -1;
}
//颜色板
vector<Scalar> colorTab = {
{0,0,255},
{0,255,0},
{255,0,0},
{255,255,0},
{0,255,255},
{255,0,255}
};
int width = src_image.cols;
int height = src_image.rows;
int chnes = src_image.channels();
//把彩色图像中的数据点提取出来放入points里面
//points的类型是CV_32F
Mat points(width * height, chnes, CV_32F,Scalar(10));
for (int row = 0; row < height; row++)
{
uchar* ptr = src_image.ptr<uchar>(row);
for (int col = 0; col < width* chnes; col+= chnes)
{
int index = row * width + col/chnes;
float* ptr_points = points.ptr<float>(index);
ptr_points[0] = static_cast<int>(ptr[col]);//B
ptr_points[1] = static_cast<int>(ptr[col+1]);//G
ptr_points[2] = static_cast<int>(ptr[col+2]);//R
}
}
//设置kmeans的参数,执行kmeans
//clusters 表示要把图像分割为几类
int clusters = 2;
//attempts 表示要在图像上尝试几次kmeans计算,因为可能会存在起始点选择不太好的情况,所以要多尝试几次
int attempts = 3;
//flags 表示选取中心点的方法,clusters为几就要选取多少个中心点
int flags = cv::KMEANS_PP_CENTERS;
//centers 记录迭代完成后中心点的位置
Mat centers(clusters, 1, points.type());
//label 记录每一个像素点所属的类别
Mat label;
//critreia kmeans算法的终止条件
//TermCriteria::EPS 迭代算法停止时要达到的精度
//TermCriteria::COUNT 表示最大迭代次数
TermCriteria critreia = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 0.1);
kmeans(points, clusters, label, critreia, attempts, flags, centers);
//处理kmeans的结果,即处理label,并且还原为分割图像
//label数据结构是width*height行,1列,每一行表示一个像素点的类别
Mat result = Mat::zeros(src_image.size(), src_image.type());
for (int row = 0; row < height; row++)
{
uchar* ptr = result.ptr<uchar>(row);
for (int col = 0; col < width*3; col+=3)
{
int index = label.at<int>(row * width + col / 3, 0);
ptr[col] = colorTab[index][0];
ptr[col + 1] = colorTab[index][1];
ptr[col + 2] = colorTab[index][2];
}
}
//输出每一种分割类别的中心点
for (int i = 0; i < centers.rows; i++)
{
int x = centers.at<float>(i, 0);
int y = centers.at<float>(i, 1);
cout << "center " << i << ":" << x << " " << y << endl;
}
imshow("result", result);
imshow("srcimage", src_image);
}