1#!/usr/bin/env python3
2
3# Copyright (c) 2021 Huawei Device Co., Ltd.
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import cv2
17import sys
18import os
19from datetime import datetime
20
21DEBUG = False
22DEBUG = True
23TARGET_WIDTH = 128
24TARGET_HEIGHT = 64
25PIXEL_PER_BYTE = 8
26WIDTH_BYTES = int(TARGET_WIDTH/PIXEL_PER_BYTE)
27PIXEL_THRESHOLD = 128.0
28
29# 将多个灰度像素打包到一个整数中
30def pack_pixels(pixels, threshold):
31    value = 0
32    for gray in pixels:
33        bit = 1 if gray >= threshold else 0 # 二值化
34        value = (value << 1) + bit # 多个二值化像素值拼接为一个字节值
35    return value
36
37frameCount = 0
38def resize_and_binarize_image(frame, width, height, threshold):
39    data = []
40    # count = 0 # for debug
41    start = datetime.now()
42    frame = cv2.resize(frame, (width, height)) # 缩放
43    frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY) # 转为灰度图
44    _, binary = cv2.threshold(frame, threshold, 255, cv2.THRESH_BINARY) # 二值化
45
46    for r in range(height):
47        for b in range(int(width / PIXEL_PER_BYTE)):
48            colStart = b * PIXEL_PER_BYTE
49            pixels = frame[r, colStart: colStart + PIXEL_PER_BYTE]
50            byte = pack_pixels(pixels, threshold)
51            data.append(byte)
52    if DEBUG:
53        global frameCount
54        cv2.imwrite(os.path.join('debug', str(frameCount) + '.png'), frame)
55        cv2.imwrite(os.path.join('debug', str(frameCount) + '-bin.png'), binary)
56        frameCount += 1
57        end = datetime.now()
58        print('time cost:', end - start)
59    return bytes(data)
60
61def convert_frame_to_bytes(frame):
62    return resize_and_binarize_image(frame, TARGET_WIDTH, TARGET_HEIGHT, PIXEL_THRESHOLD)
63
64def main():
65    if len(sys.argv) < 3:
66        print("Usage: {} input outdir [width] [height] [threshod]".format(sys.argv[0]))
67        exit(-1)
68
69    imgPath = sys.argv[1]
70    outdir = sys.argv[2]
71    width = len(sys.argv) > 3 and int(sys.argv[3]) or TARGET_WIDTH
72    height = len(sys.argv) > 4 and int(sys.argv[4]) or TARGET_HEIGHT
73    threshold = len(sys.argv) > 5 and int(sys.argv[5]) or PIXEL_THRESHOLD
74    imgFile = os.path.split(imgPath)[-1]
75    imgBase = imgFile.split('.')[-2]
76    codeFile = os.path.join(outdir, imgBase + '.c')
77    if not os.path.exists(outdir):
78        os.mkdir(outdir)
79
80    frame = cv2.imread(imgPath) # 加载图片
81    bitmap = resize_and_binarize_image(frame, width, height, threshold) # 转为目标格式的数组
82
83    with open(codeFile, 'w+') as f: # 输出到.c文件
84        f.write('const unsigned char {}_size[] = {{ {}, {} }};\n'.format(imgBase, width, height))
85        f.write('const unsigned char {}[] = {{\n'.format(imgBase))
86        for i in range(len(bitmap)):
87            v = bitmap[i]
88            sep = '\n' if (i+1) % (TARGET_WIDTH/PIXEL_PER_BYTE) == 0 else ' '
89            f.write('0x%02X,%s' % (v, sep))
90        f.write('};\n')
91    print(imgFile, '=>', codeFile, 'done!')
92
93if __name__ == "__main__":
94    main()
95