图片展示 [ 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的使用.

  1. 目标

    • 以各种方式来呈现一张图片
    • 方式有很多, 目前只提供以下几种
      • 亮度變化
      • 卷动式或拖动式
      • 圆形展示
      • 方形展示
      • 随机展式
    • 全部图片的处理只能使Numpy (偶尔会有到list)
  2. 展示

  1. 代码及说明

    • 相关库的导入
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 协议》,转载必须注明作者和本文链接
Jason Yang
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!