文章目录(Table of Contents)
简介
这一篇介绍关于词云的生成. 生成的结果如下所示. 会简单介绍一些参考资料和简单的使用方式.
参考链接
- WordCloud 的官方说明: 说明文档-wordcloud.WordCloud
- Github仓库: wordcloud-程序媛的浪漫表白,你的个人标签
- 简单使用方式: Windows环境下Python中wordcloud的使用——自己踩过的坑 2017.08.08
简单使用方式介绍
关于字体说明
使用wordcloud可以指定使用的字体, 在windows中, 字体在以下的文件夹中: C:\Windows\Fonts, 可以将其中的字体文件拷贝到当前的文件夹内.
我们指定字体可以使得其能生成中文的词云. 我下面放一张图, 具体生成过程是和下面的方法是一样的.
使用前准备
- from os import path
- from wordcloud import WordCloud
- from PIL import Image
- import numpy as np
- d = path.dirname(__file__)
- # Read the whole text.
- text = open(path.join(d, 'constitution.txt'), encoding='utf8').read()
- # 导入字体文件
- font_path = path.join(d, 'HYC6GFM.TTF')
生成普通的wordcloud
我们可以指定使用的字体, 图像的大小和颜色等.
- # 生成普通的wordcloud
- wordcloud = WordCloud(font_path=font_path, margin=1, random_state=1, max_words=300, width=1000, height=700, background_color='white').generate(text)
- wordcloud.to_file('wordcloud.jpg')
最终的生成效果如下所示:
使用蒙版来生成图片
我们想要使得生成图片能与蒙版相符, 我们使用下面的蒙版(如果想要使用自己的蒙版,可以使用关键词「剪影」或是「轮廓」,这样主要的图像是黑色的,我们主要就是突出一个轮廓):
- # 生成带有mask的图片
- mask = np.array(Image.open(path.join(d, "62.jpg")))
- wordcloud = WordCloud(font_path=font_path, mask=mask, margin=1, random_state=1, background_color='white').generate(text)
- wordcloud.to_file('wordcloud_mask.jpg')
最终生成的效果如下所示:
源代码
将上面的测试代码放在了github上, 链接为: wordcloud测试脚本
关于中文文档的词云生成(例子)
因为中文文档与外文不同,字符之间没有空格,所以我们需要首先对中文的文本进行分词。我们使用 jieba 库来对中文进行分词。这一部分参考自,中文文本的词云生成(以《三体》为例)。这一篇文章的代码可能有点问题,我在这里做一下简单的修改。
中文句子分词
首先我们对一句完整的句子进行分词,使用 jieba 来完成。
- # 对句子进行分词
- def seg_sentence(sentence):
- sentence_seged = jieba.cut(sentence.strip()) #strip()用来消除前后的空格
- outstr = ''
- for word in sentence_seged:
- if word != '\t':
- outstr += word
- outstr += " " #去掉制表符并用空格分隔各词
- return outstr.strip()
最终的效果如下所示:
停用词的处理
我们看到,上面句子中包含一些「停用词」,例如标点符号等,我们需要将其去掉。关于停用词表,可以直接在 github 上搜索「停用词」即可。我这里随便选择了其中的一个停用词来作为例子。
下面的函数可以读入停用词表,并将其转换为一个 list。
- # 创建停用词list
- def stopwordslist(filepath):
- stopwords = [line.strip() for line in open(filepath, 'r', encoding='utf-8').readlines()]
- return stopwords
大致的效果如下所示:
中文句子分词与停用词
我们把上面的两个步骤结合起来。对中文句子进行分词,同时去掉其中的「停用词」。
- def seg_sentence(sentence):
- sentence_seged = jieba.cut(sentence.strip())
- stopwords = stopwordslist('./stop.txt') # 这里加载停用词的路径
- outstr = ''
- for word in sentence_seged:
- if word not in stopwords: # 判断如果不是停用词
- if word != '\t':
- outstr += word
- outstr += " "
- return outstr
对中文文档绘制 wordcloud
在有了上面的铺垫之后,我们就可以对一个中文的文档绘制 wordcloud 了。整体的代码如下所示:
- import jieba
- from wordcloud import WordCloud
- import matplotlib.pyplot as plt
- import numpy as np
- from PIL import Image
- inputs = open('./example.txt', 'r', encoding='utf-8') # 原始的中文文档
- outputs = open('./output.txt', 'w', encoding='utf-8') # 分词过后的中文文档
- for line in inputs:
- line_seg = seg_sentence(line) # 对每个句子进行分词
- outputs.write(line_seg + '\n') # 将处理过后的文件进行保存
- outputs.close()
- inputs.close()
- mask = np.array(Image.open("./66.jpg")) # 模板图片
- inputs = open('output.txt', 'r', encoding='utf-8')
- mytext=inputs.read()
- wordcloud=WordCloud(mask=mask, width=3000, height=3000, background_color="white", margin=1,
- max_words=300, min_font_size=10, max_font_size=None, repeat=False,
- font_path="./FZKaTong-M19S.ttf").generate(mytext) #生成云图
- wordcloud.to_file('wordcloud.jpg')
- inputs.close()
最终生成的图像的效果如下所示:
指定颜色风格
在生成词云的时候,有一个参数是 colormap,我们可以指定需要的颜色风格。关于详细的 colormap 的内容,可以查看链接,Matplotlib Colormap reference。我们想要 colormap 起作用,需要设置 mode='RGBA'
。
- wordcloud=WordCloud(mask=mask, width=800, height=800, background_color="white", margin=1, max_words=10000, min_font_size=10, max_font_size=None, repeat=True,collocations=False, mode='RGBA', colormap='Reds',font_path="./FZKaTong-M19S.ttf").generate(mytext)
关键词显示重复
如果我们不想要出现的内容重复,我们可以参数,collocations=False
,即可。
词云与原图融合
有的时候,我们希望我们生成的词云与原图可以有融合的效果,这样最终生成的图像可以看出我们的原图。我们可以使用 pillow 来对两张图片进行融合。如下有两张图片,分别是一头牛的轮廓:
和按照这个牛生成的字符画。这里我们生成的时候,需要把牛的轮廓里面也涂成黑色的,不然只有一个轮廓是无法绘制出图云的。
我们将上面的两张图融合在一起,这样可以更好看出字符画是什么动物,使用 blend 来进行融合,如下所示:
- img = Image.open('./niu_2.png')
- background = Image.open('niu_1.jpg')
- background = background.convert('RGBA') # 两个图片的格式需要相同
- img = Image.blend(background, img, 0.7)
- img.save('out_with_background.png')
最终的效果如下所示,可以看出这个时候效果会更加明显:
参考资料,Python中Pillow使用介绍
词云与遮罩-进一步说明
上面我们简单介绍了 mask 的使用。但是实际情况下很可能因为图片的选择不当,造成不能生成我们想要的形状的词云。这里我们进一步来说明一下 mask 与词云的使用。这一篇的内容主要参考自,[Python] wordcloud 模組使用 mask 生成特定形狀、顏色(这一篇写得非常不错)
为了进行说明,我们从 GitHub 商获得范例图片,链接如下所示:词云范例图片-鹦鹉。图片是下面的样子,非常好看。
图片的处理
上面图片背景是黑色的,我们需要首先将黑色背景转换为白色(一些其他颜色的变化,可以参考下面的代码),同时我们我们需要检测出物体的边缘。可以使用下面的代码来进行图像的处理(如果有的时候图片比较小,我们可以使用 pillow 中的 resize 对图像进行放大):
- from scipy.ndimage import gaussian_gradient_magnitude
- # 图片的处理
- img = Image.open("./parrot-by-jose-mari-gimenez2.jpg")
- mask_color = np.array(img)
- mask_color = mask_color[::3, ::3]
- mask_image = mask_color.copycopy()
- mask_image[mask_image.sum(axis=2) == 0] = 255 # 把黑色都转换为白色
- # Edge detection
- edges = np.mean([gaussian_gradient_magnitude(mask_color[:, :, i]/255., 2) for i in range(3)], axis=0)
- mask_image[edges > .08] = 255
- im = Image.fromarray(mask_image)
- im.save("./your_file.jpeg")
处理完毕之后图像如下所示,黑色背景变为了白色:
简单的词云图像生成
首先我们只利用上面图像的形状,让最终的效果是一只鹦鹉:
- # 绘制词云
- inputs = open('./output.txt', 'r', encoding='utf-8')
- mytext=inputs.read()
- wordcloud=WordCloud(mask=mask_image, margin=1, relative_scaling=0,
- max_words=10000, min_font_size=10, max_font_size=None, repeat=True,collocations=False,
- mode='RGB',font_path="./FZKaTong-M19S.ttf").generate(mytext) #生成云图
- wordcloud.to_file('wordcloud.jpg')
- inputs.close()
最终的生成的效果如下所示:
产生特点颜色和形状的图云
上面我们可以看到原始图片中鹦鹉的颜色很好看,我们希望生成的图片的颜色也和原始图像接近。这里我们只需要在上面代码后面加上重新着色即可。下面看一下简单的说明:
- # 绘制词云
- inputs = open('./output.txt', 'r', encoding='utf-8')
- mytext=inputs.read()
- wordcloud=WordCloud(mask=mask_image, margin=1, relative_scaling=0,
- max_words=10000, min_font_size=10, max_font_size=None, repeat=True,collocations=False,
- mode='RGB',font_path="./FZKaTong-M19S.ttf").generate(mytext) #生成云图
- # Create coloring from image
- image_colors = ImageColorGenerator(mask_color)
- wordcloud.recolor(color_func=image_colors)
- # 保存至图片
- wordcloud.to_file('wordcloud.jpg')
- inputs.close()
可以看到在 generate 之后,有一个步骤是重新着色。最终的生成的图像如下所示,此时生成图片的颜色和原始图片的颜色也是想接近的。
下面是生成部分的完整的代码,文本随便找一个文本即可。关于中文文本的处理,可以参考上面第二部分的内容。
- import numpy as np
- from PIL import Image
- from wordcloud import WordCloud, ImageColorGenerator
- from scipy.ndimage import gaussian_gradient_magnitude
- # 图片的处理
- img = Image.open("./parrot-by-jose-mari-gimenez2.jpg")
- mask_color = np.array(img)
- mask_color = mask_color[::3, ::3]
- mask_image = mask_color.copycopy()
- mask_image[mask_image.sum(axis=2) == 0] = 255 # 把黑色都转换为白色
- # Edge detection
- edges = np.mean([gaussian_gradient_magnitude(mask_color[:, :, i]/255., 2) for i in range(3)], axis=0)
- mask_image[edges > .08] = 255
- # 绘制词云
- inputs = open('./output.txt', 'r', encoding='utf-8')
- mytext=inputs.read()
- wordcloud=WordCloud(mask=mask_image, margin=1, relative_scaling=0,
- max_words=10000, min_font_size=10, max_font_size=None, repeat=True,collocations=False,
- mode='RGB',font_path="./FZKaTong-M19S.ttf").generate(mytext) #生成云图
- # Create coloring from image
- image_colors = ImageColorGenerator(mask_color)
- wordcloud.recolor(color_func=image_colors)
- # 保存至图片
- wordcloud.to_file('wordcloud.jpg')
- inputs.close()
- 微信公众号
- 关注微信公众号
- QQ群
- 我们的QQ群号
评论