opencv kmeans 图像分割

利用kmeans算法,将彩色图像的像素点作为样本,rgb值作为样本的属性,
对图像所有的像素点进行分类,从而实现对图像中目标的分割。

c++代码(openCV 2.4.11)

Scalar colorTab[] = {
    Scalar(0, 0, 0),
    Scalar(255, 255, 255),
};
void color_cluster(const Mat& origin_img_rgb) {
    //  1、将图像按像素点转化为样本矩阵samples
    Mat samples = Mat(origin_img_rgb.size().width*origin_img_rgb.size().height, 1, CV_32FC3);
    int k = 0;
    for (int i = 0; i < origin_img_rgb.rows; i++) {
        for (int j = 0; j < origin_img_rgb.cols; j++) {
            samples.at<cv::Vec3f>(k, 0)[0] = origin_img_rgb.at<cv::Vec3b>(i, j)[0];
            samples.at<cv::Vec3f>(k, 0)[1] = origin_img_rgb.at<cv::Vec3b>(i, j)[1];
            samples.at<cv::Vec3f>(k, 0)[2] = origin_img_rgb.at<cv::Vec3b>(i, j)[2];
            ++k;
        }
    }

    //  2、聚类
    Mat labels;
    Mat centers;
    int nCuster = 2;  //聚类类别数
    
    // samples      输入样本浮点矩阵
    // nCuster      给定聚类类别数量
    // labels       每个样本对应的类别标识
    // TermCriteria 指定聚类的最大迭代次数或精度
    kmeans(samples, nCuster, labels, TermCriteria(CV_TERMCRIT_ITER, 10, 1.0), 3, KMEANS_RANDOM_CENTERS, centers);
    
    //  3、将聚类结果转换为图像显示出来
    k = 0;
    Mat img(origin_img_rgb.size(), CV_8UC3);
    for (int i = 0; i < origin_img_rgb.rows; i++) {
        for (int j = 0; j < origin_img_rgb.cols; j++) {
            int clusterIdx = labels.at<int>(k++, 0);
            circle(img, {j,i}, 2, colorTab[clusterIdx], CV_FILLED, CV_AA);
        }
    }
    imshow("originimg", origin_img_rgb);
    imshow("clusters", img);
    char key = (char)waitKey();
    if (key == 27 || key == 'q' || key == 'Q') {return ;}
}

效果:

posted @ 2016-04-22 07:44  clq.lib  阅读(894)  评论(0编辑  收藏  举报