檔案建立日期: 2020/03/14
最後修訂日期: 2020/04/05 內容格式調整
相關軟體資訊:
Win10 | Python 3.7.6 | Requests 2.23.0 | Matplotlib 3.2.0 | Numpy 1.18.1 | Pillow 7.0.0 |
說明: 本文請隨意引用或更改, 只須標示出處及作者, 作者不保證內容絶對正確無誤, 如造成任何後果, 請自行負責.
標題: 圖片展示 [ Numpy處理, Matplotlib展示 ]
PIL (Pillow) 可以用來作圖片的處理, 因為要處理的不是靜態的圖片, 也不太會動到圖片的內容, 再加上對Numpy有點生疏, 因此藉由Numpy來作整個片的分割處理, 讓自己再更深入瞭解Numpy的使用.
目標
- 以各種方式來呈現一張圖片
- 方式有很多, 目前只提供以下幾種
- 亮度變化
- 捲動式或拖動式
- 圓形展示
- 方形展示
- 隨機展式
- 全部圖片的處理只能使Numpy (偶爾會有到list)
展示
程式碼及說明
- 相關庫的匯入
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
from time import sleep
import random
import requests
from io import BytesIO
圖片由黑到顯示
陣列中的值 (也就是R, G B三色) 按各點顏色的比例從 (0, 0, 0) 到 該點的 (R, G, B), 這樣只會改變亮度, 不會改變色.
def black_to_show(array, interval, mode=0):
for i in range(interval, -1, -1):
yield array-array*i/interval
- 以方形的方式, 顯示圖片, 共有8種模式, 主要是依照每個點的索引值來作方形的判斷, 再以boolean值來作為圖片的陣列索引. 函式的內容雖長, 但8種模式的內容大同小異.
def box(array, interval, mode):
h, w = array.shape[0], array.shape[1]
half = int(interval/2)
y0 = np.linspace(0, array.shape[0], interval)
x0 = np.linspace(0, array.shape[1], interval)
filter = np.indices(array.shape[0:2])
im_blank = np.full(array.shape, 255, dtype=np.float)
if mode == 0:
for x, y in zip(x0, y0):
check = np.logical_and(filter[0]<=y, filter[1]<=x)
im_blank[check] = array[check]
yield im_blank
elif mode == 1:
for x, y in zip(x0[::-1], y0[::-1]):
check = np.logical_and(filter[0]>=y, filter[1]>=x)
im_blank[check] = array[check]
yield im_blank
elif mode == 2:
for x, y in zip(x0, y0[::-1]):
check = np.logical_and(filter[0]>=y, filter[1]<=x)
im_blank[check] = array[check]
yield im_blank
elif mode == 3:
for x, y in zip(x0[::-1], y0):
check = np.logical_and(filter[0]<=y, filter[1]>=x)
im_blank[check] = array[check]
yield im_blank
elif mode == 4:
for x, y in zip(x0[half:], y0[half:]):
check = np.logical_and(
np.logical_and(h-y<=filter[0], filter[0]<=y),
np.logical_and(w-x<=filter[1], filter[1]<=x))
im_blank[check] = array[check]
yield im_blank
elif mode == 5:
for x, y in zip(x0[half:], y0[half:]):
check = np.logical_or(
np.logical_and(h-y<=filter[0], filter[0]<=y),
np.logical_and(w-x<=filter[1], filter[1]<=x))
im_blank[check] = array[check]
yield im_blank
elif mode == 6:
for x, y in zip(x0[::-1][:half], y0[::-1][:half]):
check = np.logical_or(
np.logical_or(filter[0]>=y, filter[0]<=h-y),
np.logical_or(filter[1]>=x, filter[1]<=w-x))
im_blank[check] = array[check]
yield im_blank
elif mode == 7:
for x, y in zip(x0[::-1][:half], y0[::-1][:half]):
check = np.logical_and(
np.logical_or(filter[0]>=y, filter[0]<=h-y),
np.logical_or(filter[1]>=x, filter[1]<=w-x))
im_blank[check] = array[check]
yield im_blank
- 圓形展示, 分為由外向內或由內向外兩種. 處理方式以各點至中心點的距離作判斷, 預先計算所有點的距離, 再以boolean陣列作為圖片陣列的索引.
def circle(array, interval, mode=0):
h, w = array.shape[0]/2, array.shape[1]/2
value = (((np.arange(array.shape[0])-h)**2)[:, None] +
(np.arange(array.shape[1])-w)**2)
m = np.max(value)
radius = np.linspace(0, m, interval)
im_blank = np.full(array.shape, 255, dtype=np.float)
if mode == 0:
for r in radius:
im_blank[value<=r,:] = im_np[value<=r,:]
yield im_blank
else:
for r in radius[::-1]:
im_blank[value>=r,:] = im_np[value>=r,:]
yield im_blank
- 分塊隨機顯示, 簡單的圖片子陣列替換
def random_block(array, interval, mode=0):
im_blank = np.full(array.shape, 255, dtype=np.float)
y = np.linspace(0, array.shape[0], interval+1).astype(np.int)
x = np.linspace(0, array.shape[1], interval+1).astype(np.int)
where = [(i, j) for i in range(interval) for j in range(interval)]
np.random.shuffle(where)
for i, j in where:
im_blank[y[j]:y[j+1], x[i]:x[i+1]] = array[y[j]:y[j+1], x[i]:x[i+1]]
yield im_blank
- 捲動式的圖片展示, 這裡也有八種方式, 四個方向 (上, 下, 左, 右), 以及拖動或顯示. 這部份更簡單了, 就只是圖片的子陣列代入.
def scroll(array, interval, mode=0):
im_blank = np.full(array.shape, 255, dtype=np.float)
if mode < 4:
for i in np.linspace(1, array.shape[1]-1, interval):
if mode == 0:
im_blank[:, :int(i)] = array[:, :int(i)]
elif mode == 1:
im_blank[:, :int(i)] = array[:, -int(i):]
elif mode == 2:
im_blank[:, -int(i):] = array[:, :int(i)]
elif mode == 3:
im_blank[:, -int(i):] = array[:, -int(i):]
yield im_blank
else:
for i in np.linspace(1, array.shape[0]-1, interval):
if mode == 4:
im_blank[:int(i)] = array[:int(i)]
elif mode == 5:
im_blank[:int(i)] = array[-int(i):]
elif mode == 6:
im_blank[-int(i):] = array[:int(i)]
elif mode == 7:
im_blank[-int(i):] = array[-int(i):]
yield im_blank
圖片由白到顯示
陣列中的值 (也就是R, G B三色) 按各點顏色的比例從 (255, 255, 255) 到 該點的 (R, G, B), 這樣只會改變亮度, 不會改變色.
def white_to_show(array, interval, mode=0):
for i in range(interval, -1, -1):
yield array+i*(255 - array)/interval
顯示函式
呼叫相關的函式, 設定間隔及模式, 因為有時間的關係, 所以各函式都採用 yield 來迭代輸出, Matplot 中的 set_data 可以不用多作已畫影像的刪除, draw_idle 函式用來更新, pause 用來暫停以更新圖片.
def show(func, array, interval, mode=0):
for data in func(array, interval, mode):
im_plt.set_data(np.clip(data.astype(int), 0, 255))
fig.canvas.draw_idle()
plt.pause(0.001)
圖片的載入
為免圖片檔案需另外存在, 直接從網頁上下載一張圖片, 供全程使用.
url = 'https://p2.bahamut.com.tw/WIKI/82/00365182.JPG'
response = requests.get(url)
im = Image.open(BytesIO(response.content))
im_np = np.array(im, dtype=np.float)
- Matplotlib 初使化, 主要還是隱藏座標軸
fig,ax = plt.subplots(1,1)
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
im_plt = ax.imshow(np.full(im_np.shape, 255))
- 顯示各函式的展示功能
show(white_to_show, im_np, 10)
show(black_to_show, im_np, 10)
for mode in range(8):
show(scroll, im_np, 10, mode=mode)
show(random_block, im_np, 5)
show(circle, im_np, 20, mode=0)
show(circle, im_np, 20, mode=1)
for mode in range(4, 8):
show(box, im_np, 20, mode=mode)
- 關閉繪圖介面
plt.close()
本作品採用《CC 協議》,轉載必須註明作者和本文連結