注意Mat作为kmeans的参数的含义。

扩展:高维向量的聚类。

一、像素聚类

#include "opencv2/highgui.hpp"
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream> using namespace cv;
using namespace std; // static void help()
// {
// cout << "\nThis program demonstrates kmeans clustering.\n"
// "It generates an image with random points, then assigns a random number of cluster\n"
// "centers and uses kmeans to move those cluster centers to their representitive location\n"
// "Call\n"
// "./kmeans\n" << endl;
// } int main( int /*argc*/, char** /*argv*/ )
{
const int MAX_CLUSTERS = 5;
Scalar colorTab[] =
{
Scalar(0, 0, 255),
Scalar(0,255,0),
Scalar(255,100,100),
Scalar(255,0,255),
Scalar(0,255,255)
}; Mat img(500, 500, CV_8UC3);
RNG rng(12345); for(;;)
{
//Jeff --> The second parameter is non-inclusive boundary.
int k, clusterCount = rng.uniform(2, MAX_CLUSTERS+1);
int i, sampleCount = rng.uniform(2, 1001);
// int i, sampleCount = 10; Mat points(sampleCount, 1, CV_32FC2), labels;

     //一般来说,没有必要。sampleCount都远大于ClusterCount。
// clusterCount = MIN(clusterCount, sampleCount);
Mat centers; /* Jeff --> generate random sample from multigaussian distribution 以某一个中心点,二维高斯分布分配点;主要是一个数学技巧。*/
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);
rng.fill(pointChunk, RNG::NORMAL, Scalar(center.x, center.y), Scalar(img.cols*0.05, img.rows*0.05));
cout << pointChunk << endl;
}

//洗牌
randShuffle(points, 1, &rng); std::cout << points << std::endl; //Jeff --> Mat is vector here, including a list of points.
// labels: index of cluster for each points.
kmeans(points, clusterCount, labels,
TermCriteria( TermCriteria::EPS+TermCriteria::COUNT, 10, 1.0),
3, KMEANS_PP_CENTERS, centers); //Jeff --> Draw point (tiny circle) with its color on black background.
img = Scalar::all(0); // Step One: show sample points.
for( i = 0; i < sampleCount; i++ )
{
int clusterIdx = labels.at<int>(i);
Point ipt = points.at<Point2f>(i);
circle( img, ipt, 2, colorTab[clusterIdx], FILLED, LINE_AA );
} // Step Two: show central points.
for( i = 0; i < clusterCount; i++ )
{
std::cout << centers.at<Point2f>(i) << std::endl;
} imshow("clusters", img); char key = (char)waitKey();
if( key == 27 || key == 'q' || key == 'Q' ) // 'ESC'
break;
} return 0;
}

二、图像的kmeans降维处理

g++ -std=c++11 -pthread  -fpermissive  main.cpp -o output `pkg-config --cflags --libs opencv` -ldl

From: http://seiya-kumada.blogspot.com/2013/03/k-means-clustering.html【非常好】

#include <opencv2/highgui.hpp>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream> using namespace cv;
using namespace std; void show_result(const cv::Mat& labels, const cv::Mat& centers, int height, int width)
{
std::cout << "===\n";
std::cout << "labels: " << labels.rows << " " << labels.cols << std::endl;
std::cout << "centers: " << centers.rows << " " << centers.cols << std::endl;
assert(labels.type() == CV_32SC1);
assert(centers.type() == CV_32FC1); cv::Mat rgb_image(height, width, CV_8UC3);
cv::MatIterator_<cv::Vec3b> rgb_first = rgb_image.begin<cv::Vec3b>();
cv::MatIterator_<cv::Vec3b> rgb_last = rgb_image.end<cv::Vec3b>();
cv::MatConstIterator_<int> label_first = labels.begin<int>(); cv::Mat centers_u8;
centers.convertTo(centers_u8, CV_8UC1, 255.0);
cv::Mat centers_u8c3 = centers_u8.reshape(); while ( rgb_first != rgb_last ) {
const cv::Vec3b& rgb = centers_u8c3.ptr<cv::Vec3b>(*label_first)[];
*rgb_first = rgb;
++rgb_first;
++label_first;
}
cv::imshow("tmp", rgb_image);
cv::imwrite("./result.jpg", rgb_image);
cv::waitKey();
} int main(int argc, const char * argv[])
{
cv::Mat image = cv::imread("./d1.jpg");
if ( image.empty() ) {
std::cout << "unable to load an input image\n";
return ;
} std::cout << "image: " << image.rows << ", " << image.cols << std::endl;
assert(image.type() == CV_8UC3);
cv::imshow("image", image); cv::Mat reshaped_image = image.reshape(, image.cols * image.rows);
std::cout << "reshaped image: " << reshaped_image.rows << ", " << reshaped_image.cols << std::endl;
assert(reshaped_image.type() == CV_8UC1);
//check0(image, reshaped_image); cv::Mat reshaped_image32f;
reshaped_image.convertTo(reshaped_image32f, CV_32FC1, 1.0 / 255.0);
std::cout << "reshaped image 32f: " << reshaped_image32f.rows << ", " << reshaped_image32f.cols << std::endl;
assert(reshaped_image32f.type() == CV_32FC1); cv::Mat labels;
int cluster_number = ;
cv::TermCriteria criteria {cv::TermCriteria::COUNT, , };
cv::Mat centers;
cv::kmeans(reshaped_image32f, cluster_number, labels, criteria, , cv::KMEANS_RANDOM_CENTERS, centers); show_result(labels, centers, image.rows, image.cols); return ;
}

三、ROI的kmeans支持

原文:https://blog.csdn.net/fengbingchun/article/details/79395298

double kmeans( InputArray data, int K, InputOutputArray bestLabels, 
TermCriteria criteria,
int attempts, int flags, OutputArray centers = noArray() );

接口的声明在include/opencv2/core.hpp文件中,实现在modules/core/src/kmeans.cpp文件中

(1)、data:为cv::Mat类型,每行代表一个样本,即特征,即mat.cols=特征长度,mat.rows=样本数,数据类型仅支持float;

(2)、K:指定聚类时划分为几类;

(3)、bestLabels:为cv::Mat类型,是一个长度为(样本数,1)的矩阵,即mat.cols=1,mat.rows=样本数;为K-Means算法的结果输出,指定每一个样本聚类到哪一个label中;

(4)、criteria:TermCriteria类,算法进行迭代时终止的条件,可以指定最大迭代次数,也可以指定预期的精度,也可以这两种同时指定;

(5)、attempts:指定K-Means算法执行的次数,每次算法执行的结果是不一样的,选择最好的那次结果输出;

(6)、flags:初始化均值点的方法,目前支持三种:KMEANS_RANDOM_CENTERS、KMEANS_PP_CENTERS、KMEANS_USE_INITIAL_LABELS;

(7)、centers:为cv::Mat类型,输出最终的均值点,mat.cols=特征长度,mat.rols=K.

    // Color dimension reduction
Mat processTagByKmean(Mat3b const tag, Option option)
{
int K = option.knnClusterNum; // 0. Prepare arguments for kmeans.
cv::Mat reshaped_tag = tag.reshape(, tag.cols * tag.rows); cv::Mat reshaped_tag32f, labels, centers;
reshaped_tag.convertTo(reshaped_tag32f, CV_32FC1, 1.0 / 255.0);
// ------------------------------------------------------------------
// 1. do kmeans
cv::kmeans(reshaped_tag32f, K, labels,
TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, , 1.0),
, KMEANS_PP_CENTERS, centers);
// ------------------------------------------------------------------
// 2. convert to rgb mat
cv::Mat rgb_tag(tag.rows, tag.cols, CV_8UC3);
cv::MatIterator_<cv::Vec3b> rgb_first = rgb_tag.begin<cv::Vec3b>();
cv::MatIterator_<cv::Vec3b> rgb_last = rgb_tag.end<cv::Vec3b>();
cv::MatConstIterator_<int> label_first = labels.begin<int>(); cv::Mat centers_u8;
centers.convertTo(centers_u8, CV_8UC1, 255.0);
cv::Mat centers_u8c3 = centers_u8.reshape(); while (rgb_first != rgb_last)
{
const cv::Vec3b &rgb = centers_u8c3.ptr<cv::Vec3b>(*label_first)[];
*rgb_first = rgb;
++rgb_first;
++label_first;
} return rgb_tag;
}

原文:https://blog.csdn.net/qq_22764813/article/details/52135686

如果Mat类型数据的深度和通道数不满足上面的要求,则需要使用convertTo()函数和cvtColor()函数来进行转换。
convertTo()函数负责转换数据类型不同的Mat,即可以将类似float型的Mat转换到imwrite()函数能够接受的类型。
cvtColor()函数是负责转换不同通道的Mat,因为该函数的第4个参数就可以设置目的Mat数据的通道数(只是我们一般没有用到它,一般情况下这个函数是用来进行色彩空间转换的)。
另外也可以不用imwrite()函数来存图片数据,可以直接用通用的XML IO接口函数将数据存在XML或者YXML中。

[OpenCV] Samples 03: cout_mat的更多相关文章

  1. [OpenCV] Samples 03: kmeans

    注意Mat作为kmeans的参数的含义. 扩展:高维向量的聚类. 一.像素聚类 #include "opencv2/highgui.hpp" #include "open ...

  2. [OpenCV] Samples 10: imagelist_creator

    yaml写法的简单例子.将 $ ./ 1 2 3 4 5 命令的参数(代表图片地址)写入yaml中. 写yaml文件. 参考:[OpenCV] Samples 06: [ML] logistic re ...

  3. [OpenCV] Samples 16: Decompose and Analyse RGB channels

    物体的颜色特征决定了灰度处理不是万能,对RGB分别处理具有相当的意义. #include <iostream> #include <stdio.h> #include &quo ...

  4. [OpenCV] Samples 06: [ML] logistic regression

    logistic regression,这个算法只能解决简单的线性二分类,在众多的机器学习分类算法中并不出众,但它能被改进为多分类,并换了另外一个名字softmax, 这可是深度学习中响当当的分类算法 ...

  5. [OpenCV] Samples 06: logistic regression

    logistic regression,这个算法只能解决简单的线性二分类,在众多的机器学习分类算法中并不出众,但它能被改进为多分类,并换了另外一个名字softmax, 这可是深度学习中响当当的分类算法 ...

  6. [OpenCV] Samples 13: opencv_version

    cv::CommandLineParser的使用. I suppose CommandLineParser::has("something") should be true whe ...

  7. [OpenCV] Samples 12: laplace

    先模糊再laplace,也可以替换为sobel等. 变换效果后录成视频,挺好玩. #include "opencv2/videoio/videoio.hpp" #include & ...

  8. [OpenCV] Samples 05: convexhull

    得到了复杂轮廓往往不适合特征的检测,这里再介绍一个点集凸包络的提取函数convexHull,输入参数就可以是contours组中的一个轮廓,返回外凸包络的点集 ---- 如此就能去掉凹进去的边. 对于 ...

  9. [OpenCV] Samples 02: [ML] kmeans

    注意Mat作为kmeans的参数的含义. 扩展:高维向量的聚类. #include "opencv2/highgui.hpp" #include "opencv2/cor ...

随机推荐

  1. [XAF] How to improve the application's performance

    [自己的解决方案]数据量大时,可显著提升用户使用体验! 1.Root ListView 参考官方的E1554 点击导航菜单后首先跳出查询条件设置窗体进行设置 可设置查询方案或查询方案的查询条件,排序字 ...

  2. CSS浮动(float,clear)通俗讲解

    首先要知道,div是块级元素,在页面中独占一行,自上而下排列,也就是传说中的流.如下图: 可以看出,即使div1的宽度很小,页面中一行可以容下div1和div2,div2也不会排在div1后边,因为d ...

  3. android adb install

    环境:centos6.8 需要安装 root@localhost ~]# yum install libstdc++.so.6 1.下载安装包; http://pan.baidu.com/s/1skg ...

  4. IEnumerable<IEnumerable<string>>结构解析通用解决方案(支持指定属性顺序)

    一.前言 类似如下字符串 "ID", "NameValue", "CodeValue", "ExchangeTypeValue&q ...

  5. Oracle中的Temporary tablespace的作用

    临时表空间主要用途是在数据库进行排序运算[如创建索引.order by及group by.distinct.union/intersect/minus/.sort-merge及join.analyze ...

  6. 【重磅推荐】腾讯Bugly2015年移动应用质量大数据报告

    2015年,随着移动智能设备的普及,移动端用户的增速明显放缓:相比之下,由于云服务.众筹平台.推广平台等基础设施和服务的不断改善,极大降低了创业的门槛,越来越多人投身于移动应用的创新创业中. 想让用户 ...

  7. 全面理解Javascript闭包和闭包的几种写法及用途

    好久没有写博客了,过了一个十一长假都变懒了,今天总算是恢复状态了.好了,进入正题,今天来说一说javascript里面的闭包吧!本篇博客主要讲一些实用的东西,主要将闭包的写法.用法和用途.  一.什么 ...

  8. Linux Shell变量

    200 ? "200px" : this.width)!important;} --> 介绍 变量是shell脚本中必不可少的组成部分,在脚本中使用变量不需要提前声明.在ba ...

  9. 如何基于纯GDI实现alpha通道的矢量和文字绘制

    今天有人在QQ群里问GDI能不能支持带alpha通道的线条绘制? 大家的答案当然是否定的,很多人推荐用GDI+. 一个基本的图形引擎要包括几个方面的支持:位图绘制,文字绘制,矢量绘制(如矩形,线条). ...

  10. 移动APP的自动化测试

    开发移动应用,最耗时耗力的就是手动测试APP的每个功能点或修复bug.有人就会提议App的业务逻辑可以使用nUnit或xUnit测试单元来辅助完成.那用户界面要如何测试?众所周知,移动设备多种多样,数 ...