天天看點

python實作彩照轉黑白以及圖檔轉素描畫(1)彩照轉黑白(2)圖檔轉素描畫

python實作彩照轉黑白以及圖檔轉素描畫(1)彩照轉黑白(2)圖檔轉素描畫
python實作彩照轉黑白以及圖檔轉素描畫(1)彩照轉黑白(2)圖檔轉素描畫

(1)彩照轉黑白

# -*- coding: utf-8 -*-
"""
Created on Thu Mar 21 03:45:16 2019

@author: czh
"""
%clear
%reset -f
# In[*]
from PIL import Image
import numpy as np
import os
os.chdir('D:\\train\\cv')
# In[*]

from PIL import Image
import numpy as np
a = np.asarray(Image.open("AWM.jpg").convert('L'))#.convert是變成黑白的
grad = np.gradient(a)
grad
grad_x, grad_y = grad

# In[*]
b=255-a#在對應的顔色通道減去他自己變成黑白底片的效果
im=Image.fromarray(b.astype('uint8'))
im
# In[*]

c=(100/255)*a+150#區間變換,顔色比較淡的灰階的圖檔
im=Image.fromarray(c.astype('uint8'))

im
# In[*]
d=255*(a/255)**2#像素平方,顔色比較深的圖
im=Image.fromarray(d.astype('uint8'))
im           

複制

python實作彩照轉黑白以及圖檔轉素描畫(1)彩照轉黑白(2)圖檔轉素描畫
python實作彩照轉黑白以及圖檔轉素描畫(1)彩照轉黑白(2)圖檔轉素描畫

image.png

python實作彩照轉黑白以及圖檔轉素描畫(1)彩照轉黑白(2)圖檔轉素描畫

image.png

python實作彩照轉黑白以及圖檔轉素描畫(1)彩照轉黑白(2)圖檔轉素描畫

image.png

(2)圖檔轉素描畫

通過Numpy中的asarray函數将圖檔的灰階值以浮點型矩陣的形式存儲起來,再用gradient函數得出圖檔灰階值的梯度

# -*- coding: utf-8 -*-
"""
Created on Thu Mar 21 03:45:16 2019

@author: czh
"""
%clear
%reset -f
# In[*]
from PIL import Image
import numpy as np
import os
os.chdir('D:\\train\\cv')
# In[*]

from PIL import Image
import numpy as np
a = np.asarray(Image.open("StarryNight.jpg").convert('L'))#.convert是變成黑白的
grad = np.gradient(a)
grad
Out[37]: 
[array([[225. , 233. , 252. , ...,  18. ,  19. ,   2. ],
        [  0.5, 127. ,   3.5, ...,   5. ,  18. ,  17. ],
        [ 19.5,  10. , 126.5, ..., 103.5,   5.5,  29. ],
        ...,
        [  0. ,   0.5,   1. , ..., 126.5, 126.5, 126.5],
        [  4. ,   4.5,   5. , ...,   7. ,   7. ,   7. ],
        [  9. ,  10. ,   9. , ...,  13. ,  13. ,  13. ]]),
 array([[239. ,   0. ,  21. , ..., 113.5, 115.5, 243. ],
        [247. ,  13.5,  29. , ...,  25.5, 107.5, 226. ],
        [236. ,   3. ,  17. , ...,  62.5, 127.5, 241. ],
        ...,
        [242. , 116.5, 126. , ...,   4. ,   5. ,   5. ],
        [242. , 117.5, 127. , ...,   3. ,   5. ,   5. ],
        [243. , 117.5, 127. , ...,   5. ,   5. ,   5. ]])]           

複制

我們來觀察一下L矩陣,可以看出a是一個二維浮點型矩陣,是以它的梯度grad裡應該有兩個數組矩陣,分别對應兩層次元的梯度。現取最外層次元梯度為x方向的梯度值grad_x,取第二層次元梯度值為y方向梯度值grad_y

grad_x, grad_y = grad           

複制

這時我們已經取得了圖像的梯度值,就可以通過改變像素的梯度值來改變圖像的灰階變化,對圖像進行重構了。我們先設一個深度值depth,取值範圍為(0,100),然後利用深度調整x和y方向的梯度值。

我們使

grad_x = grad_x*depth/100.
grad_y = grad_y*depth/100.           

複制

深度值越小,重構後的圖像梯度值越小,即圖像灰階值變化越小,畫面線條越少,整體更顯潔淨。

比如當depth=1時:

python實作彩照轉黑白以及圖檔轉素描畫(1)彩照轉黑白(2)圖檔轉素描畫

反之,深度值越大,重構後的圖像梯度值越大,即圖像灰階值變化越大,畫面線條越多,整體更顯肮髒。比如當depth=100時

python實作彩照轉黑白以及圖檔轉素描畫(1)彩照轉黑白(2)圖檔轉素描畫

image.png

是以我們需要通過改變depth,找到最符合人類視覺遠近程度的深度值。經過多次測試發現,當深度值為10左右時,即圖像灰階梯度變為原來的10%左右時,畫面最接近手繪化效果。(當然,對于不同的圖檔,這個最佳深度值不一定相同)。在本文中我們取depth=10

制造光源效果

類似版畫的效果,這是因為此時的圖像還沒有光源效果,跟我們實際觀察事物的感覺不一樣,是以我們還需要為圖像制造光源效果。如圖,我們先假設一個光源位于圖像斜上方,設俯視角為el,方位角為az,則機關光線在x,y,z方向上的投影長度分别為:通過多次調整發現,當俯視角el=π/2.2, 方位角az=π/4時光照效果最好。(當然對于不同圖像兩個角度的選取不一定相同)

實作代碼為:

depth = 10                  # (0-100)
grad = np.gradient(a)             #取圖像灰階的梯度值
grad_x, grad_y =grad               #分别取橫縱圖像梯度值
grad_x = grad_x*depth/100.
grad_y = grad_y*depth/100.
A = np.sqrt(grad_x**2 + grad_y**2 + 1.)
uni_x = grad_x/A
uni_y = grad_y/A
uni_z = 1./A

vec_el = np.pi/2.2                   # 光源的俯視角度,弧度值
vec_az = np.pi/4.                    # 光源的方位角度,弧度值
dx = np.cos(vec_el)*np.cos(vec_az)   #光源對x 軸的影響
dy = np.cos(vec_el)*np.sin(vec_az)   #光源對y 軸的影響
dz = np.sin(vec_el)              #光源對z 軸的影響

b = 255*(dx*uni_x + dy*uni_y + dz*uni_z)     #光源歸一化           

複制

我們将這個過程叫做光源的歸一化

重構圖像

由于灰階值的選取範圍為(0,255),為了避免資料越界,需要将生成的灰階值裁剪至0-255之間

b = b.clip(0,255)           

複制

由新的灰階值重構圖像

im = Image.fromarray(gd.astype('uint8'))           

複制

其中uint8是一種資料類型。這時圖像的手繪化效果已經完成了

python實作彩照轉黑白以及圖檔轉素描畫(1)彩照轉黑白(2)圖檔轉素描畫
python實作彩照轉黑白以及圖檔轉素描畫(1)彩照轉黑白(2)圖檔轉素描畫
# -*- coding: utf-8 -*-
"""
Created on Thu Mar 21 03:45:16 2019

@author: czh
"""
%clear
%reset -f
# In[*]
from PIL import Image
import numpy as np
import os
os.chdir('D:\\train\\cv')
# In[*]

from PIL import Image
import numpy as np
a = np.asarray(Image.open("AWM.jpg").convert('L'))#.convert是變成黑白的
grad = np.gradient(a)
grad
grad_x, grad_y = grad

# In[*]
b=255-a#在對應的顔色通道減去他自己變成黑白底片的效果
im=Image.fromarray(b.astype('uint8'))
im
# In[*]

c=(100/255)*a+150#區間變換,顔色比較淡的灰階的圖檔
im=Image.fromarray(c.astype('uint8'))

im
# In[*]
d=255*(a/255)**2#像素平方,顔色比較深的圖
im=Image.fromarray(d.astype('uint8'))
im


# In[*]
a = np.asarray(Image.open("AWM.jpg").convert('L')).astype('float')
# In[*]
depth = 10                  # (0-100)
grad = np.gradient(a)             #取圖像灰階的梯度值
grad_x, grad_y =grad               #分别取橫縱圖像梯度值
grad_x = grad_x*depth/100.
grad_y = grad_y*depth/100.
A = np.sqrt(grad_x**2 + grad_y**2 + 1.)
uni_x = grad_x/A
uni_y = grad_y/A
uni_z = 1./A

vec_el = np.pi/2.2                   # 光源的俯視角度,弧度值
vec_az = np.pi/4.                    # 光源的方位角度,弧度值
dx = np.cos(vec_el)*np.cos(vec_az)   #光源對x 軸的影響
dy = np.cos(vec_el)*np.sin(vec_az)   #光源對y 軸的影響
dz = np.sin(vec_el)              #光源對z 軸的影響

b = 255*(dx*uni_x + dy*uni_y + dz*uni_z)     #光源歸一化
b = b.clip(0,255)

im = Image.fromarray(b.astype('uint8'))  #重構圖像
im
# In[*]
im.save("手繪.jpg")           

複制