摘要:在上一篇文章图工具的优化实现文本居中中,我们已经实现了对插入字体的左中右对齐显示,那因为上期文章混进去了不少语法讲解,所以后面的内容就顺延到这啦,哈哈哈。
在上一篇文章【图工具的优化——实现文本居中】中,我们已经实现了对插入字体的左中右对齐显示,那因为上期文章混进去了不少语法讲解,所以后面的内容就顺延到这啦,哈哈哈。
我比较长怎么办啊?我们的斗图小工具,现在面临这一个苦恼,这些文本他坏,一会长一会短的,一旦有个很长很长的,直接就捅到里面去了,根本显示不全啊,这咋办呢?
我稍微想了下,这个也简单,我可以不断的减小字号,直到我们的空白区域可以放得下:
while (CONST_IMG_WIDTH <= textLen + 2*off_set[0]) and fontSize >= 1: fontSize -= 1 imageFont = ImageFont.truetype("./resources/msyh.ttc", fontSize) textLen = draw.textsize(text, imageFont)[0] print("当前字号{},文本宽度{}".format(fontSize, textLen))
看看效果吧:
python emofigther.py 长的就会变细变细了就能塞下了嘛
效果其实还是挺好的,就是实现的方式有点太low了,而且不停的加载字体,看着就觉得开销很大,那有没有更优雅的办法呢?
来做点小数据分析吧下面我们来研究一下,字体的字号大小跟其经过PIL绘制之后的大小有什么关系,接下来我们主要会用到Numpy、matplotlib跟scipy几个库。
先来准备点数据样本,通过draw.textSize函数,绘制单个字并获取其大小:
# 准备分析数据 font_num = [] text_size = [] for i in range(1, 31): imageFont = ImageFont.truetype("./resources/msyh.ttc", i) text_size.append(draw.textsize("字", font=imageFont)) font_num.append(i)
借助matplotlib的pyplot模块,我们可以绘制各种图像,先让我们以字号为x轴,字体宽度为y轴,画出样本的散点图
import matplotlib.pyplot as plt #.... # scatter画出散点图,以字号为x轴,字体宽度为y轴 # 在分析前,先绘制散点图,对大致的函数形状进行分析 plt.scatter(list(map(lambda x: x[0], text_size)), font_num, color="b", label=u"字体宽度")
运行之后,会弹出这样一个窗口
好的,从这个图片上分析,我们的字号与宽度是一个完美的正相关,用函数来表示,就是
$$ y=kx+b $$
那问题来了,我们如何取得k和b两个常数的值呢,那个说k=1,b=0的同学你坐下!我们要严谨,看出来了也不要说出来嘛,额,不对,就算是看出来了,但我们还是要以严谨的方式去证明他的!为了求出k和b两个常数的最优解,我们需要用到scipy.optimize模块的leastsq函数,这个函数实现了“最小二乘法”算法,通过不断的尝试不同的常数,求出与期望结果误差最小的最优解,那下面就简单介绍一下怎么用leastsq对函数进行拟合:
首先,我们要定义一个函数形状(一元一次、一元二次、多元多次)
def func_shape(p, x): """定义函数形状,哈哈哈,就是 y = kx+b 直线! Args: p: 常数 x: 自变量 Returns: 函数运算求得的因变量 """ k,b = p return k*x + b
然后定义一个误差计算函数
def func_err(p, x, y): """定义误差函数 Args: p: 常数 x: 自变量 y: 验证因变量 Returns: 返回函数运算结果与验证因变量之间的误差值 """ return func_shape(p, x) - y
使用leastsq函数进行求解,获取最优常量k、b
from scipy.optimize import leastsq r = leastsq(func_err, p0, args=(_font_size_np[:,0], _font_num_np)) # 计算结果中的r[0]为一个元组,为求得的k和b k, b = r[0] # 最后我们得出结论,拟合结果为y = x print("k=",k,"b=",b, "r=", r)
把拟合曲线也画在图标上:
# 画出拟合线,以字号为X轴,函数运算结果为Y轴 plt.plot(X,func_shape((k, b), X),color="orange",label=u"字体宽度拟合",linewidth=2)
可以看到拟合曲线完美的经过了每一个数据点,这基本就可以认定我们的拟合曲线基本上就是 y=x了,
当然,我们的样本量现在是非常少的,也非常的规整,其实更多情况下,数据可能是这样分布的:
这样是不是就能体现出拟合的意义了呢?
# 方法2:通过简单的数据分析,我们研究出字体宽度 = 字体字号这一函数 def char_len(text_size): return text_size # 减小字号,直到 字数*单位宽度 适应空白区域宽度 while char_len(fontSize) * len(text) > (CONST_IMG_WIDTH - 2*off_set[0]): fontSize -= 1学霸们,动起来!
如果有小伙伴们看到这个章节,对本章节描述的数据分析过程非常感兴趣,而且觉得自己的数学功底非常扎实(特别是离散数学、概率、统计这方面的)你们请离开本系列文章——因为你们已经了解到了在科学计算领域,Python也是一把不错的兵刃,而你们,被选中的魔法少女(大雾)们,可以去深入了解以下几个库,然后投入到轰轰烈烈的数据分析事业中去吧!
Numpy —— 为Python提供了多维数组的扩展,同时也提供了丰富的集合运算、矩阵运算、向量运算,可以说是Python科学计算的基石
matplotlib —— 可产生出版物质量的图表的2D绘图库,数据可视化是数据分析不可或缺的手段之一
pandas —— 数据分析库,包括数据框架(dataframes)等结构
Scipy —— 高级科学计算库,提供了大量的科学计算工具及算法,例如本文用到的leastsq最小二乘法求解多项式算法(妈妈再也不用担心我要重复造轮子了!)
这些库的相关资料都非常的好找,而小弟又才疏学浅,就不再对它们在作过多展开了!
因为作者数学水平太差了,我们下期换个方向玩按照惯例,放上此次的源码:
GitHub
其中的char_analysis.py即为本文所属的函数拟合例子
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/42121.html
摘要:大家还记得上一篇文章来学点吧从一个斗图小工具开始中最后提到的几个问题么,我们这次就来解决一下其中难度最大的一个文本居中看,我把代码优化了上次之后,我偷偷把代码优化了,现在的方法长这样创建表情图调试用生成表情包对的,我把那些老长老长 showImg(https://segmentfault.com/img/bVbeDVL?w=250&h=250); 大家还记得上一篇文章0.来学点Pyth...
摘要:因此,本文将会以一些正经的严谨的有深度的大概吧的课题,慢慢的接触人工智能的相关知识。 Before The Beginning 近年,技术圈炒的最火的两个话(ba)题(gua)不外乎就是人工智障智能以及炒币区块链了,这个系列文章我主要以一个小菜鸟的角度一步一步的对人工智能的相关知识做一点了解,也算是一个颤颤巍巍追着AI浪潮公交车的社会主义五好青年,咳咳,扯远了...其实对于人工...
阅读 2643·2021-09-13 10:26
阅读 1906·2021-09-03 10:28
阅读 1977·2019-08-30 15:44
阅读 794·2019-08-29 14:07
阅读 385·2019-08-29 13:12
阅读 2142·2019-08-26 11:44
阅读 2335·2019-08-26 11:36
阅读 2002·2019-08-26 10:19