完美數學公式轉圖片:純Python實現,可設置字體、字號、顏色和分辨率

      網友投稿 1185 2022-05-30

      寫數學公式,功能最強大的當然是LaTex了。不過,強大不代表易用,駕馭LaTex絕不是一件容易的事兒。這也不難理解:畢竟數學公式不是孤立存在的,必然要作為文檔、網頁或者程序輸出的元素,如何無縫地讓LaTex關聯到文檔、網頁或程序,的確是個棘手的難題。

      既然直接使用LaTex有難度,那就退而求其次:借助于工具將數學公式轉為圖片,然后就可以方便地應用到文檔、網頁或者程序中了。這樣的工具,除了在線式的,基本上都是重量級的,安裝和使用極不方便。我曾經花了11個C幣從CSDN買過一個數學公式轉圖片的工具,下載之后發現,竟然只是封裝了一個http請求,圖片仍然是在線生成的!一氣之下,自己寫了個離線的,只是功能比較簡單,不能方便地設置輸出圖像的大小和顏色。

      最近工作中又用到了LaTex,幾經嘗試,終于在matplotlib源碼中發現了一個處理LaTex數學公式的好東西。稍加改造,增加了字體、字號、顏色和分辨率的設置,最終完美解決了LaTex數學公式轉圖片的問題。

      1. 核心代碼

      先從最簡單的開始吧。matplotlib有個mathtext子模塊,提供了math_to_image函數可以直接將LaTex數學公式生成圖片。下面的代碼,僅僅兩行,就將質能方程轉成了圖片。請注意,LaTex數學公式一定要包含在兩個$符號之間。

      >>> from matplotlib import mathtext >>> mathtext.math_to_image(r'$E=mc^2$', r'd:\demo_1.png')

      生成的圖片寬度55個像素,高度15個像素,分辨率為100dpi。這么迷你,看上去可憐巴巴的。

      雖然指定了png格式,也確實存在透明通道,其背景卻是不透明的。除了png格式外,math_to_image函數還支持eps, pdf, pgf, png, ps, raw, rgba, svg, svgz等格式,但不支持jpg格式。

      2. 設置字體、字號、分辨率

      要設置字體字號,就得先導入matplotlib的font_manager字體管理模塊。該模塊的FontProperties類可以實例化一個字體對象傳給math_to_image函數,用來設置family(字體)、size(字號)和weight(筆畫輕重)等。

      最完美的數學公式轉圖片:純Python實現,可設置字體、字號、顏色和分辨率

      math_to_image函數的dpi參數用于設置分辨率(每英寸像素數)。如果應用于網頁的話,建議分辨率設置為72dpi就可以了,如果用于印刷,請將dip設置為300。

      >>> import matplotlib.font_manager as mfm >>> prop = mfm.FontProperties(family='sans-serif', size=64, weight='normal') >>> mathtext.math_to_image(r'$E=mc^2$', r'd:\demo_2.png', prop=prop, dpi=72)

      輸出結果如下。這次生成的圖片終于不那么可憐了,寬度250個像素,高度59個像素。

      如果不知道有哪些字體可用怎么辦?不要擔心,下面這一行代碼就可以列出當前系統中全部的可用字體。在我的電腦上運行之后,找到了幾百種可用的字體(重名的字體表示該字體有多個字體文件)。

      >>> [item.name for item in mfm.fontManager.ttflist]

      3. 設置顏色

      要想對圖片文件做顏色處理,最好的方式是先將math_to_image的輸出暫存到類文件對象中,借助于PIL和NumPy完成顏色設置后,再保存為文件。為此,要先導入io模塊、pillow模塊和numpy模塊。

      在開始寫代碼前,先約定使用浮點型的三元組表示顏色,比如,(0.17, 0.63, 0.17)表示亮度稍暗的綠色。如果喜歡使用其他方式表示顏色,請自行轉換。下面的例子換了一個復雜的數學公式(虛構的,并無實際意義)來演示如何設置顏色。

      >>> from io import BytesIO >>> from PIL import Image >>> import numpy as np >>> text = r'$s(t) = \mathcal{A}\mathrm{sin}(2 \omega \sum_{i=0}^\infty t_i)$' >>> color = (0.17, 0.63, 0.17) # 要使用的顏色 >>> bfo = BytesIO() # 創建二進制的類文件對象 >>> prop = mfm.FontProperties(family='Palatino Linotype', size=256, weight='normal') >>> mathtext.math_to_image(text, bfo, prop=prop, dpi=72) 209.0 >>> im = Image.open(bfo) # 打開二進制的類文件對象,返回一個PIL圖像對象 >>> r, g, b, a = im.split() # 分離出RGBA四個通道 >>> r, g, b = 255-np.array(r), 255-np.array(g), 255-np.array(b) # RGB通道反白 >>> a = r/3 + g/3 + b/3 # 生成新的alpha通道 >>> r, g, b = r*color[0], g*color[1], b*color[2] # RGB通道設置為目標顏色 >>> im = np.dstack((r,g,b,a)).astype(np.uint8) # RGBA四個通道合并為三維的numpy數組 >>> im = Image.fromarray(im) # numpy數組轉PIL圖像對象 >>> im.save(r'd:\demo_3.png') # PIL圖像對象保存為文件

      來看看最終的輸出結果是什么樣的呢?最終生成了2451x653的一張大圖,公式內容、字體、字號、顏色等,正如期望的那樣。大功告成!

      4. 封裝成函數

      為了方便使用,將上面的代碼封裝成一個函數,完整代碼如下。

      # -*- coding: utf-8 -*- import os from io import BytesIO from PIL import Image import numpy as np import matplotlib.font_manager as mfm from matplotlib import mathtext def latex2img(text, size=32, color=(0.1,0.1,0.1), out=None, **kwds): """LaTex數學公式轉圖片 text - 文本字符串,其中數學公式須包含在兩個$符號之間 size - 字號,整型,默認32 color - 顏色,浮點型三元組,值域范圍[0,1],默認深黑色 out - 文件名,僅支持后綴名為.png的文件名。若維None,則返回PIL圖像對象 kwds - 關鍵字參數 dpi - 輸出分辨率(每英寸像素數),默認72 family - 系統支持的字體,None表示當前默認的字體 weight - 筆畫輕重,可選項包括:normal(默認)、light和bold """ assert out is None or os.path.splitext(out)[1].lower() == '.png', '僅支持后綴名為.png的文件名' for key in kwds: if key not in ['dpi', 'family', 'weight']: raise KeyError('不支持的關鍵字參數:%s'%key) dpi = kwds.get('dpi', 72) family = kwds.get('family', None) weight = kwds.get('weight', 'normal') bfo = BytesIO() # 創建二進制的類文件對象 prop = mfm.FontProperties(family=family, size=size, weight=weight) mathtext.math_to_image(text, bfo, prop=prop, dpi=dpi) im = Image.open(bfo) r, g, b, a = im.split() r, g, b = 255-np.array(r), 255-np.array(g), 255-np.array(b) a = r/3 + g/3 + b/3 r, g, b = r*color[0], g*color[1], b*color[2] im = np.dstack((r,g,b,a)).astype(np.uint8) im = Image.fromarray(im) if out is None: return im else: im.save(out) print('生成的圖片已保存為%s'%out) if __name__ == '__main__': text = r'$\sum_{i=0}^\infty x_i$' latex2img(text, size=48, color=(0.1,0.8,0.8), out=r'd:\demo.png') text = r'$\sum_{n=1}^\infty\frac{-e^{i\pi}}{2^n}$' im = latex2img(text, size=48, color=(0.9,0.1,0.1)) im.show()

      AI Python

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:Python 3.8 即將到來,這是你需要關注的幾大新特性
      下一篇:Python代碼覆蓋率分析工具----Coverage
      相關文章
      国产精品亚洲高清一区二区| 亚洲男人的天堂在线va拉文| 亚洲色成人WWW永久网站| 亚洲AV日韩AV一区二区三曲| 亚洲人成电影青青在线播放| 91亚洲导航深夜福利| 亚洲AV综合色区无码一区爱AV| 国产成人亚洲精品狼色在线| 精品国产人成亚洲区| 亚洲中文无韩国r级电影| 亚洲精品国产电影| 亚洲国产精品自产在线播放| 国产亚洲福利一区二区免费看| 日韩精品亚洲专区在线观看| 伊人久久亚洲综合影院| 色噜噜的亚洲男人的天堂| 亚洲第一se情网站| 国产成人久久精品亚洲小说| 亚洲av手机在线观看| 亚洲国产综合精品一区在线播放| 在线亚洲精品视频| 亚洲综合激情另类专区| 亚洲中文字幕无码永久在线| 国产成人精品日本亚洲网站| 亚洲综合精品香蕉久久网97| 亚洲精品国产电影午夜| 亚洲ts人妖网站| 亚洲中文无码mv| jizzjizz亚洲日本少妇| 亚洲一级片内射网站在线观看| 亚洲真人无码永久在线| 亚洲视频中文字幕| 亚洲另类春色国产精品| 国产 亚洲 中文在线 字幕| 亚洲国产欧美一区二区三区| heyzo亚洲精品日韩| 77777亚洲午夜久久多人| 亚洲国产精品自在线一区二区| 亚洲色偷偷偷网站色偷一区| 亚洲综合无码无在线观看| 亚洲av日韩av永久在线观看|