程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python幫你完成美術作業——圖片轉灰度,字符畫,素描手繪風格

編輯:Python

Python圖像處理——圖片轉黑白,字符畫,手繪風

實現原理

用PIL,一個強大的python圖像處理庫。主要用到了Image。
終端下載命令:

pip install pillow

代碼

自己在東方明珠上拍到的黃浦江是多麼美麗!但想到這裡就回憶起兒時畫風景畫苦不堪言的感覺,心想一定要寫個程序幫自己完成美術作業。

圖片轉黑白

最簡單的一步,就是把彩色圖片轉為黑白圖片。

from PIL import Image #導入PIL庫
d = input("Img Directory:") #輸入要處理的圖片路徑
img = Image.open(d).convert('LA') #直接處理
img.save('greyscale.png') #保存圖片

怎麼樣?是不是很簡單?
用了自己在東方明珠上拍到的黃浦江,下面是效果圖:

圖片轉ascii

會了簡單的轉黑白,試試更難的轉ascii字符畫。代碼如下:

from PIL import Image #導入PIL 
#生成ascii圖的寬度和高度。建議和原圖比例類似。
WIDTH = 300
HEIGHT = 200
ascii_char = list("[email protected]%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ") #字符DPI(Dots Per Inch,每英寸點數)從高到低排序
#把彩色圖轉化為灰度圖,然後將256個灰度映射到70個字符上 
def get_char(r, g, b, alpha=256): #R紅G綠B藍A透明度
if alpha == 0: #空白像素返回空格
return ' '
length = len(ascii_char) #
gray = int(r*0.299 + g*0.587 + b*0.114) #計算灰度,3:6:1是比較靠譜的
unit = (256.0+1)/length
return ascii_char[int(gray/unit)]#不同的灰度對應著不同的字符 
d = input("Img Directory:") #輸入圖片路徑
img = Image.open(d) #打開文件
img = img.resize((WIDTH, HEIGHT), Image.NEAREST) #變得小一點好處理
txt = "" #臨時儲存字符畫信息
for i in range(HEIGHT): #遍歷每一個像素點
for j in range(WIDTH):
txt += get_char(*img.getpixel((j, i))) #獲得DPI最接近的字符
txt += '\n' #寫完一行就換行
with open("ascii_picture.txt",'w') as f: #寫到txt文件裡儲存
f.write(txt)

注意字體要用mono space,比如python IDLE默認的monaco字體,不要其它格式哦!不然會亂七八糟的
博主很懶沒有寫代碼自動修改寬高,小伙伴們可以自己動動腦子修改一下
計算灰度我也偷懶了,直接代數求值,但有很多其它更好用更准確的算法
感興趣的同學可以看看Gamma校正算法,轉化成物理光功率會更准確哦!
效果圖如下:

這是我截圖的,因為太密集所以出現了莫爾條紋。300x200還是有點離譜,可以用小一點的。但是還原還是很到位的!

圖片轉素描

到了這一點,python圖像處理功能看起來更強大了。代碼如下:

from PIL import Image #導入PIL
d = input("Img Directory:") #輸入圖片路徑
img = Image.open(d) #打開圖片
img_all = "素描" + d #存儲生成文件的位置
new = Image.new("L", img.size, 255) #創造新文件,大小和原來文件一樣
width, height = img.size #不偷懶了,獲得圖片大小
img = img.convert("L") #變成灰度,其實PIL用的也是簡單算法
Pen_size = int(input('Pensize:')) #畫筆大小
Color_diff = int(input('Color diffusion variable:')) #色差擴散器
#簡單說大概就是ps裡的顏色減淡模式啦……
#作用就是把色差較大的色塊交界線保留下來
for i in range(Pen_size + 1, width - Pen_size - 1):
for j in range(Pen_size + 1, height - Pen_size - 1):
originalColor = 255
lcolor = sum([img.getpixel((i - r, j)) for r in range(Pen_size)]) // Pen_size
rcolor = sum([img.getpixel((i + r, j)) for r in range(Pen_size)]) // Pen_size
if abs(lcolor - rcolor) > Color_diff:
originalColor -= (255 - img.getpixel((i, j))) // 4
new.putpixel((i, j), originalColor)
ucolor = sum([img.getpixel((i, j - r)) for r in range(Pen_size)]) // Pen_size
dcolor = sum([img.getpixel((i, j + r)) for r in range(Pen_size)]) // Pen_size
if abs(ucolor - dcolor) > Color_diff:
originalColor -= (255 - img.getpixel((i, j))) // 4
new.putpixel((i, j), originalColor)
acolor = sum([img.getpixel((i - r, j - r)) for r in range(Pen_size)]) // Pen_size
bcolor = sum([img.getpixel((i + r, j + r)) for r in range(Pen_size)]) // Pen_size
if abs(acolor - bcolor) > Color_diff:
originalColor -= (255 - img.getpixel((i, j))) // 4
new.putpixel((i, j), originalColor)
qcolor = sum([img.getpixel((i + r, j - r)) for r in range(Pen_size)]) // Pen_size
wcolor = sum([img.getpixel((i - r, j + r)) for r in range(Pen_size)]) // Pen_size
if abs(qcolor - wcolor) > Color_diff:
originalColor -= (255 - img.getpixel((i, j))) // 4
new.putpixel((i, j), originalColor)
new.save(img_all) #保存圖片

我的MacBook Air i5 1.6GHz芯片鬼哭狼嚎了不知道多久,還是沒辦法把原圖處理出來……
測試了下,處理一個256x256的圖也就幾秒鐘時間。小伙伴們可以先把圖片分辨率調低再處理
我選擇的畫筆大小是5,色差擴散器也是5,效果看起來還不錯。

好了,現在可以和其它小伙伴炫耀你的畫技了!

功能拓展

RGB轉灰度的算法有很多分類,可以搜一下有關算法,看看能不能做到准確地把灰度圖片還原成彩色圖片。本人試了試pillow的算法把灰度轉為彩色,發現還原出來的圖片人類還是不太能接受的

選用畫筆大小和色彩擴散器的時候可以自己嘗試下不同值出來的效果噢!

可以在畫素描的時候加一個自動調整圖片大小的代碼,這個問題交給各位來解決喽

其實畫素描的算法可以有很大提高,比如加一個隨機函數讓筆畫更加自然,或者干脆換一種算法讓它變得更快。相關資源網上有很多,就不再贅述了


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved