您的位置:首页 > 运维架构

k-means提取图像主色(调用opencv-kmeans)

2017-07-23 14:51 459 查看
一、Kmeans简介

k-means提取图像主色(手写)

二、opencv-kmeans主色提取

//输入彩色图像 k-means获取主色(颜色中心及比例)
void DCD(Mat& src)
{
if(!src.data)
{
return;
}

//分割通道
vector<Mat> bgr;
split(src, bgr);

int nRows = src.rows;
int nCols = src.cols;

//设定类数
int nClusters = 20;

//输入样本 按行存储
Mat samples(nRows*nCols, 1, CV_32FC3/*, Scalar(0)*/);

for(int i = 0; i < nRows; ++i)
{
for(int j = 0; j < nCols; ++j)
{
for(int iChanel = 0; iChanel < 3; ++iChanel)
{
samples.at<Vec3f>(i*nCols + j)[iChanel] = bgr[iChanel].at<uchar>(i, j);
}
}
}

TermCriteria  criteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 1000, FLT_EPSILON);
Mat centers(nClusters,1, CV_32FC3);
Mat labels(nRows*nCols, 1, CV_8UC1);

//进行聚类
kmeans(samples, nClusters, labels, criteria, 1, KMEANS_PP_CENTERS, centers);

//分割后的颜色
Mat res(nRows, nCols, CV_8UC3);

//每个类别的颜色中心
Vec3f *p = new Vec3f[nClusters];

cout<< "颜色聚类中心"<< endl;
for(int i = 0; i < nClusters; ++i)
{
p[i] = centers.ptr<Vec3f>(i)[0];
cout<<p[i].val[0]<< " "<< p[i].val[1]<<" "<< p[i].val[2]<< endl;
}

int dis = nRows/nClusters;
for(int i = 0; i < nClusters; ++i)
{
for(int r = i*dis; r < (i + 1)*dis; ++r)
{
for(int c = 0; c < nCols; ++c)
{
*res.ptr<Vec3b>(r, c) = p[i];
}
}
}

imshow("res", src);
imshow("color", res);

//每个类别所占的比例
float* precent = new float[nClusters];
memset(precent, 0, sizeof(p)*nClusters);

for(int n = 0; n < nRows*nCols; ++n)
{
int r = n/nCols;
int c = n%nCols;

*res.ptr<Vec3b>(r, c) = p[*labels.ptr<uchar>(n, 0)];
precent[*labels.ptr<uchar>(n, 0)] ++;
}

cout<< "相应颜色比例"<< endl;
for(int i = 0; i < nClusters; ++i)
{
precent[i]/=(nRows*nCols);
cout<<precent[i]<<" ";
}
cout<<endl;
waitKey(0);
}
三、程序结果





内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: