首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >K-means算法在图像分割中的应用实例

K-means算法在图像分割中的应用实例

作者头像
用户9831583
发布2022-06-16 14:30:44
发布2022-06-16 14:30:44
1.1K0
举报
文章被收录于专栏:码出名企路码出名企路

图片来源于关注者提问,已私发,供参考

原图:

K-means分割后:

附上代码:

代码语言:javascript
复制
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

void Kmeans(Mat& img,Mat& r)
{
//定义图像分割颜色
    Scalar color[]=
    {
        Scalar(0,0,255),
        Scalar(0,255,0),
        Scalar(255,0,0),
        Scalar(0,255,255),
        Scalar(255,0,255)
    };
    
    int w=img.cols;
    int h=img.rows;
    int d=img.channels();

    int count=w*h;
    int cluster_count=2;
    Mat Points(count,d,CV_32F,Scalar(10));

    Mat labels;//输出
    Mat centers(cluster_count,1,Points.type());//存储聚类后的中心点

    int index=0;
    for(int i=0;i<h;i++)
    {
        for(int j=0;j<w;j++)
        {
            index=i*w+j;//每个像素点的索引值,一行一行的遍历
            Vec3b bgr=img.at<Vec3b>(i,j);
            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均值
    TermCriteria criteria=
    TermCriteria(TermCriteria::EPS+TermCriteria::COUNT,10,0.1);
    
    kmeans(Points,cluster_count,labels,criteria,3,KMEANS_PP_CENTERS,centers);
  
        for(int i=0;i<h;i++)
    {
        for(int j=0;j<w;j++)
        {
            index=i*w+j;//每个像素点的索引值,一行一行的遍历
            int label=labels.at<int>(index,0);

            r.at<Vec3b>(i,j)[0]=color[label][0];
            r.at<Vec3b>(i,j)[1]=color[label][1];
            r.at<Vec3b>(i,j)[2]=color[label][2];       
        }
    }
   /最后聚类中心点的坐标
   for(int i=0;i<centers.rows;i++)
   {
       int x=centers.at<float>(i,0);
       int y=centers.at<float>(i,1);

       cout<<"centers: "<<i<<" "<<x<<" "<<y<<" "<<endl;
   }
}
int main(int argc,char* argv[])
{
    Mat img=imread(argv[1],1);
    if(img.empty())
    {
        cout<<"not img"<<endl;
        return -1;
    }

    imshow("img",img);
    waitKey(0);
      
    Mat r=Mat::zeros(img.size(),img.type());
     Kmeans( img, r);
    imshow("result",r);
    waitKey(0);
    return 0;
}

TermCriteria::TermCriteria - 构造函数

代码语言:javascript
复制
TermCriteria::TermCriteria
(
  int type, 
  int maxCount, 
  double epsilon
)

参数说明: type - 终止条件的类型:TermCriteria::COUNT,TermCriteria::EPS或 TermCriteria::COUNT + TermCriteria::EPS maxCount - 要计算的最大迭代次数或元素 epsilon - 迭代算法停止的所需精度或参数更改 criteria - 终止标准(已弃用的CvTermCriteria格式)。

kmeans - 查找聚类的中心,并对聚类周围的输入样本进行分组

代码语言:javascript
复制
 double kmeans
(
  InputArray data, 
  int K, 
  InputOutputArray bestLabels, 
  TermCriteria criteria, 
  int attempts, 
  int flags, 
  OutputArray centers=noArray() 
)

参数说明: data - 用于聚类的数据。需要具有浮点坐标的N维点数组。此数组的示例 可以是:

代码语言:javascript
复制
- Mat points(count, 2, CV_32F);
      - Mat points(count, 1, CV_32FC2);
      - Mat points(1, count, CV_32FC2);
      - std::vector<cv::Point2f> points(sampleCount);

K - 用来分割集合的集群数。 labels - 输入/输出整数数组,用于存储每个样本的聚类索引。 criteria - 算法终止标准,即最大迭代次数和/或所需精度。精度被指定为criteria.epsilon。一旦每个聚类中心在某个迭代上移动的距离小于criteria.epsilon,该算法就会停止。 termcrit - 算法终止标准,即最大迭代次数和/或所需精度。 attempts - 用于指定使用不同的初始标签执行算法的次数的标志。该算法返回产生最佳紧凑性的标签(请参见最后一个功能参数)。 flags - 可以采用以下值的标志    KMEANS_RANDOM_CENTERS - 在每次尝试中选择随机的初始中心。    KMEANS_PP_CENTERS - 使用Arthur和Vassilvitskii进行的kmeans ++中心初始化。    KMEANS_USE_INITIAL_LABELS - 在第一次(可能也是唯一的)尝试期间,请使用用户提供的标签,而不要从初始中心进行计算。对于第二次或更进一步的尝试,请使用随机或半随机中心。使用KMEANS _ * _ CENTERS标志之一来指定确切的方法 .

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-02-09,如有侵权请联系 cloudcommunity@tencent.com 删除
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档