图片展示 [ Numpy 处理, Matplotlib 展示 ]
文件建立日期: 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 协议》,转载必须注明作者和本文链接