• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2import cv2
3import sys
4import os
5from datetime import datetime
6
7DEBUG = False
8DEBUG = True
9TARGET_WIDTH = 128
10TARGET_HEIGHT = 64
11PIXEL_PER_BYTE = 8
12WIDTH_BYTES = int(TARGET_WIDTH/PIXEL_PER_BYTE)
13PIXEL_THRESHOLD = 128.0
14
15# 将多个灰度像素打包到一个整数中
16def pack_pixels(pixels, threshold):
17    value = 0
18    for gray in pixels:
19        bit = 1 if gray >= threshold else 0 # 二值化
20        value = (value << 1) + bit # 多个二值化像素值拼接为一个字节值
21    return value
22
23frameCount = 0
24def resize_and_binarize_image(frame, width, height, threshold):
25    data = []
26    # count = 0 # for debug
27    start = datetime.now()
28    frame = cv2.resize(frame, (width, height)) # 缩放
29    frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY) # 转为灰度图
30    _, binary = cv2.threshold(frame, threshold, 255, cv2.THRESH_BINARY) # 二值化
31
32    for r in range(height):
33        for b in range(int(width / PIXEL_PER_BYTE)):
34            colStart = b * PIXEL_PER_BYTE
35            pixels = frame[r, colStart: colStart + PIXEL_PER_BYTE]
36            byte = pack_pixels(pixels, threshold)
37            data.append(byte)
38    if DEBUG:
39        global frameCount
40        cv2.imwrite(os.path.join('debug', str(frameCount) + '.png'), frame)
41        cv2.imwrite(os.path.join('debug', str(frameCount) + '-bin.png'), binary)
42        frameCount += 1
43        end = datetime.now()
44        print('time cost:', end - start)
45    return bytes(data)
46
47def convert_frame_to_bytes(frame):
48    return resize_and_binarize_image(frame, TARGET_WIDTH, TARGET_HEIGHT, PIXEL_THRESHOLD)
49
50def main():
51    if len(sys.argv) < 3:
52        print("Usage: {} input outdir [width] [height] [threshod]".format(sys.argv[0]))
53        exit(-1)
54
55    imgPath = sys.argv[1]
56    outdir = sys.argv[2]
57    width = len(sys.argv) > 3 and int(sys.argv[3]) or TARGET_WIDTH
58    height = len(sys.argv) > 4 and int(sys.argv[4]) or TARGET_HEIGHT
59    threshold = len(sys.argv) > 5 and int(sys.argv[5]) or PIXEL_THRESHOLD
60    imgFile = os.path.split(imgPath)[-1]
61    imgBase = imgFile.split('.')[-2]
62    codeFile = os.path.join(outdir, imgBase + '.c')
63    if not os.path.exists(outdir):
64        os.mkdir(outdir)
65
66    frame = cv2.imread(imgPath) # 加载图片
67    bitmap = resize_and_binarize_image(frame, width, height, threshold) # 转为目标格式的数组
68
69    with open(codeFile, 'w+') as f: # 输出到.c文件
70        f.write('const unsigned char {}_size[] = {{ {}, {} }};\n'.format(imgBase, width, height))
71        f.write('const unsigned char {}[] = {{\n'.format(imgBase))
72        for i in range(len(bitmap)):
73            v = bitmap[i]
74            sep = '\n' if (i+1) % (TARGET_WIDTH/PIXEL_PER_BYTE) == 0 else ' '
75            f.write('0x%02X,%s' % (v, sep))
76        f.write('};\n')
77    print(imgFile, '=>', codeFile, 'done!')
78
79if __name__ == "__main__":
80    main()
81