• OpenCV学习(22) opencv中使用kmeans算法


    kmeans算法的原理参考:http://www.cnblogs.com/mikewolf2002/p/3368118.html

    下面学习一下opencv中kmeans函数的使用。

         首先我们通过OpenCV中的随机数产生器RNG,生成一些均匀分布的随机点,这些点的位置对应一副图像中的像素位置,然后使用kmeans算法对这些随机点进行分类,并计算出分类簇的中心点。

         随机产生的簇的数量是2到5之间的值,采样点的数量范围是1-1000,一维矩阵centers存放kmeans算法结束后,各个簇的中心位置。

         

    //簇的数量
    int k, clusterCount = rng.uniform(2, MAX_CLUSTERS+1);
    //采样点的数量
    int i, sampleCount = rng.uniform(1, 1001);
    Mat points(sampleCount, 1, CV_32FC2), labels;

    clusterCount = MIN(clusterCount, sampleCount);
    //中心点矩阵
    Mat centers(clusterCount, 1, points.type());

    printf("clusterCount=%d, sampleCount=%d ", clusterCount, sampleCount);
    //产生多高斯部分的随机采样点
    for( k = 0; k < clusterCount; k++ )
        {
        Point center;
        center.x = rng.uniform(0, img.cols);
        center.y = rng.uniform(0, img.rows);
        Mat pointChunk = points.rowRange(k*sampleCount/clusterCount,
            k == clusterCount - 1 ? sampleCount :
            (k+1)*sampleCount/clusterCount);
        printf("rows start=%d rows end=%d ", k*sampleCount/clusterCount, k == clusterCount - 1 ? sampleCount :
            (k+1)*sampleCount/clusterCount);

    注意rng.fill函数,会以center点为中心,产生高斯分布的随机点(位置点),并把位置点保存在矩阵pointChunk中。
        //第三个参数中心,第四个参数偏移
        rng.fill(pointChunk, CV_RAND_NORMAL, Scalar(center.x, center.y), Scalar(img.cols*0.05, img.rows*0.05));
        }

    //打乱points中值,第二个参数表示随机交换元素的数量的缩放因子,总的交换次数dst.rows*dst.cols*iterFactor,第三个参数是个随机发生器,决定选那两个元素交换

    randShuffle(points, 1, &rng);

          kmeans函数中points为输入矩阵,其中存储的是采样点,labels也是一个一维矩阵,它的size和points一样,里面存储的是每个采样点执行kmeans算法后属于属于那一个簇,值为0到clusterCount-1,centers中存放的是kmeans算法结束后每个簇的中心位置。

          flags(第7个参数)为KMEANS_PP_CENTERS 表示使用 kmeans++ center initialization by Arthur and Vassilvitskii [Arthur2007]算法决定簇的初始中心,否则就是采用随机值的方法决定初始中心

         如果flags是CV_KMEANS_USE_INITIAL_LABELS,则需要初始化labels,就是初始指定点的分类。

         最后我们在图像中画出每个位置点对应的像素,中心位置用蓝色的圆圈表示。

    //labels中放的是执行kmeans算法后sample中簇的索引
    kmeans(points, clusterCount, labels,
        TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0),
        3, KMEANS_PP_CENTERS, centers);

    img = Scalar::all(0);

    for( i = 0; i < sampleCount; i++ )
        {
        int clusterIdx = labels.at<int>(i);
        Point ipt = points.at<Point2f>(i);
        circle( img, ipt, 2, colorTab[clusterIdx], CV_FILLED, CV_AA );
        }

    cout<<"Center: "<<centers<<endl;

    //用蓝色画出每个聚类的中心
    //有bug,不让我直接用centers.at<Point2f>(i);,会异常

    for( i = 0; i < clusterCount; i++ )
        {
        Point ipt = Point(centers.at<float>(i*2), centers.at<float>(i*2+1));
        circle( img, ipt, 5, Scalar(255,0,0),CV_FILLED, CV_AA );

        }
    imshow("clusters", img);

    下面图像是5个簇的kmeans聚类结果。

    image

    源代码参考工程:FirstOpenCV15

  • 相关阅读:
    网站SEO优化问答精选
    用eclipse怎样将本地的项目打成jar包上传到maven仓库
    查询linux机器的公网ip
    Srping mvc mabatis 报错 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
    使用SecureCRT的SFTP在WINDOWS与LINUX之间传输文件(转载)
    苹果手机如何减少后台流量
    《图解CSS3——第4章 CSS3背景-2》
    《图解CSS3——第4章 CSS3背景-1》
    《图解CSS3——第3章 CSS3边框-4》
    《图解CSS3——第3章 CSS3边框-3》
  • 原文地址:https://www.cnblogs.com/mikewolf2002/p/3372846.html
Copyright © 2020-2023  润新知