OpenCv-C++-02-KMeans-图像分割

关于KMeans上一篇文章有提到,也用了一些随机点进行数据分类,那么图像呢?图像也是一堆数据,我们只需要把1图像转变为一组数据即可进行数据分类,然后重新显示在图像上,这就是图像分割。
代码部分与上一章文章没多大区别,只需稍作改动即可:

#include<opencv2/opencv.hpp>
#include<iostream>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
	Mat src = imread("F:/test/lena.jpg");
	if (!src.data)
	{
		printf("图片未找到!\n");
		return -1;
	}
	imshow("input image", src);
	int width = src.cols; //图像宽
	int height = src.rows; //图像高
	int channels = src.channels(); //通道数
	Scalar colorTab[] = {    //定义颜色数组
		Scalar(0,0,255),
		Scalar(255,0,255),
		Scalar(0,255,0),
		Scalar(255,0,0),
		Scalar(0,255,255),
	};
	//初始化定义
	int clusterCount = 4;//4分类
	int sampleCount = width * height;//样本点数量
	Mat points(sampleCount, channels, CV_32F, Scalar(10));
	Mat labels;
	Mat centers(clusterCount, 1, points.type());

	//RGB转换到样本数据
	int index = 0;
	for (int row = 0; row < src.rows; row++)
	{
		for (int col = 0; col < src.cols; col++)
		{
			index = row * width + col;
			Vec3b bgr = src.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]);
		}
	}
	//运行KMeans
	TermCriteria cirteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 0.1);
	kmeans(points, clusterCount, labels, cirteria, 3, KMEANS_PP_CENTERS, centers);
	
	//显示图像分割结果

	Mat result = Mat::zeros(src.size(), src.type());
	for (int row = 0; row < src.rows; row++)
	{
		for (int col = 0; col < src.cols; 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];
		}
	}

	
	imshow("result", result);
	waitKey(0);
	return 0;
}



运行结果:
在这里插入图片描述
分割后的结果:
在这里插入图片描述

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值