请将你的原始图像保存为 1.jpg,然后调用下面的代码。
这银卖个与上一次解答问题类似(http://zhidao.baidu.com/question/2056108112801456027),主要是对区域编号采用手工编号(因为区域描述子出来的区域编号与你的图不一致,所以人工观察了一下,然后利用switch那段代码修改的,如regionprops中的1号区域对应你图像的3号区域)。
clc clear close allhuman = [1336.593, 1340, 9673.42, 460, 3600, 2520, 504, 1800, 1790, 720, 870]
[~,sortI] = 差差sort(human)
imgori = imread('1.jpg')
imgori = im2bw(imgori)
imgcom = imfill(~imgori,'holes') %反相填充,去除贴边区域
img = imgori & imgcom
img = imfill(img,'holes')
% 区域描述子
tmpregions = regionprops(img,'PixelList','BoundingBox','Centroid')
% 去除字符内的闭合区域
need = ones(1,length(tmpregions))
for m = 1:length(tmpregions)
bbm = tmpregions(m).BoundingBox
for n = 1:length(tmpregions)
bbn = tmpregions(n).BoundingBox
if m~=n && bbm(1)<bbn(1) && bbm(2)<bbn(2) && ...
bbm(1)+bbm(3)>bbn(1)+bbn(3) && bbm(2)+bbm(4)>bbn(2)+bbn(4)
need(n) = 0
end
end
end
% 保留的区域
id = 1
for k = 1:length(tmpregions)
if need(k)==1
regions(id) = tmpregions(k)
id = id + 1
end
end
length(regions) % 输出11
% 区域手动编号锋庆逗
map = zeros(size(img))
for k = 1:length(regions)
pl = regions(k).PixelList
for m = 1:size(pl,1)
switch k
case 1, map(pl(m,2),pl(m,1))=find(sortI==3)
case 2, map(pl(m,2),pl(m,1))=find(sortI==4)
case 3, map(pl(m,2),pl(m,1))=find(sortI==2)
case 4, map(pl(m,2),pl(m,1))=find(sortI==1)
case 5, map(pl(m,2),pl(m,1))=find(sortI==5)
case 6, map(pl(m,2),pl(m,1))=find(sortI==6)
case 7, map(pl(m,2),pl(m,1))=find(sortI==8)
case 8, map(pl(m,2),pl(m,1))=find(sortI==9)
case 9, map(pl(m,2),pl(m,1))=find(sortI==10)
case 10, map(pl(m,2),pl(m,1))=find(sortI==7)
case 11, map(pl(m,2),pl(m,1))=find(sortI==11)
end
end
end
map = map + 1
% 输出区域人数
figure,imshow(img)
hold on
for k = 1:length(regions)
center = regions(k).Centroid
center = fix(center)
text(center(1),center(2),num2str(human(sortI(map(center(2),center(1))-1))),'FontSize',15,'Color','r')
end
% 显示热力图
figure
tmp = flipud(hot(12))
tmp(1,:) = [0 0.5 0.4] % 背景色
imshow(map, colormap(tmp))
两维数据的展现形式有很多,例如使用图线相对高低来表征数据大小的折线图与条形图,用角度大小来表征占比的饼形图。当面对更多维度的数据时,例如常见的课程表就是三维数据
这张图是用matlab的pcolor函数画的(实际上是修正了原始数据的pcolor,因为pcolor不会画出最边缘的一行和一列),用excel、origin和python自然都可以画出来。从图中可以看出,除了星期三(横坐标3-4之间)以外,每一天都不必早起,另外由于第4和第5节课之间是午餐时间,可见星期三是不能午休的。类似地,星期一和星期五下午没有太多的时间进行运动,因为下午过后有晚课。这样,我们就将课程表的数据转换为了直观可视的二维图。
只显示有无课,对于数据分析而言是不够的,我顷棚们可以尝试对更多的信息进行量化。例如,将纵坐标缩小为“上午-中午-下午”,横坐标展示课程的节数,我们可以把矩阵写成:
通常来说,热力图关心的事情是,一个区域内粒子的密度与位置的关系。例如,足球运动员在球场上的活动范围,或者是研究病毒携带者的活动轨迹。但是我们也可以用它来表征一般的三维数据。在我最近所接触到的一项用户调研中,获得的数据是一系列的每日问卷。问卷关心用户在看到手机推送消息之后,怎样处理消息,因此因变量自然是消息的处理方式。在问卷中,处理方式分为五种,即立即阅读、稍后阅读、上滑忽略、立即删除和一键清空全部消息。根据前面描述的方法,很自然可以圆配将其量化为1-5。而问卷所涉及的自变量就有很多了,例如用户看到消息的时间,他当时在做什么,心情如何,觉得消息是否有趣或者有用,等等。于是我们可以设计一个类似于课程表一样的两维表格,将其中的两个自变量作为横纵轴,处理方式作为因变量,以展现三维数据。
是这样吗?
问题来了,从统计学意义上,单份问卷实际上是没有意义的,万一填写问卷的用户与众不同,喜欢在上课的时候刷抖音,在娱乐的时候上网课呢?为了减小误差,我们一定需要大量的数据支持,才能得出有用的结论——这就是所谓的 大数据 技术。于是我们发出去了很多封问卷,也收回来了很多封。于是, 真正的因变量一定是群体行为 ,最容易研究的群体行为是人数。所以,对于这样的一系列量表,我们最终关心的热力图将拥有下面的形式:
自变量1:固定不变,为用户对消息的处理方式,已经量化为1-5
自变量2:可变,例如,取用户的心情,同样量化为1-5,用1表示心情很差,3代表一般,5代表心情很好
因变量:用户的人数
接下来的问题,是如何确定每一个格子的人数了,也就是要给下面5x5的黑色格子填上数。
解读这一个数表,每一个格子都有具体的含义,例如,(处理方橘乎指式, 心情好坏)=(2,4)表示,稍后阅读消息并且心情有点不好的用户。那么(2,4)这个格子对应多少人呢?很容易想到评选班委的唱票法:每有一个这样的用户,就给正字添上一笔。
知道了这一点,写下一个算法就很容易了:
for person in all_questionnaire
____x = person.operation
____y = person.mood
____table(x, y) += 1
endfor
(下划线表示缩进)
利用这样的算法,我们就可以生成类似于量化课程表那样的数表。或者,有些软件有现成的方法可以一键绘制热力图,例如Origin,画出来还很好看,可以经过各种后期调整,推荐使用:
最后画出来的图是这样的。说到数据可视化,我们一定能从里面分析出点什么来。还记得色阶的定义嘛?颜色越偏红,代表该类用户数量越多;相反,颜色越偏蓝,代表该类用户数量越少。从图中可以很明显地看出,对于有趣程度=1,也就是很无聊的消息,选择一键清空全部消息的用户数量十分多,接近了50人。而对于有趣程度=4,也就是比较有趣的消息,大约有10名用户选择了立即查看,而有接近20名用户选择了稍后查看,几乎没有用户选择忽略或删除消息。从这一个热力图中,我们获得了这样的信息。
还没完,如果仔细观察图中的浅色格子,有没有注意到,这些格子呈现一个左高-右低的趋势。从数学上讲,这说明,消息的有趣程度,与用户删除消息的趋势,呈现负相关的态势——也就是说,对于有趣的消息,更多用户不选择删除,更想去阅读它们;对于无聊的消息,更多用户删除的意愿更高。再根据统计学的知识,用这一个样本反应总体情况,我们就可以知道用户更倾向于阅读 他们认为有趣 的消息了。有了这样的发现,我们就可以去做那些耗时更多的深入研究,例如做相关度检验和回归分析。
总结 利用一个量表就可以很方便地将各种评价或者分类量化为数据,接下来就可以借助热力图来快速定性分析三列数据之间的各种关系,例如数据的变化趋势(例如星期天要熬夜赶作业),还有不同数据之间的相关度(例如用户想读有趣的消息,删除无聊的消息)。从直观和效率的角度,特别是当展示给甲方爸爸看时,无疑是事半功倍的。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)