用树莓派和墨水屏做一个 mnist clock

效果

用树莓派和墨水屏做一个 mnist clock_第1张图片
epd29_mnist_clock.jpg

1. 墨水屏

  • 型号:微雪 2.9inch e-Paper Module, 带驱动板,8PIN

  • 工作电压:3.3V/5V

  • 通信接口:SPI

  • 分辨率:296 x 128

  • 显示颜色:黑、白

  • 局部刷新:0.3s

  • 全局刷新 :2s

  • 接线表:

墨水屏 8PIN 树莓派 40PIN 物理序号 备注
VCC 1 3.3V
GND 6 GND
DIN 19
CLK 23
CS 24
DC 22
RST 11
BUSY 18

2. 树莓派基本配置

  • 详细步骤见帮助文档: https://www.waveshare.net/wiki/2.9inch_e-Paper_Module
  • 程序源码在 github 也有: https://github.com/waveshare/e-Paper
  • 下载git clone https://github.com/waveshare/e-Paper.git --depth 1
  • 目录如下,有用的文件就几个:
├───Arduino
├───RaspberryPi&JetsonNano
│   ├───c
│   │   └─── ...
│   └───python
│       │   readme_rpi_CN.txt
│       │   setup.py
│       │   ...
│       │
│       ├───examples
│       │       epd_2in9bc_test.py  # 测试程序
│       │       ...
│       │
│       ├───lib
│       │   └───waveshare_epd
│       │           epd2in9.py      # 主逻辑
│       │           epdconfig.py    # 配置文件
│       │           __init__.py
│       │           ...
│       │
│       └───pic                
│               2in9.bmp            # 图片
│               Font.ttc            # 字体文件,文泉驿,含中文字体
│               ...
└─── ...

  • 运行测试程序
cd e-Paper/'RaspberryPi&JetsonNano'/
cd python/examples

sudo python3 epd_2in9bc_test.py

3. 处理 mnist 数据集,提取 index

  • 下载 mnist.npz
    https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz

  • 我们使用x_train的60000个数字,把0-9对应的序号(index),提取出来,保存到 mnist_index.json

import numpy as np
import json


img_rows, img_cols = 28, 28

# the data, split between train and test sets
path = 'mnist.npz'
with np.load(path) as f:
    x_train, y_train = f['x_train'], f['y_train']
    x_test, y_test = f['x_test'], f['y_test']

print('x_train.shape: {}, y_train.shape: {}'.format(x_train.shape, y_train.shape))
print('x_test.shape: {}, y_test.shape: {}'.format(x_test.shape, y_test.shape))

print(x_train[0], y_train[0])
print(x_test[0], y_test[0])


# 创建一个字典,keys 是0-9,values为空的list,后面将序号存进去
idx_dict = {}
for i in range(10):
    idx_dict[i] = []
print(idx_dict)

# 将序号存进去
for idx in range(60000):
    num = y_train[idx]
    idx_dict[num].append(idx)

    # if idx == 60: break

# print(idx_dict)

# 转为 json 格式, 保存
idx_json = json.dumps(idx_dict)
# print(idx_json)

with open('mnist_index.json', 'w') as f:
    json.dump(idx_dict, f)

# 读取 json 文件
# with open('mnist_index.json', 'r') as f:
#     data = json.load(f)
# print(data)

4. 先测试下用 opencv 显示时间

import numpy as np
import json
import random
import cv2
import time

# load mnist dataset
path = 'mnist.npz'
with np.load(path) as f:
    x_train, y_train = f['x_train'], f['y_train']
    x_test, y_test = f['x_test'], f['y_test']

with open('mnist_index.json', 'r') as f:
    idx_dict = json.load(f)

for i in range(10):
    print(i, len(idx_dict[str(i)]))


def get_mnist_num(num):
    idxs = idx_dict[str(num)]
    idx = random.choice(idxs)
    return x_train[idx]


gap = np.zeros((28, 10))
for i in [8, 9, 18, 19]:
    for j in [4,5,6,]:
        gap[i][j] = 255

last_time = [-1, -1, -1, -1, -1, -1]
last_imgs = np.zeros((6, 28, 28))

while True:
    now = time.localtime(time.time())
    sec, mnt, hour = now.tm_sec, now.tm_min, now.tm_hour
    s1, s2 = sec//10, sec%10
    m1, m2 = mnt//10, mnt%10
    h1, h2 = hour//10, hour%10
    now_time = [h1, h2, m1, m2, s1, s2]
    print(last_time, now_time)

    for i in range(6):
        if last_time[i] != now_time[i]:
            last_imgs[i] = get_mnist_num(now_time[i])
            last_time[i] = now_time[i]

    img = np.hstack((last_imgs[0], last_imgs[1], gap,
                     last_imgs[2], last_imgs[3], gap,
                     last_imgs[4], last_imgs[5]))

    cv2.imshow('num', img)
    # cv2.imwrite('mnist-clock.png', img)
    cv2.waitKey(100)

mnist-clock.png

5. 在墨水屏显示时间

详见 epd29_mnist_clock.py

# epd29_mnist_clock.py 

import sys
import os

import logging
import json
import numpy as np
import random
import time
import traceback

from PIL import Image, ImageDraw, ImageFont

from lib import epd2in9


logging.basicConfig(level=logging.DEBUG)
font = ImageFont.truetype('lib/Font.ttc', 18)

# load mnist dataset
with np.load('mnist.npz') as f:
    x_train, y_train = f['x_train'], f['y_train']
    x_test, y_test = f['x_test'], f['y_test']

with open('mnist_index.json', 'r') as f:
    idx_dict = json.load(f)

gap = np.ones((28, 10)) * 255
for i in [8, 9, 18, 19]:
    for j in [4,5,6,]:
        gap[i][j] = 0

def get_mnist_num(num):
    idxs = idx_dict[str(num)]
    idx = random.choice(idxs)
    return 255 - x_train[idx]


# === 0. init 
logging.info('epd2in9 Demo')

epd = epd2in9.EPD()
logging.info('init and Clear')
epd.init(epd.lut_full_update)
epd.Clear(0xFF)

# === 1. show date & time
logging.info('show date & time')

def YMD(draw, x1=10, y1=5, x2=160, y2=30):
    draw.rectangle((x1, y1, x2, y2), fill=255)
    draw.text((x1, y1), time.strftime('%Y-%m-%d  %a'), font = font, fill=0)

def HMS(draw, x1=180, y1=5, x2=280, y2=30):
    draw.rectangle((x1, y1, x2, y2), fill = 255)
    draw.text((x1, y1), time.strftime('%H:%M'), font = font, fill=0)
    
def MNIST(img, draw, mnist_img, x1=8, y1=30, x2=280, y2=120):
    draw.rectangle((x1, y1, x2, y2), fill = 255)
    mnist_img = Image.fromarray(mnist_img)
    mnist_img = mnist_img.resize((38*2*3, 28*3))
    img.paste(mnist_img, (x1, y1))

# partial update

time_image = Image.new('1', (epd.height, epd.width), 255)
time_draw = ImageDraw.Draw(time_image)

last_time = [-1, -1, -1, -1]
last_imgs = np.ones((4, 28, 28)) * 255

while (True):
    now = time.localtime(time.time())
    sec, mnt, hour = now.tm_sec, now.tm_min, now.tm_hour
    m1, m2 = mnt//10, mnt%10
    h1, h2 = hour//10, hour%10
    now_time = [h1, h2, m1, m2]
    print(f'{hour}:{mnt}:{sec}', last_time, now_time)

    if -1 in last_time or (mnt == 0 and sec < 5) :
        logging.info('partial update')
        epd.init(epd.lut_full_update)
        epd.Clear(0xFF)
        time.sleep(1)

        logging.info('partial update')
        epd.init(epd.lut_partial_update)
        epd.Clear(0xFF)
        YMD(time_draw)
        time.sleep(1)

    for i in range(4):
        if last_time[i] != now_time[i]:
            last_imgs[i] = get_mnist_num(now_time[i])
            last_time[i] = now_time[i]
            mnist_image = np.hstack((last_imgs[0], last_imgs[1], gap,
                                     last_imgs[2], last_imgs[3]))
            HMS(time_draw)  
            MNIST(time_image, time_draw, mnist_image)
            
            epd.display(epd.getbuffer(time_image))
            time.sleep(1)
    
    time.sleep(3)

# Clear        
logging.info('Clear...')
epd.init(epd.lut_full_update)
epd.Clear(0xFF)

# Sleep
logging.info('Goto Sleep...')
epd.sleep()
epd.Dev_exit()


所有的文件

把有用的几个文件拉出来放在一个文件夹里。

.
├── cv2_mnist_clock.py     # 测试用 opencv 显示时间
├── epd29_mnist_clock.py   # 在墨水屏显示时间
├── epd_2in9_test.py
├── lib
│ ├── epd2in9.py
│ ├── epdconfig.py
│ ├── Font.ttc
│ └── __init__.py
├── mnist_index_gen.py     # 提取序号(index)
├── mnist_index.json       # 保存序号(index),以 json 格式
└── mnist.npz              # mnist 原始数据集 

完整代码:

https://github.com/shenbo/mnist-clock

灵感

https://github.com/dheera/mnist-clock

你可能感兴趣的:(用树莓派和墨水屏做一个 mnist clock)