zoukankan      html  css  js  c++  java
  • 词云wordcloud的实现

    TOC

    什么是云词

    词云,也称为文本云或标签云。在词云图片制作中,一般我们规定特定文本词在文本数据源中出现的次数越多,说明该词越重要,其在词云中所占区域也就越大。词云可以利用常见的几何图形,或者其他不规则的图片素材形状来作为界限。词云不仅可以应用在企业数据分析上,还可以应用到媒体营销或者平面设计当中。
    大概长这样:

    快速实现

    要实现词云,首先肯定是要获取词组和权重,然后再根据数据进行可视化的展示。

    分词

    手动输入比较麻烦,一般根据句子进行分词,然后按照词语出现的次数计算权重。
    这里推荐用【讯飞关键词提取API】,有免费的额度,类似的云平台基本上都有这类API。
    https://www.xfyun.cn/doc/nlp/keyword-extraction/API.html
    如果不想用云API,也可以用开源分词库,这里推荐jieba
    https://github.com/fxsjy/jieba

    可视化

    直接用轮子:
    https://github.com/timdream/wordcloud2.js

    如果是基于echart,可以以扩展形式引入:
    https://github.com/ecomfe/echarts-wordcloud

    实现原理

    这里主要分析wordcloud2.js的源码,简要说明。
    假设我们要将一个不带旋转的词放入canvas中,如下图所示:

    注:canvas坐标系Y轴是向下的。
    1、canvas其实被切成了许多小方块(如例图所示),默认方块大小为16px,不小于4px,方格越大,间距越大。
    2、初始化grid = [];用来判断方块中能否放置元素。
    3、getTextInfo方法中,创建了一个新的fcanvas,通过measureText测量出词组宽度,为了防止文字被切,实际的fcanvas是大于测量的宽度的,如例图中黄色方框与绿色方框的关系。
    fctx.fillText(word, fillTextOffsetX * mu, (fillTextOffsetY + fontSize * 0.5) * mu);
    注意:这里为什么fillTextOffsetY要加上fontSize?
    默认情况下fillText的字体是左下角在坐标点的,所以需要加上fontSize使其满足canvas坐标系。例如:

    var c=document.getElementById("myCanvas");
    var ctx=c.getContext("2d");
    
    
    ctx.font="20px Georgia";
    ctx.fillText("Hello World!",50,50);
    
    
    ctx.fillRect(50,50,20,20)


    可以看到文字是整个高出了方块的。
    4、fcanvas填充完文字之后,通过getImageData获取图片像素信息,然后循环遍历每隔格子的每个像素,判断像素alpha是否有值,有则判断文字bounds边界(例图绿色方框),继续循环下一个格子。
    其中,bounds的值为【小y,大x,大y,小x】,通过这4个值,就可以得出边界坐标和宽高。
    左上:【小x,小y】
    右上:【大x,小y】
    左下:【小x,大y】
    右下:【大x,大y】
    宽:大x-小x
    高:大y-小y
    注意:imageData[((gy * g + y) * width + (gx * g + x)) * 4 + 3]

    getImageData() 方法返回 ImageData 对象,该对象拷贝了画布指定矩形的像素数据。
    对于 ImageData 对象中的每个像素,都存在着四方面的信息,即 RGBA 值:
    R - 红色 (0-255)
    G - 绿色 (0-255)
    B - 蓝色 (0-255)
    A - alpha 通道 (0-255; 0 是透明的,255 是完全可见的)
    color/alpha 以数组形式存在,并存储于 ImageData 对象的 data 属性中。

    这里乘以4是因为每个像素占4个下标,加3是为了获取alpha值。
    5、从中心点位置到半径范围内遍历,结合计算出的文字信息判断格子是否被占用,没被占用则填充文字,更新格子的值,直到放不下或放完为止。

    红色部分即为被“占领”的方格。
    6、图案遮罩如何实现的?
    我们可以通过上传图片,实现图片遮罩,白色部分将会被忽略,文字将被填充到黑色部分。


    还记得grid[]吗?其实我们在上传图片之后,通过getImageData获取图片数据,将白色的部分都标记成了已被占用的状态,所以后续的遍历,只会找到黑色的部分进行填充。

  • 相关阅读:
    美国诚实签经验——必带材料:护照,证件照,DS160确认页,面试预约确认页,+境外照片
    美国诚实签经验——医院预约单和医院资料,医生预约收据和报价表,赴美预算,赴美行程,保险是加分项,工作证明(勾出职位和薪酬),附上名片或者工卡,全家福照片
    php MySQLi部分函数(面向对象和过程)
    php calling scope
    mysqli_set_charset和SET NAMES优劣分析
    php 父类子类构造函数注意事项
    Dreamweaver显示花括号匹配
    php 父类调用子类方法和成员
    PHP 重载 __call() _callStatic方法
    转:Linus:利用二级指针删除单向链表
  • 原文地址:https://www.cnblogs.com/leestar54/p/13303468.html
Copyright © 2011-2022 走看看