6 月 30 日是 Beyond黃家駒逝世周年紀(jì)念日,對(duì)于編程獅W3Cschool小編和廣大70、80甚至90年代的人來(lái)說(shuō)“Beyond”可以是一種情結(jié)可以是一種回憶也可以是一種精神上的能量,《再見(jiàn)理想》《Amani》《海闊天空》《光輝歲月》一首首膾炙人口的歌曲,鼓舞著一代人在逆境中成長(zhǎng)。許多樂(lè)迷曾經(jīng)說(shuō)過(guò),喜歡 Beyond 就是在紀(jì)念自己。紀(jì)念黃家駒,也像是在紀(jì)念自己的青春,家駒不僅是一代人的記憶,沒(méi)有什么能夠比 Beyond 的名字更能概括 Be-yond ———超越。今天我們來(lái)看看會(huì) Python 編程的樂(lè)迷是如何致敬黃家駒的吧~
- 作者:薛定諤的殼
- 原文:【有點(diǎn)意思】Python Turtle+PIL ‘畫圖’之黃家駒
- 來(lái)源:CSDN博客
最終效果圖:
思路:
運(yùn)用 PIL 的 Image 模塊與 turtle 模塊讀取并重新畫出圖像
就是讀取一張有人像的圖片,然后通過(guò)循環(huán)對(duì)比,記錄下人各行人像的像素坐標(biāo),然后再通過(guò) turtle 畫出大概的人像輪廓。
Image 模塊有直接顯示輪廓的函數(shù),而且對(duì)于從圖象中識(shí)別出人像,這個(gè)對(duì)于小白太難了,所以就選取黑白或者是色彩單一、含人像的圖像來(lái)識(shí)別。
步驟:
步驟 | 操作 | 用到的庫(kù) |
---|---|---|
1 | 讀取圖像,通過(guò)遍歷每一行像素記錄并對(duì)比,得到畫圖所需的人像‘坐標(biāo)’ | PIL |
2 | 根據(jù)所得到的坐標(biāo),調(diào)用 turtle 庫(kù)畫圖 | turtle |
第一步,讀取圖片,獲得畫圖坐標(biāo)
讀取圖片如上,獲取坐標(biāo)是逐行遍歷像素的過(guò)程,便利時(shí)記錄每一行像素中非白色(白色為背景色)的像素條的始末坐標(biāo)(X1
,X2
)。
對(duì)比時(shí),當(dāng)前像素與同行的下一個(gè)像素進(jìn)行比較,如果兩個(gè)像素值不同,且有一像素為背景色,那么記錄非背景色的橫坐標(biāo)。
記錄時(shí),整張圖的數(shù)據(jù)暫時(shí)保存在一個(gè)列表中,該列表由 n 個(gè)列表組成(n 為圖像像素行數(shù)),這 n 個(gè)列表存著對(duì)應(yīng)行的所有非背景色像素條的始末坐標(biāo)。
源碼:
from PIL import Image
import turtle as t
def get_lst(img_path):
imgf = Image.open(img_path) # 讀取圖像
global size
print(size:= imgf.size) # 獲取圖像尺寸/大小
pix = imgf.load()
lst = [[] for i in range(size[1])] # 構(gòu)造空列表
for y in range(0, size[1]): # 從第一行開(kāi)始循環(huán)
index = 0
for x in range(0, size[0]-1): # 循環(huán)第y行的每一個(gè)像素
# 如果當(dāng)前像素與下一個(gè)像素值不同且兩者有一為背景色,則記錄坐標(biāo)
if pix[x, y] != pix[x+1, y] and (255, 255, 255, 255) in [pix[x, y], pix[x+1, y]]:
if index == 0: # index值為0說(shuō)明是像素條起始坐標(biāo)
lst[y].append([x+1, ])
index += 1
else: # index值為1說(shuō)明記錄的是像素條結(jié)束坐標(biāo)
lst[y][-1].append(x)
index = 0
return lst
第二步,畫圖
得到了每一個(gè)像素條的始末坐標(biāo)后,就可以逐行畫圖了
源碼
def paint(lst):
fontc = 'whitesmoke' # 右邊字的顏色
manc = 'black' #'dimgrey' 人像的顏色
t.setup(width=size[0]+40, height=size[1]) # 繪圖窗口大小
t.screensize(bg='oldlace') # 畫布背景色
t.bgpic(r'c:\\users\\pxo\\desktop\\bg.png') # 畫布背景圖
t.speed(333) #畫畫速度 據(jù)說(shuō)范圍[1,10]
for y in range(0, size[1]):
# 遍歷每一行
t.pencolor(manc)
for line in lst[y]:
# 遍歷每一個(gè)像素條
if line[0] > 364 and 144 < y < 495: # 這個(gè)是判斷是否是右邊的字
t.pencolor(fontc)
# 下面是畫像素條
t.penup()
t.goto(line[0]-size[0]//2, (size[1]-y)-size[1]//2)
t.pendown()
t.goto(line[1]-size[0]//2, (size[1]-y)-size[1]//2)
t.mainloop()
開(kāi)始:
if __name__ == '__main__':
img_path = r'c:\\users\\pxo\\desktop\\jh.png' # 圖像地址
lst = get_lst(img_path)
paint(lst)
附上一張帶背景圖的效果
這樣就實(shí)現(xiàn)了使用 Python Turtle+PIL 繪制黃家駒效果。如果還不過(guò)癮以下提供了另一種思路,具體查看源碼注釋↓
隨機(jī)線條實(shí)現(xiàn)方式:
源碼:
from PIL import Image
import turtle as t
from random import choice
def get_lst(img_path):
imgf = Image.open(img_path)
global size
print(size:= imgf.size)
pix = imgf.load()
lst = [[] for i in range(size[1])]
for y in range(0, size[1]):
index = 0
for x in range(0, size[0]-1):
if pix[x, y] != pix[x+1, y] and (255, 255, 255, 255) in [pix[x, y], pix[x+1, y]]:
if index == 0:
lst[y].append([y, x+1, ]) # 這里在每一個(gè)像素條的數(shù)據(jù)中加入了其縱坐標(biāo)y
index += 1
else:
lst[y][-1].append(x)
index = 0
# 這里也改了,返回的數(shù)據(jù)列表的子元素是所有單獨(dú)的像素條,而不是某一行像素條的總和
lt = []
for i in lst:
for j in i:
if j:
lt.append(j)
return lt
def paint(lst):
fontc = 'darkorange'
manc = 'black' #'dimgrey'
t.setup(width=size[0]+40, height=size[1]+40)
t.screensize(bg='oldlace')
#t.bgpic(r'c:\\users\\pxo\\desktop\\bg.png')
t.speed(330)
cnt = len(lst)
lt = [i for i in range(cnt)] # 弄一個(gè)種子列表,理解為存取位置
flst = []
for i in range(cnt):
del lt[lt.index(index:=choice(lt))] #獲取并刪除一個(gè)隨機(jī)位置
line = lst[index] # 從所有線條中得到一條隨機(jī)線條(像素條)
y = line[0]
x1, x2 = line[1], line[2]
t.pencolor(manc)
if x1 > 364 and 144 < y < 495:
flst.append(line)
continue
t.penup()
t.goto(x1-size[0]//2, (size[1]-y)-size[1]//2)
t.pendown()
t.goto(x2-size[0]//2, (size[1]-y)-size[1]//2)
new_flst = sorted(flst[:-80], reverse=True)
for line in new_flst:
y = line[0]
x1, x2 = line[1], line[2]
t.pencolor(fontc)
t.penup()
t.goto(x1-size[0]//2, (size[1]-y)-size[1]//2)
t.pendown()
t.goto(x2-size[0]//2, (size[1]-y)-size[1]//2)
t.hideturtle()
t.mainloop()
if __name__ == '__main__':
img_path = r'c:\\users\\pxo\\desktop\\jh.png'
lst = get_lst(img_path)
paint(lst)
附幾張畫到一半的圖
以上就是編程獅(w3cschool.cn)小編為你整理的《程序員如何使用 Python Turtle+PIL 畫圖繪制黃家駒?【附源碼】》全部?jī)?nèi)容,更多 IT 編程技術(shù)文章請(qǐng)關(guān)注W3C技術(shù)頭條。
如果你也想擁有這種能力,你也許需要先掌握以下技能: