未分类

Pillow的简单使用

最近导师让我根据已有的笔画位置信息,生成相对应的图像信息,其中用到的就是Pillow库,所以接下来就按照这个任务要求,对Pillow这个库进行使用讲解。

数据

先介绍下数据吧,当时导师给了我一份600M的JSON文件,看到之后我的内心毫无波澜,甚至还想来一份黄焖鸡米饭。虽然数据量很大,但是每条数据是很规范的,例如这样:

1
{"_id":{"$oid":"58cbeb882398b78ed0c8165b"},"word":"640,83;640,83;642,93;645,102;650,112;653,121;654,128;656,136;654,143;649,152;641,164;630,178;616,193;599,208;583,224;571,234;564,241;558,246;557,250;556,254;562,257;567,260;573,263;575,264;578,270;576,278;572,289;566,303;557,320;549,332;542,342;539,348;537,352;538,353;539,354;541,354;543,355;544,356;544,358;544,363;543,372;541,384;538,396;536,405;536,411;536,415;537,417;542,418;546,420;551,420;554,421;555,422;555,427;552,437;546,455;533,479;514,511;493,548;473,580;460,604;452,622;448,632;448,638;451,639;464,637;484,621;504,600;518,581;527,566;530,558;531,552;529,548;526,545;525,542;523,539;526,534;533,526;546,519;555,514;565,514;569,515;570,522;567,537;560,557;551,577;544,592;540,600;540,604;540,605;541,606;544,607;548,609;550,610;552,613;552,618;552,627;551,637;549,647;548,653;547,658;547,661;549,664;550,665;553,668;554,672;556,676;556,686;555,697;553,708;550,717;549,722;549,725;551,728;553,730;557,733;560,736;563,743;565,754;561,777;552,804;540,833;524,862;508,884;496,899;490,906;485,908;484,903;484,890;494,863;506,842;522,829;543,821;568,835;589,855;608,886;622,923;629,946;633,966;633,977;633,979#577,414;577,414;593,416;614,420;648,423;666,423;689,418;704,414;724,404;742,390;755,381","wordIndex":8826,"str":"ᠠᠯᠳᠠᠬᠤ","createAtDate":{"$date":"2017-03-17T13:58:32.767Z"},"updateAtDate":{"$date":"2017-03-17T13:58:32.767Z"},"phoneId":"9e29fc4021b45fbe","userId":"0161132290","paid":false,"__v":0}

word字段就是笔画的信息,所以现在找个画笔跟着这个笔画画就行了。

思路

因为这些笔画的位置和大小并不是特别规范的(因为收集这些手写体的时候,就是利用手机的手写输入收集的,所以不是很规范),所以首先生成一个3000*3000的灰度图(底是白色),然后用一个很粗的画笔(当时用来一个width = 18的画笔)将上述的笔画画出来,在这之前我们可以先找出笔画的横向最大最小值和纵向的最大最小值,然后根据这四个值,在画布上裁剪出一个矩形框,最后我们可以将裁剪出的矩形区域resize,按照要求是生成宽度为32,高度等比例缩放的图像,当然这个时候我们可以加一个参数,叫做抗锯齿,稍后我会讲到。

因为传统的PIL库不支持Python3,所以使用从PIL派生出来的Pillow库。

Image和ImageDraw类

Pillow中最重要的就是Image类,该类存在于同名的模块中。我们本次用到的实例化方式是直接创建一个图片。

生成画布

1
image = Image.new("L",(3000,3000),"white")

ImageDraw类,从名字中不难看出他的作用,那么接下来就开始画图吧。

顺便说一下,word字段里面,\(;\)分割的是点,\(,\)分割的是x和y,\(#\)分割的是笔画,所以根据这个层级关系,三层嵌套的方式就可以将这些笔画刻画出来。

生成画笔

1
draw = ImageDraw.Draw(image)

画图

1
2
3
4
5
6
7
8
9
lines = [[[int(x) for x in point.split(',')] for point in line.split(';')] for line in fileJson['word'].split('#')]

for line in lines:
if(len(line)>1):
draw.line((line[0][0], -line[0][1], line[1][0], -line[1][1]),fill='black',width=18)
temp = [line[1][0],line[1][1]]
for point in line:
draw.line((temp[0],temp[1],point[0],point[1]),fill='black',width=18)
temp=[point[0],point[1]]

裁剪

计算出横向纵向上的最大最小值,进行裁剪。(之所以加30,是因为有白边的情况下看着比较舒服,但是min的值并没有加,原因是容易产生黑杠)

1
2
box = (hor_min  , ver_min , hor_max + 30 , ver_max + 30)
b = image.crop(box)

resize并保存

1
2
a = b.resize((32,length),Image.ANTIALIAS)
a.save(path)

本次实验很简单,用到了Pillow中不多的函数,其实Pillow中还有很多有趣的操作,请大家自行研究它的中文文档。

效果

最后给大家看下效果:

593d584661d6b6417c2b19d6.bmp

58dba09d2398b78ed0c9a7ac.bmp