这篇文章将以北京工商大学良乡校区附近的共享单车图进行鼠标取点操作以及对相关图像的处理,将共享单车以数据点的形式呈现,并且对数据点进行K值聚类找到最佳的中心点。
下面是对tif型的正方形图片进行取点操作(其他形状或者格式的图片可以,即将ylim注释掉),将所要进行操作的图片拖入工作区执行下面的代码:
%% 建立主函数
function BTBU_mouse_track() %BTBU_mouse_track() 运行时只要运行函数名即可
in = imread('照片名称.tif'); %imread函数为读取图像的函数
figure,imshow(in);
%% 显示坐标系,以及画平行于x轴与y轴的水平线,将图片分为四个区域
axis on; % 打开(显示)坐标系
hold on; plot([550,550],[0,1100],'r-'); %ylim 用于绘制y轴的取值范围
hold on; plot([0,1100],[550,550],'r-'); %m-- 用于描述线型,粉色,虚线
BTBUbikedata = zeros(0,2); %保存所取得点,并且以mat形式储存
save BTBUbikedata BTBUbikedata;
set(gcf,'WindowButtonDownFcn',@BTBU_ButttonDownFcn);
%% 回调函数
function [x,y]=BTBU_ButttonDownFcn(src,event)
load('BTBUbikedata.mat');
pt = get(gca,'CurrentPoint');
x = pt(1,1);
y = pt(1,2);
BTBUbikedata(end+1,1)=round(y); %每次新产生的坐标加到BTBUbikedata中,注意figure中的x,y坐标跟实际的是反过来的
BTBUbikedata(end,2)=round(x); %由于图像放大会产生非整数坐标,这里取整
[len,~] = size(BTBUbikedata);
fprintf('单车编号=%d,x=%f,y=%f\n',len,y,x);
save BTBUbikedata BTBUbikedata;
接着在先导入需要在上面展示数据点的底图,执行下列代码,可以得到图1-2所示的展示图
load('BTBUbikedata.mat'); %% 导入数据
x=BTBUbikedata(:,2); y=BTBUbikedata(:,1);
in = imread('图片底层.tif');%% 导入需要在图片上显示点的底图
figure,imshow(in); axis on;
hold on; plot([550,550],[0,1100],'r-'); %ylim 用于绘制y轴的取值范围
hold on; plot([0,1100],[550,550],'r-'); %m-- 用于描述线型,粉色,虚线
hold on; plot(x,y,'ro'); xlim([0,1100]); ylim([0,1100]);%对X轴和Y轴设定显示范围
title('研究样本散点分布图')
执行下列代码可以得到图1-3 二类聚类的轮廓图,由轮库图可以知道第一类数据大部分在0.8以下,而第二类的数据则比较集中,随后采用分层聚类进一步验证,根据分层聚类的方法得出的树状图可以看出,有两大类具有明显差异性的数据,而第三类则是也具有差异但数目极少的数据,因此可以分成明显的两类。
[cidx2,cmeans2,sumd2,D2] = kmeans(BTBUbikedata,2,'dist','sqEuclidean'); %二类K值
P2 = figure;clf;
[silh2,h2] = silhouette(BTBUbikedata,cidx2,'sqeuclidean');
eucD = pdist(BTBUbikedata,'euclidean'); %分层聚类
clustTreeEuc = linkage(eucD,'average');
cophenet(clustTreeEuc,eucD);
P3 = figure;clf;
[h,nodes] = dendrogram(clustTreeEuc,20);
set(gca,'TickDir','out','TickLength',[.002 0],'XTickLabel',[]); % 尝试用三类K值聚类分析
[cidx3,cmeans3,sumd3,D3] = kmeans(BTBUbikedata,3,'dist','sqEuclidean');
P4 = figure;clf;
[silh3,h3] = silhouette(BTBUbikedata,cidx3,'sqeuclidean');
然后将中心化的点再现在更加清晰可见的底图上
A=xlsread('BTBUbikedaily0801.xls'); %读取Excel表格数据
x=A(:,2); y=A(:,1);
x1=A(:,4); y1=A(:,3);
x2=A(:,6); y2=A(:,5);
x3=A(:,8); y3=A(:,7);
in = imread('图片.tif'); figure,imshow(in); axis on;
hold on; p1=plot([550,550],[0,1100],'r-'); %ylim 用于绘制y轴的取值范围
hold on; p2=plot([0,1100],[550,550],'r-'); %m-- 用于描述线型,粉色,虚线
hold on; p3=plot(x,y,'yo','MarkerFaceColor','y'); %绘制x和y的图像
hold on; p4=plot(x1,y1,'ro','MarkerFaceColor','r'); %MarkerFaceColor表示实心点
hold on; p5=plot(x2,y2,'bo','MarkerFaceColor','b');
hold on; p6=plot(x3,y3,'go','MarkerFaceColor','g');
legend([p3,p4,p5,p6],'昨日时间段03','时间段01','时间段02','时间段03','Location','northoutside','Orientation','horizontal'); %图例,注意图例会展示展示出所有前面plot所画的图像,包括所画的直线,因此采用[pi,pn]来限制图例的展示
title(legend,'0801各个时间段'); xlim([0,1100]); ylim([0,1100]); %对X和Y轴设定显示范围
set(gca,'YDir','reverse'); %将x轴方向设置为反向(从上到下递增)。
title('显示同一天的三个时间段样本散点分布图');
其中使用的单车数据BTBUbikedata.xlsx下载可以访问:https://github.com/ChenQihome9/CSDN-Data-Library
——Written in BTBU