Zedboard甲诊opencv图像处理(三)
flags: 这个主要是传递一些配置参数,例如 初始的时候使用user code给定的label –KMEANS_USE_INITIAL_LABELS,若使用kmeans++初始化算法– KMEANS_PP_CENTERS
_centers: 这个就是我们想要的结果了,该函数运行完毕以后,这个变量里面储存所有的center的数据,也就是你想要的东西了,引用例子的程序,稍作修改就拿来用了。
void kmeans_mat(const Mat& src_img,Mat& dst_img)
{
int width_src=src_img.cols;
int height_src=src_img.rows;
Mat samples=Mat::zeros(width_src*height_src,1,CV_32FC3);//创建样本矩阵,CV_32FC3代表32位浮点3通道(彩色图像)
Mat clusters;//类别标记矩阵
int k=0;
for (int i=0;i)
{
for (int j=0;j)
{
//将像素点三通道的值按顺序排入样本矩阵
samples.at(k,0)[0]=(float)src_img.at(i,j)[0];
samples.at(k,0)[1]=(float)src_img.at(i,j)[1];
samples.at(k,0)[2]=(float)src_img.at(i,j)[2];
}
}
int nCuster=2;//聚类类别数,自己修改。
//聚类,KMEANS PP CENTERS Use kmeans++ center iniTIalization by Arthur and Vassilvitskii
kmeans(samples,nCuster,clusters,TermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,10,1.0),2,KMEANS_PP_CENTERS);
//显示聚类结果
if (dst_img.empty())
{
dst_img=Mat::zeros(height_src,width_src,CV_8UC1);
}
k=0;
int val=0;
float step=255/(nCuster-1);
for (int i=0;i)
{
for (int j=0;j)
{
val=255-clusters.at(k,0)*step;//int
dst_img.at(i,j)=val;
}
}
}
来看看聚类结果先:
聚类效果还不错,只是比原本的指甲小了点,需要进一步修改,或者和前面的边缘提取相结合进行修正。而且聚类的数目需要人来控制。
我在opencv的处理中总是遇到一个问题:Bad argument (Ukown array type) in cvarrToMat,后来发现是opencv库函数的使用问题,他有c的也有c++的,Mat一般是c++下的,所以用c的库函数会出现这个问题。
另外c版本中的保存图片为cvSaveImage()函数,c++版本中直接与matlab的相似,imwrite()函数。小插曲!