opencv2 kmeans算法 应用
2015-04-13 17:18
375 查看
K-Means算法原理:百度或谷歌之。。。有一个简单的例子:https://www.youtube.com/watch?v=zHbxbb2ye3Eopencv:kmeans函数:Finds centers of clusters and groups input samples around the clusters.
C++函数原型:
double kmeans(InputArray samples, int clusterCount, InputOutputArray labels, TermCriteria criteria,
int attempts, int flags, OutputArray centers=noArray() )
Returns
The function returns the compactness of the final clustering. What is compactness? It's a measure of how good the labeling was done. The smaller the better.When attempts is 1, the value returned is the compactness of the only iteration that happened. Ifattempts is more than 1, the final labeling returned is the one with the least compactness.来源: <http://www.aishack.in/tutorials/kmeans-clustering-in-opencv/>Parameters:
samples – Floating-point matrix of input samples, one row per sample. //输入矩阵
clusterCount – Number of clusters to split the set by. //自定义的聚类中心数目
labels – Input/output integer array that stores the cluster indices for every sample. //输入或输出的整数数组,用于存储每一个sample的聚类目录(索引)
criteria – The algorithm termination criteria, that is, the maximum number of iterations
and/or the desired accuracy. The accuracy is specified as criteria.epsilon. As soon as
each of the cluster centers moves by less than criteria.epsilon on some iteration, the
algorithm stops. //标准,具体见TermCriteria
attempts – Flag to specify the number of times the algorithm is executed using different
initial labelings. The algorithm returns the labels that yield the best compactness (see the
last function parameter).
flags – Flag that can take the following values:
– KMEANS_RANDOM_CENTERS Select random initial centers in each attempt.
– KMEANS_PP_CENTERS Use kmeans++ center initialization by Arthur and Vassilvitskii
[Arthur2007].
– KMEANS_USE_INITIAL_LABELS During the first (and possibly the only) attempt,
use the user-supplied labels instead of computing them from the initial centers. For
the second and further attempts, use the random or semi-random centers. Use one of
KMEANS_*_CENTERS flag to specify the exact method.
centers – Output matrix of the cluster centers, one row per each cluster center. //输出的聚类中心示例:
void getDomainColor(cv::Mat image,int clusterNum) //输入原图,以及设定的聚类数目
{
// cvtColor(image,image,CV_RGB2Lab); //转化成Lab
//cvtColor(image,image,CV_RGB2YUV);
//将image复制到samples,3通道的Mat转成一通道的,每一行是颜色的3个值
Mat samples(image.rows * image.cols, 3, CV_32F);
for( int y = 0; y < image.rows; y++ )
for( int x = 0; x < image.cols; x++ )
for( int z = 0; z < 3; z++)
samples.at<float>(y + x*image.rows, z) = image.at<Vec3b>(y,x)[z];
Mat labels; //索引
int attempts = 5; //是否合适?
Mat centers; //中心
Mat centerColor(1,clusterNum,image.type()); //存储每一聚类的颜色
Mat percent;
percent=cv::Mat::zeros(1,clusterNum,CV_32F); //每一聚类占的比例
double compactness=cv::kmeans(samples, clusterNum, labels, TermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS, 0.0001, 10000),
attempts, KMEANS_PP_CENTERS, centers );
cout<<"attempts:"<<attempts<<endl;
cout<<"compactness"<<compactness<<endl;
for(int i=0;i<clusterNum;i++)
{
for(int j=0;j<3;j++)
{
centerColor.at<Vec3b>(0,i)[j]=centers.at<float>(i,j);
}
}
// cvtColor(centerColor,centerColor,CV_Lab2RGB);
Mat new_image( image.size(), image.type() ); //将原图与聚类中心的映射(根据labels)
for( int y = 0; y < image.rows; y++ )
for( int x = 0; x < image.cols; x++ )
{
int cluster_idx = labels.at<int>(y + x*image.rows,0);
percent.at<float>(0,labels.at<int>(y + x*image.rows,0))++; //统计
new_image.at<Vec3b>(y,x)[0] = centers.at<float>(cluster_idx, 0);
new_image.at<Vec3b>(y,x)[1] = centers.at<float>(cluster_idx, 1);
new_image.at<Vec3b>(y,x)[2] = centers.at<float>(cluster_idx, 2);
}
percent/=image.total(); //求比例
// cvtColor(new_image,new_image,CV_Lab2RGB);
//保存矩阵
cv::FileStorage fs;
fs.open("D:\\a.txt", cv::FileStorage::WRITE);
fs << "centerColor" << centerColor;
fs.release();
cv::FileStorage fs1;
fs1.open("D:\\b.txt", cv::FileStorage::WRITE);
fs1 << "center" << centers;
fs1.release();
cv::FileStorage fs2;
fs2.open("D:\\c.txt", cv::FileStorage::WRITE);
fs2 << "labels" << labels;
fs2.release();
cv::FileStorage fs3;
fs3.open("D:\\d.txt", cv::FileStorage::WRITE);
fs3 << "percent" << percent;
fs3.release();
cv::imshow("new_image",new_image);
}分析centers、centerColor、labels与percent的内容:因为kmeans是按行作为向量输入的,所以聚类数目为8时,输出的centers是8*3的矩阵,列表示BGR的值,将其转换成1*8的三通道矩阵centerColor,即可得到该图像的主色向量。labels用于标记输入的sample中,每一行(即每一像素)属于的聚类中心种类percent表示每一类所占的比例,将颜色与空间分布相结合attempts取值对聚类的影响:原图:(720*480)attempts=1 调节对比度:(调节对比度对于聚类无明显影响效果,且光照影响不能去除)(左图为原图)Kmeans后的用途:1.主色,用于图像检索,详见文献《基于主色选择的CBIR检索》(万方或知网里有);2.图像分割:参考http://qtandopencv.blogspot.com/2013/10/opencv-and-color-quantization-01-kmeans.html
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
int main()
{
cv::Mat src = cv::imread("D:\\t.jpg");
if(src.empty()){
std::cerr<<"can't read the image"<<std::endl;
return -1;
}
//step 1 : map the src to the samples
cv::Mat samples(src.total(), 3, CV_32F);
float* samples_ptr = samples.ptr<float>(0);
for( int row = 0; row != src.rows; ++row){
uchar* src_begin = src.ptr<uchar>(row);
uchar* src_end = src_begin + src.cols * src.channels();
//auto samples_ptr = samples.ptr<float>(row * src.cols);
while(src_begin != src_end){
samples_ptr[0] = src_begin[0];
samples_ptr[1] = src_begin[1];
samples_ptr[2] = src_begin[2];
samples_ptr += 3; src_begin +=3;
}
}
//step 2 : apply kmeans to find labels and centers
int clusterCount = 3;
cv::Mat labels;
int attempts = 5;
cv::Mat centers;
cv::kmeans(samples, clusterCount, labels,
cv::TermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS,
10, 0.01),
attempts, cv::KMEANS_PP_CENTERS, centers);
//step 3 : map the centers to the output
cv::Mat new_image(src.size(), src.type());
for( int row = 0; row != src.rows; ++row){
uchar* new_image_begin = new_image.ptr<uchar>(row);
uchar* new_image_end = new_image_begin + new_image.cols * 3;
int* labels_ptr = labels.ptr<int>(row * src.cols);
while(new_image_begin != new_image_end){
int const cluster_idx = *labels_ptr;
float* centers_ptr = centers.ptr<float>(cluster_idx);
new_image_begin[0] = centers_ptr[0];
new_image_begin[1] = centers_ptr[1];
new_image_begin[2] = centers_ptr[2];
new_image_begin += 3; ++labels_ptr;
}
}
cv::Mat binary;
cv::Canny(new_image, binary, 30, 90);
cv::imshow("original", src);
cv::imshow("binary", binary);
cv::imshow( "clustered image", new_image );
cv::waitKey();
return 0;
}
相关文章推荐
- OpenCV中KMeans算法介绍与应用
- 【OpenCV】中的KMeans算法介绍与应用(一)
- 【opencv】OpenCV中的KMeans算法介绍与应用(二)
- otsu自适应阈值分割的算法描述和opencv实现,及其在肤色检测中的应用
- opencv自适应阀值cvAdaptiveThreshold的应用
- 导向滤波小结:从导向滤波(guided filter)到快速导向滤波(fast guide filter)的原理,应用及opencv实现代码
- opencv中camshift例子的应用
- opencv(25)---轮廓特征属性及应用之矩
- Kmeans算法原理极其opencv实现(转帖)
- OpenCV图像处理车牌检测与定位应用
- opencv 轮廓应用
- opencv轮廓高级应用(轮廓匹配,几何直方图)
- OpenCV学习笔记-应用trackbar实现按钮功能
- VC6.0应用OpenCV时出现的错误及解决办法
- Matlab与OpenCV在实际应用中的选择问题
- opencv3矩的计算-在图像中的应用
- 【OpenCV学习笔记】九、实例应用(二)鼠标截图程序及滑动条视频播放程序
- Opencv中K均值算法(K-Means)及其在图像分割中的应用
- Opencv决策树分类器应用
- opencv-python 摄像头的简单应用