-
-
Save tinytintoy/31d9ab906eba80356d0ea553a7211ce6 to your computer and use it in GitHub Desktop.
GIFアニメ画像を2値化してArduino用のヘッダファイルを出力するプログラム / 64x64 の白黒二値画像を ATtiny85 で使用するフォーク
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
import numpy as np | |
import sys | |
sys.path.append('/usr/local/lib/python2.7/site-packages') | |
import cv2 | |
from PIL import Image, ImageSequence, ImageDraw | |
import time | |
import unittest | |
width = 64 | |
height = 64 | |
def cvImageToBinaryString(cvImage): | |
row = 0 | |
col = 0 | |
bit = 0 | |
# バイナリの格納先を指定 | |
ba = np.zeros((height/8, width), dtype=np.uint8) | |
# 要素数が正しいかチェック | |
assert len(ba) == height / 8, "ba height missmuch" | |
assert len(ba[0]) == width, "ba width missmuch" | |
# TODO: 全部0か調べる | |
PIL_data = Image.fromarray(cvImage).convert('1') | |
# PIL_data.show() | |
# 0 or 1 の1行バイナリ列に変換 | |
b = list([0 if x else 1 for x in PIL_data.getdata()]) | |
binaryString = "" | |
for i in range(width * height): | |
val = b[i] | |
ba[row, col] |= val << bit | |
# next col | |
col += 1 | |
# next bit | |
if col >= width: | |
col = 0 | |
bit += 1 | |
# next data row | |
if bit >= 8: | |
bit = 0 | |
for x in range(width): | |
s = "%x" % ba[row, x] | |
assert "0x" + s == hex(ba[row, x]), "hex convert failture" | |
# Do some formatting | |
if len(s) > 2: | |
s = s[-2:] | |
while len(s) < 2: | |
s = "0" + s | |
binaryString += "0x" + s + "," | |
binaryString += "\n" | |
row += 1 | |
# 最後のコロンを削除 | |
binaryString = binaryString[:-2] | |
return binaryString | |
def gif89a_alpha_merge(now_frame, pre_frame): | |
nowf_rgba = now_frame.convert('RGBA') | |
pref_rgba = pre_frame.convert('RGBA') | |
img = Image.alpha_composite(pref_rgba, nowf_rgba) | |
return img | |
if __name__ == '__main__': | |
name = sys.argv[1] | |
im = Image.open(name) | |
binStr_List = [] | |
bframe = im.convert('RGB') | |
for fn,f in enumerate(ImageSequence.Iterator(im)): #using the class from the PIL handbook | |
# gif89aなら透過色の処理を入れる | |
if im.info['version'] == "GIF89a" and fn > 0: | |
f = gif89a_alpha_merge(f, bframe) | |
PIL_data = f.convert('RGB') | |
bframe = PIL_data | |
# PILからOpenCVに変換 | |
OpenCV_RGB = np.asarray(PIL_data) | |
# 色をRGB から BGRに変換 | |
OpenCV_BGR = cv2.cvtColor(OpenCV_RGB, cv2.COLOR_RGB2BGR) | |
# グレイスケール化 | |
gray = cv2.cvtColor(OpenCV_BGR, cv2.COLOR_BGR2GRAY) | |
# リサイズする | |
# 先にリサイズしたほうが、二値化後が綺麗 | |
gray_resized = cv2.resize(gray, (width, height)) | |
# ガウス分布を用いたしきい値より二値化 | |
#resize_first = cv2.adaptiveThreshold(gray_resized,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2) | |
retval, resize_first = cv2.threshold(gray_resized,254,255,cv2.THRESH_BINARY_INV) | |
binStr_List.append( cvImageToBinaryString(resize_first) ) | |
# 表示 | |
cv2.imshow('frame', OpenCV_BGR ) | |
cv2.imshow('binary_mini', resize_first ) | |
time.sleep(0.1) | |
if cv2.waitKey(1) & 0xFF == ord('q'): | |
break | |
cv2.destroyAllWindows() | |
# ファイル書き込み | |
f = open("gifHeader.h", 'w') | |
f.write('#include "Arduino.h"' + "\n") | |
f.write('#include <avr/pgmspace.h>' + "\n\n") | |
f.write("#define PICTURE_ENTRY " + str(len(binStr_List)) + "\n") | |
f.write("#define PICTURE_SIZE " + str(len(binStr_List[0].split(','))) + "\n\n") | |
for i,binStr in enumerate(binStr_List): | |
f.write("PROGMEM const unsigned char gifAnime_" + str(i) + "[] = { \n") | |
# f.write(" { \n ") | |
f.write(binStr) | |
# f.write("\n }") | |
f.write(",\n" if i != (len(binStr_List) - 1) else "\n") | |
f.write("};\n\n") | |
f.write("const static unsigned char *gifAnimePointer[] = { \n") | |
for i in range(len(binStr_List)): | |
f.write(" gifAnime_" + str(i) + ",\n") | |
f.write("};\n") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment