Start_python’s diary

ふたり暮らし

アラフィフ夫婦のフリーランスプラン

Python GIFファイルをTwitterに張り付ける(GIFアニメーションに変換する)

はじめに

以前作成したGIFファイルがTwitterに張り付けると動きませんでした。原因を調べてみると色が最大256色しか使えないことがわかりました。

今回はすでに保存したGIFファイルをGIFアニメーションに変換するプログラムを作っていきます。

 

解説

色情報は、(0,0,0) ~ (255,255,255) の約1677万色(256×256×256)あります。

GIFアニメーションの場合は、最大256色(8×8×4)です。

=====ここから勘違い=====

なるほど。RGBなら赤が8段階、緑が8段階、青が4段階の256色か、と思ってしまいました。256を8で割って「32」。おそらく、0, 32, 64, 96, 128, 160, 192, 224, 255だと思いました。(この時点で9段階に気づいてない・・)

ここで32の倍数になるための計算式を考えました。

少数「x」を四捨五入した場合は、y = int((x + 0.5)//1) になるので

15捨16入の計算式は、y = int((x + 16)//32) * 32 でいいはず。

しかし・・・

=====ここまで勘違い=====

いろいろ調べてみると256色はどの色でも良いみたいです。「品質の良い減色ソフトを使用すれば、アニメーションしている時にはフルカラーと比較しても、さほど劣化を感じない」とのこと。

start-python.hateblo.jp

このときに減色処理やってました。

あとは減色処理の部分の組み込んで1コマずつ画像を256色にします。

結果がこちら

f:id:Start_python:20191227160017g:plain

このGIFならTwitterに張り付けることが出来ました。

元の画像がこちら

f:id:Start_python:20191227160129g:plain

256色でもほとんど変わっていないように見えます。逆になぜか減色処理した後のほうがファイルサイズが大きくなっていました。

 

プログラムのコード

import cv2
import numpy as np
from moviepy.editor import ImageSequenceClip


# 減色処理
def sub_color(src, K):
    # 次元数を1落とす
    Z = src.reshape((-1,3))
    # float32型に変換
    Z = np.float32(Z)
    # 基準の定義
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
    # K-means法で減色
    ret, label, center = cv2.kmeans(Z, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
    # UINT8に変換
    center = np.uint8(center)
    res = center[label.flatten()]
    # 配列の次元数と入力画像と同じに戻す
    return res.reshape((src.shape))


# 読み込み
gif = cv2.VideoCapture('sample.gif')
fps = gif.get(cv2.CAP_PROP_FPS)  # fpsは1秒あたりのコマ数

# 編集
images = []
i = 0
while True:
    is_success, img = gif.read()
    if not is_success:
        break

    # 減色処理
    img = sub_color(img, K=256)

    images.append(img)
    i += 1
    #print(i)  # あまりにも処理に時間がかかるので確認用

# 表示
cv2.namedWindow('test', cv2.WINDOW_AUTOSIZE)

for t in range(len(images)):
    cv2.imshow('test', images[t])
    cv2.waitKey(int(1000/fps))  # 1コマを表示するミリ秒

cv2.destroyAllWindows()

# 保存
images = np.array(images)
print(images.shape)
images = images[:, :, :, [2, 1, 0]]    # BGR <-> RGB
images = list(images)

clip = ImageSequenceClip(images, fps=fps)
clip.write_gif('test.gif')

 

まとめ

減色処理にかなり時間がかかります。今回のGIFで32コマだったのですが数分かかりました。減色を256色から16色に変えると画像は荒くなりますが早かったです。

ここからGIF編集ソフトを作っていきたいです。動画編集ソフトのように減色数も指定して、切り取りやトリミング、あと文字なども入れられるといいかもです。

 

 

保存ファイル

lesson76.py

 

 

文責:Luke