0. 前言
需要在后端生成一个词云图给小程序。
使用kumo项目实现。
1. demo
首先新建maven项目,prom.xml中加入以下依赖。加完之后记得reload。
要确保自己电脑或者服务器安装了设置的字体,否则中文会出现乱码
<dependency>
<groupId>com.kennycason</groupId>
<artifactId>kumo-core</artifactId>
<version>1.28</version>
</dependency>
<dependency>
<groupId>com.kennycason</groupId>
<artifactId>kumo-tokenizers</artifactId>
<version>1.28</version>
</dependency>
TagWordCloudService 是一个生成词云图的类,有逐句注释。
import com.kennycason.kumo.CollisionMode;
import com.kennycason.kumo.WordCloud;
import com.kennycason.kumo.WordFrequency;
import com.kennycason.kumo.bg.CircleBackground;
import com.kennycason.kumo.bg.PixelBoundaryBackground;
import com.kennycason.kumo.font.FontWeight;
import com.kennycason.kumo.font.KumoFont;
import com.kennycason.kumo.font.scale.SqrtFontScalar;
import com.kennycason.kumo.image.AngleGenerator;
import com.kennycason.kumo.nlp.FrequencyAnalyzer;
import com.kennycason.kumo.nlp.FrequencyFileLoader;
import com.kennycason.kumo.nlp.tokenizers.ChineseWordTokenizer;
import com.kennycason.kumo.palette.ColorPalette;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.List;
public class TagWordCloudService {
// 照片纵横比
private double ratio = 1;
// 获取词云图片
// wordFile:单词及其频率文件路径
// pngOutputPath:图片输出路径,应该以.png结尾
// shapePicPath:词云形状图片路径,其背景应为透明背景,格式为png
public void generate(String wordFile, String pngOutputPath, String shapePicPath) throws IOException {
// final FrequencyAnalyzer frequencyAnalyzer = new FrequencyAnalyzer();
// 共检索多少个词
// frequencyAnalyzer.setWordFrequenciesToReturn(1000);
// 单词最短长度,一个汉字和一个英文字符都是1
// frequencyAnalyzer.setMinWordLength(2);
// frequencyAnalyzer.setStopWords(loadStopWords());
// 设置中文支持,另一种加载方式不用设置
// frequencyAnalyzer.setWordTokenizer(new ChineseWordTokenizer());
final List<WordFrequency> wordFrequencies;
// 加载词云有两种方式,一种是在txt文件中统计词出现的个数,另一种是直接给出每个词出现的次数,这里使用第二种
// 文件格式如下
// 100: frog
// 94: dog
// 43: cog
// 20: bog
FrequencyFileLoader frequencyFileLoader = new FrequencyFileLoader();
File file = new File(wordFile);
wordFrequencies = frequencyFileLoader.load(file);
// 生成图片的像素大小
final Dimension dimension = new Dimension(1024, (int)(1024*ratio));
final WordCloud wordCloud = new WordCloud(dimension, CollisionMode.PIXEL_PERFECT);
// 调节词云的稀疏程度,越高越稀疏
wordCloud.setPadding(10);
//设置背景色
wordCloud.setBackgroundColor(new Color(255,255,255));
//设置背景图片
wordCloud.setBackground(new PixelBoundaryBackground(shapePicPath));
// 颜色模板,不同频率的颜色会不同
wordCloud.setColorPalette(new ColorPalette(new Color(0x4055F1), new Color(0x408DF1), new Color(0x40AAF1), new Color(0x40C5F1), new Color(0x40D3F1), new Color(0xFFFFFF)));
// 设置字体
java.awt.Font font = new java.awt.Font("楷体", 0, 20);
wordCloud.setKumoFont(new KumoFont(font));
// 设置偏转角,角度为0时,字体都是水平的
// wordCloud.setAngleGenerator(new AngleGenerator(0, 90, 9));
wordCloud.setAngleGenerator(new AngleGenerator(0));
// 字体的大小范围,最小是多少,最大是多少
wordCloud.setFontScalar(new SqrtFontScalar(5, 40));
wordCloud.build(wordFrequencies);
wordCloud.writeToFile(pngOutputPath);
}
}
2. 方法详解
2.1 FrequencyFileLoader
加载每个单词及其频次有两种方法,一种是使用FrequencyAnalyzer,统计文档中每个词出现的次数。另一种是FrequencyFileLoader,直接获取每个词及出现的次数。每行使用 次数:词 的形式。
使用如下语句进行加载
wordFrequencies = frequencyFileLoader.load(file);
例如如下文件:
1: 赤赤
2: 赤橙
3: 赤红
4: 赤绿
5: 赤青
6: 赤蓝
7: 赤紫
8: 橙赤
9: 橙橙
10: 橙红
11: 橙绿
12: 橙青
13: 橙蓝
14: 橙紫
15: 红赤
16: 红橙
17: 红红
18: 红绿
19: 红青
20: 红蓝
21: 红紫
22: 绿赤
23: 绿橙
24: 绿红
25: 绿绿
26: 绿青
27: 绿蓝
28: 绿紫
29: 青赤
30: 青橙
31: 青红
32: 青绿
33: 青青
34: 青蓝
35: 青紫
36: 蓝赤
37: 蓝橙
38: 蓝红
39: 蓝绿
40: 蓝青
41: 蓝蓝
42: 蓝紫
43: 紫赤
44: 紫橙
45: 紫红
46: 紫绿
47: 紫青
48: 紫蓝
49: 紫紫
2.2 WordCloud
wordCloud.setBackground
设置背景样式,背景类包括CircleBackground、RectangleBackground、PixelBoundaryBackground。
最好用的莫过于PixelBoundaryBackground,可以使用一张透明背景图来限制词云生成的位置。
使用如下语句设置背景。
wordCloud.setBackground(new PixelBoundaryBackground(shapePicPath));
我使用如下图片进行词云生成。
最后效果:
wordCloud.setAngleGenerator
设置词旋转角度。
有两种形式,第一种是所有词的角度都相同。
wordCloud.setAngleGenerator(new AngleGenerator(0));
第二种是不同的词进行随便的旋转,从一个角度到另一个角度,设置一个step,限制有几个随机值。
wordCloud.setAngleGenerator(new AngleGenerator(0, 90, 9));