kmean是常用的聚类算法之一主要步骤为:
1.读如点数据,随机选取k个点成为最后要聚的类数目;
2.求剩下的点到这k个点的距离,取最小值,按点的距离聚成一类;
3算同一类中点的质心坐标,即x,y的平均值作为中心点,
4求个点到这中心点的距离,按距离再进行聚类;
5迭代求中心,再聚类;
6当中心点变化在相邻两次迭代的变化数值小与某一范围时停止迭代
7用OpenGL,VTK等可视化软件显示点的分布;
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include <time.h>
#include "vtkSphereSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkCamera.h"
#include "vtkActor.h"
#include "vtkRenderer.h"
#include "vtkPolyData.h"
#include "vtkBoxWidget.h"
#include "vtkCardinalSpline.h"
#include "vtkPoints.h"
#include "stdio.h"
#include <time.h>
#include <vtkGlyph3D.h>
#include <vtkProperty.h>
#include <vtkCellArray.h>
#include <vtkTubeFilter.h>
#include <vtkPolyLine.h>
class dian///点类
{
public:
double x;
double y;
};
dian dianji[150];
dian zhongxin[3];
int findmin(double *juli)//找最小距离
{
int minnum=0;
if (juli[0] > juli[1])
{
minnum = 1;
if (juli[1] > juli[2])
{
minnum = 2;
}
}
else
{
if (juli[0] > juli[2])
{
minnum = 2;
}
}
return minnum;
}
int findminkguancha(int *kguanchadian,dian shuru)//算距离
{
double juli[3];
int kdiannum;
juli[0] = abs(shuru.x*shuru.x + shuru.y*shuru.y - dianji[kguanchadian[0]].x*dianji[kguanchadian[0]].x - dianji[kguanchadian[0]].y*dianji[kguanchadian[0]].y);
juli[1] = abs(shuru.x*shuru.x + shuru.y*shuru.y - dianji[kguanchadian[1]].x*dianji[kguanchadian[1]].x - dianji[kguanchadian[1]].y*dianji[kguanchadian[1]].y);
juli[2] = abs(shuru.x*shuru.x + shuru.y*shuru.y - dianji[kguanchadian[2]].x*dianji[kguanchadian[2]].x - dianji[kguanchadian[2]].y*dianji[kguanchadian[2]].y);
kdiannum = findmin(juli);
return kdiannum;
}
void findzhongxin(int* juleibaochun, int leidianshu,int k)//找中心点
{
double zhongxinX,zhongxinY ;
double zhongX, zhongY;
zhongX = zhongY = zhongxinY = zhongxinX = 0;
for (int i = 0; i < leidianshu; i++)
{
zhongX = zhongX + dianji[juleibaochun[i]].x;
zhongY = zhongY + dianji[juleibaochun[i]].y;
}
zhongxinX = zhongX / leidianshu;
zhongxinY = zhongY / leidianshu;
zhongxin[k].x = zhongxinX;
zhongxin[k].y = zhongxinY;
}
int findminkguancha2( dian shuru)//找中心点
{
double juli[3];
int kdiannum;
juli[0] = abs(shuru.x*shuru.x + shuru.y*shuru.y - zhongxin[0].x*zhongxin[0].x - zhongxin[0].y*zhongxin[0].y);
juli[1] = abs(shuru.x*shuru.x + shuru.y*shuru.y - zhongxin[1].x*zhongxin[1].x - zhongxin[1].y*zhongxin[1].y);
juli[2] = abs(shuru.x*shuru.x + shuru.y*shuru.y - zhongxin[2].x*zhongxin[2].x - zhongxin[2].y*zhongxin[2].y);
kdiannum = findmin(juli);
return kdiannum;
}
void main()
{
int kguanchadian[3];
int juleibaochun[3][150];
int leidianshu[3] = {0};
for (int i1 = 0; i1 < 150; i1++)
{
dianji[i1].x = rand() % 150;
dianji[i1].y = rand() % 150;
}
for (int i2 = 0; i2 < 3; i2++)
{
kguanchadian[i2] = rand() % 150;
}
for (int i3 = 0; i3 < 150; i3++)
{
int temp;
temp = findminkguancha(kguanchadian, dianji[i3]);
juleibaochun[temp][leidianshu[temp]] = i3;
leidianshu[temp]++;
}
findzhongxin(juleibaochun[0], leidianshu[0], 0);
findzhongxin(juleibaochun[1], leidianshu[1], 1);
findzhongxin(juleibaochun[2], leidianshu[2], 2);
printf("第1次点集中心\n");
for (int i4 = 0; i4 < 3; i4++)
{
printf("点集%d中心\n",i4+1);
printf("x:%lf,y:%lf\n", zhongxin[i4].x, zhongxin[i4].y);
}
for (int i5 = 0; i5 <20 ; i5++)
{
int juleibaochun2[3][150];
int leidianshu2[3] = { 0 };
for (int j = 0; j < 150; j++)
{
int temp;
temp = findminkguancha2(dianji[j]);
juleibaochun2[temp][leidianshu2[temp]] = j;
leidianshu2[temp]++;
}
findzhongxin(juleibaochun2[0], leidianshu2[0], 0);
findzhongxin(juleibaochun2[1], leidianshu2[1], 1);
findzhongxin(juleibaochun2[2], leidianshu2[2], 2);
printf("第%d次点集中心\n",i5+2);
for (int p = 0; p < 3; p++)
{
printf("点集%d中心\n", p+1);
printf("x:%lf,y:%lf\n", zhongxin[p].x, zhongxin[p].y);
}
if (i5 == 19)
{
//hwnd = GetConsoleWindow();
//hdc = GetDC(hwnd);
printf("点集一包含的元素\n");
for (int q = 0; q < leidianshu2[0]; q++)
{
printf("元素%d,x:%lf,y:%lf\n", q+1, dianji[juleibaochun2[0][q]].x, dianji[juleibaochun2[0][q]].y);
//SetPixel(hdc, dianji[juleibaochun2[0][q]].x, dianji[juleibaochun2[0][q]].y, 1);;
}
printf("\n");
printf("\n");
printf("点集二包含的元素\n");
for (int q1 = 0; q1 < leidianshu2[1]; q1++)
{
printf("元素%d,x:%lf,y:%lf\n", q1+1, dianji[juleibaochun2[1][q1]].x, dianji[juleibaochun2[1][q1]].y);
}
printf("\n");
printf("\n");
printf("点集三包含的元素\n");
for (int q2 = 0; q2 < leidianshu2[2]; q2++)
{
printf("元素%d,x:%lf,y:%lf\n", q2 + 1, dianji[juleibaochun2[2][q2]].x, dianji[juleibaochun2[2][q2]].y);
}
////////////////////////下面主要是画图
vtkRenderer *ren = vtkRenderer::New();
vtkRenderWindow *renWindow = vtkRenderWindow::New();
renWindow->AddRenderer(ren);
renWindow->SetSize(600, 600);
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(renWindow);
vtkPoints *inputPoints0 = vtkPoints::New();
for (int q4 = 0; q4 < leidianshu2[0]; q4++)
{
inputPoints0->InsertPoint(q4, dianji[juleibaochun2[0][q4]].x, dianji[juleibaochun2[0][q4]].y, 0);
}
vtkPolyData *inputData0 = vtkPolyData::New();
inputData0->SetPoints(inputPoints0);
vtkSphereSource *balls0 = vtkSphereSource::New();
balls0->SetRadius(1);
balls0->SetPhiResolution(10);
balls0->SetThetaResolution(10);
vtkGlyph3D *glyphPoints0 = vtkGlyph3D::New();
glyphPoints0->SetInput(inputData0);
glyphPoints0->SetSource(balls0->GetOutput());
vtkPolyDataMapper *glyphMapper0 = vtkPolyDataMapper::New();
glyphMapper0->SetInputConnection(glyphPoints0->GetOutputPort());
vtkActor *glyph0 = vtkActor::New();
glyph0->SetMapper(glyphMapper0);
glyph0->GetProperty()->SetDiffuseColor(1, 0, 0);
glyph0->GetProperty()->SetSpecular(3);
glyph0->GetProperty()->SetSpecularPower(30);
///////////////////////////////////////////////////////
vtkPoints *inputPoints1 = vtkPoints::New();
for (int q5 = 0; q5 < leidianshu2[1]; q5++)
{
inputPoints1->InsertPoint(q5, dianji[juleibaochun2[1][q5]].x, dianji[juleibaochun2[1][q5]].y, 0);
}
vtkPolyData *inputData1 = vtkPolyData::New();
inputData1->SetPoints(inputPoints1);
vtkSphereSource *balls1 = vtkSphereSource::New();
balls1->SetRadius(1);
balls1->SetPhiResolution(10);
balls1->SetThetaResolution(10);
vtkGlyph3D *glyphPoints1 = vtkGlyph3D::New();
glyphPoints1->SetInput(inputData1);
glyphPoints1->SetSource(balls1->GetOutput());
vtkPolyDataMapper *glyphMapper1 = vtkPolyDataMapper::New();
glyphMapper1->SetInputConnection(glyphPoints1->GetOutputPort());
vtkActor *glyph1 = vtkActor::New();
glyph1->SetMapper(glyphMapper1);
glyph1->GetProperty()->SetDiffuseColor(0, 1, 0);
glyph1->GetProperty()->SetSpecular(3);
glyph1->GetProperty()->SetSpecularPower(30);
////////////////////////////////////////////
vtkPoints *inputPoints2 = vtkPoints::New();
for (int q6 = 0; q6 < leidianshu2[2]; q6++)
{
inputPoints2->InsertPoint(q6, dianji[juleibaochun2[2][q6]].x, dianji[juleibaochun2[2][q6]].y, 0);
}
vtkPolyData *inputData2 = vtkPolyData::New();
inputData2->SetPoints(inputPoints2);
vtkSphereSource *balls2 = vtkSphereSource::New();
balls2->SetRadius(1);
balls2->SetPhiResolution(10);
balls2->SetThetaResolution(10);
vtkGlyph3D *glyphPoints2 = vtkGlyph3D::New();
glyphPoints2->SetInput(inputData2);
glyphPoints2->SetSource(balls2->GetOutput());
vtkPolyDataMapper *glyphMapper2 = vtkPolyDataMapper::New();
glyphMapper2->SetInputConnection(glyphPoints2->GetOutputPort());
vtkActor *glyph2 = vtkActor::New();
glyph2->SetMapper(glyphMapper2);
glyph2->GetProperty()->SetDiffuseColor(0, 0, 2);
glyph2->GetProperty()->SetSpecular(3);
glyph2->GetProperty()->SetSpecularPower(30);
////////////////////////////////////////////
ren->AddActor(glyph0);
ren->AddActor(glyph1);
ren->AddActor(glyph2);
iren->Initialize();
renWindow->Render();
iren->Start();
}
}
}
这里主要用了vtk来显示结果;
结果为