Skip to content

Instantly share code, notes, and snippets.

@tinytintoy
Forked from jitomesky/gifAnime2binImage.py
Last active September 19, 2017 04:06
Show Gist options
  • Save tinytintoy/31d9ab906eba80356d0ea553a7211ce6 to your computer and use it in GitHub Desktop.
Save tinytintoy/31d9ab906eba80356d0ea553a7211ce6 to your computer and use it in GitHub Desktop.
GIFアニメ画像を2値化してArduino用のヘッダファイルを出力するプログラム / 64x64 の白黒二値画像を ATtiny85 で使用するフォーク
#!/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