日本で人気のSNS「LINE」はスタンプを自作し販売することが出来る特色があります。ここではスタンプ画像を自作する時に面倒なサイズ合わせ、透過処理、枠処理を自動化するPythonコードを紹介します(実際に公式の審査承認まで行きました!)。
こんにちは。wat(@watlablog)です。ここでは適当な画像からLINEのスタンプ画像フォーマットに自動変換してくれるPythonコードを紹介します!変換画像を公式に申請し、承認・リリース実績もあるのでこれから作成する方の参考になると思います!
ここではPythonを使ったLINEスタンプフォーマット変換方法を説明していますが、もしまだPythonを触ったことが無い方は「Python入門!初心者がインストールから学習開始するまでの3ステップ」という記事でPythonインストールから実行方法までを説明しています。
是非これを機にPythonプログラマとして色々なプログラムを作ってみて下さい!
審査を合格したスタンプの例
ここで紹介しているPythonコードで変換した画像を試しにLINEクリエイターズマーケットで申請してみた所、なんと一発で合格してしまいました!
以下リンクがそのページです(せっかく作ったので使って頂けると今後の記事作成モチベーションが爆上がりします!)。
スタンプページ外部リンク:https://line.me/S/sticker/11074713
ちなみにこのスタンプはG検定取得を目指して機械学習・ディープラーニングを勉強していた時に作ったので、かなり理系向けです。
数十枚の画像フォーマットを変換するのはハードルが高いと思いますが、是非ここで紹介しているプログラムで楽をしてみて下さい!
LINEスタンプ画像の作成ルール
画像サイズ/余白/背景透過
スタンプを作る前に、作成する時のルールをよく把握しましょう。
LINE公式のスタンプ作成ガイドラインによると、スタンプ作成に必要な画像はメイン画像が1枚、スタンプ(sticker)画像が指定枚(8, 16, 24, 32, 40枚からの選択)、トークルームタブ画像が1枚必要とのこと。
そして画像種類毎にサイズ(偶数)に関するルールが決まっており、さらにイラストの背景は透過処理(Alphaチャンネルの値が0)が必要、余白は10[px(ピクセル)]くらい(曖昧!)必要、画像形式はPNGとあります。
図にすると以下のように読み取れました。
今回はこのフォーマットにするためのPythonコードを作成していきます。
※解像度dpi(dots per inch)72[dpi]以上、カラーモードはRGBというのは今回紹介する方法で作成する分には普通にクリアできると思うので省略します。
イラストの内容
イラストは何でも良いわけではなく、LINE公式ガイドラインに記載の以下を守る必要があります。
・日常会話、コミュニケーションで使いやすい物
・表情、メッセージ、イラストが分かりやすくシンプルなもの
そして以下のNG項目に該当してはいけません。
・日常会話で使用しにくいもの(例:物体、景色など)
・視認性が悪いもの
・スタンプ全体のバランスを著しく欠いているもの
・公序良俗に反するもの未成年者の飲酒喫煙を想起するもの、性的表現、暴力的表現、ナショナリズムを煽るもの
・宣伝目的
・個人情報の記載
・ロゴのみのイラスト
・著作権に侵害しているもの
今回はPythonコードの動作確認も兼ね、実際に公式の審査をパスすることを目指します。そして以下のような完全オリジナル画像を24枚作成しました。
技術系プログラマは煽ってるかも知れませんが、上記NG項目にあるナショナリズム等は煽っていませんし、日常会話でも使いやすいので多分OKでしょう。
プログラムでフォーマットを変換するメリット
一般的にLINEスタンプを作っている人は、PhotoShopやGIMP、もしくはペイントに代表される汎用的な画像処理ソフトを使っていることと思います。
しかしLINEスタンプは最大で40枚ほどの画像コンテンツを必要とします。
サイズ調整、背景透過、余白の追加といった処理を数十枚分やるのは大変面倒です。
できれば適当に作成した画像に対し、プログラムで一括変換できればスタンプ作成作業の効率がグッと上がることでしょう。
フォーマット変換という退屈な作業をPythonにやらせると、クリエイターはコンテンツのクオリティに注力できるというのが最大のメリットです。
LINEスタンプフォーマットへ自動変換するPythonコード
事前準備
スタンプ画像の用意
まずは何はともあれ、元となる画像が必要です。画像は上記ガイドラインに沿って自分で作成しましょう。
ここではスタンプ画像として、実際にトークで使用する複数枚の画像をこしらえます。
今回はPythonコードの動作検証なので、パワポのオートシェイプを使って適当にキャラクターとメッセージを作成しました。このパワポイラストをWindowsであればSnipping Tool等を使ってこれまた適当に画像切り出しします。
この時点で画像のサイズは個々でばらばらです(見た目に正方形っぽくなってる程度でOK、形式もJPGやBMP、PNGのどれでもOK)。
またスタンプ画像にはメッセージを添えることが多いと思いますが、フォントにも著作権があるのでLINEスタンプとして使って良いものを選びましょう。
今回は「外部サイト:LINEスタンプに使えそうな無料フォント36選」を参考にさせて頂きました。
以下のように24枚作成しました(疲れた…40枚は無理)。クオリティに関するツッコミは禁止です。本質はあくまで変換コードなので。
ここでのファイル名は何でも良いですが、LINEスタンプ画像は01~40の番号のみという指定があります。このスタンプ画像に関してはプログラムで連番を作ります。順番を指定したい時だけ名前の先頭に番号を付けておきましょう。
メイン画像の用意
メイン画像は別途作成しても良いですが、サイズが正方形(240×240)なので上記スタンプ画像から1つ選びました。
但し、ファイル名をmainにしておきます。
トークルームタブ画像の用意
トークルームタブ画像はLINEでスタンプのパッケージを選択する時に表示されるものです。サイズが(縦74、横96)と指定されているので、やや横長の切り出し画像を別途用意しましょう。
今回はディープラーニングフレームワークのPyTorchからインスピレーションを得た以下の画像を適当にやや横長切り出ししました。
フォルダ構成とフォルダの中身
コードを実行する前に、Pythonコード(.pyファイル)があるフォルダに以下の3つのフォルダを作成し、それぞれのフォルダに対応ファイルを入れます。
・main(mainと名前を付けたメイン画像を入れる)
・sticker(複数枚のスタンプ画像を入れる)
・tab(tabと名前を付けたトークルームタブ画像を入れる)
Pythonコード
Pythonの全コードを以下に示します。詳細はコメントに記載しましたが、ポイントは実行結果の後で説明します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
''' 2020/3/15:Created by WATLAB LINEスタンプフォーマット変換プログラム (適当な画像の白色画素を透過処理し、規定の大きさにリサイズ、 画像の周りに透過画素をパディングするだけ。) ''' import cv2 import numpy as np import glob import os # LINEスタンプ申請用画像を作成する関数 def create_sticker(dir, w, h): path = glob.glob(dir + '\*') # dirに入っている全ての画像パスを取得 out_dir = 'out' # 変換画像の出力先フォルダ # 出力先フォルダが無ければ新規作成する if os.path.isdir(out_dir): pass else: os.mkdir(out_dir) # LINEスタンプフォーマットに変換する for j in range(len(path)): img = cv2.imread(path[j], -1) # -1はAlphaを含んだ形式(0:グレー, 1:カラー) color_lower = np.array([235, 235, 235, 235]) # 抽出する色の下限(BGR形式) color_upper = np.array([255, 255, 255, 255]) # 抽出する色の上限(BGR形式) img_mask = cv2.inRange(img, color_lower, color_upper) # 範囲からマスク画像を作成 img_bool = cv2.bitwise_not(img, img, mask=img_mask) # 元画像とマスク画像の演算(背景を白くする) img_resize = cv2.resize(img_bool, (w, h)) # 透過処理済み画像をリサイズする # 画像の周りにサイズ10の透過画素をパディングする img_padding = cv2.copyMakeBorder(img_resize, 10, 10, 10, 10, cv2.BORDER_CONSTANT, value=[0, 0, 0, 0]) num = str("{:02}".format(j + 1)) # 連番作成 out_path = os.path.join(*[out_dir, num + '.png']) # 出力スタンプのファイルパス # 連番ファイル名が既に存在する場合はmain.pngかtab.pngなので、元画像の拡張子付きファイル名を使う if os.path.isfile(out_path): file = os.path.basename(path[j]) # 拡張子ありファイル名を取得 name = os.path.splitext(file) # 拡張子なしファイル名と拡張子を取得 out_path = os.path.join(*[out_dir, name[0] + '.png']) cv2.imwrite(out_path, img_padding) # 最終画像を保存 return # 画像種類毎にフォルダを設定 dir_sticker = 'sticker' # スタンプ画像(8, 16, 24, 32, 40枚)の入ったフォルダ dir_main = 'main' # メイン画像(購入画面で表示される)の入ったフォルダ dir_tab = 'tab' # トークルームタブ画像の入ったフォルダ DIR = [dir_sticker, dir_main, dir_tab] # フォルダディレクトリリスト # スタンプの横w, 縦hサイズ(パディング分20を引いた数値) w_sticker, h_sticker = 300, 300 # スタンプ画像のサイズ w_main, h_main = 220, 220 # メイン画像のサイズ w_tab, h_tab = 76, 54 # トークルームタブ画像のサイズ W = [w_sticker, w_main, w_tab] # 画像の横サイズリスト H = [h_sticker, h_main, h_tab] # 画像の縦サイズリスト # 関数を実行してスタンプを自動変換する for i in range(len(DIR)): create_sticker(DIR[i], W[i], H[i]) |
実行結果
以下が実行結果です。outフォルダが自動生成され、その中に申請に必要な全ての画像(01.png~24.png, main.png, tab.png)も作られています。
白色部分の透過、規定のサイズにリサイズ、余白として透過画素10[px]のパディング(画像の周りに一定値のピクセルを置いてサイズ拡張すること)が施されました。
キャラクターの頭から出ている湯気(…湯気のつもりです)も透過されていますが、ここは色を付けた方がよかったかも知れません。
コードのポイント
必要な変数
フォーマット変換は関数の中で実施していますが、関数の引数としてフォルダの名前、画像のサイズを変数として設定しています。
もし正方形以外のサイズにしたい場合はこの数値を変更するだけでOKです。
1 2 3 4 5 6 7 8 9 10 11 12 |
# 画像種類毎にフォルダを設定 dir_sticker = 'sticker' # スタンプ画像(8, 16, 24, 32, 40枚)の入ったフォルダ dir_main = 'main' # メイン画像(購入画面で表示される)の入ったフォルダ dir_tab = 'tab' # トークルームタブ画像の入ったフォルダ DIR = [dir_sticker, dir_main, dir_tab] # フォルダディレクトリリスト # スタンプの横w, 縦hサイズ(パディング分20を引いた数値) w_sticker, h_sticker = 300, 300 # スタンプ画像のサイズ w_main, h_main = 220, 220 # メイン画像のサイズ w_tab, h_tab = 76, 54 # トークルームタブ画像のサイズ W = [w_sticker, w_main, w_tab] # 画像の横サイズリスト H = [h_sticker, h_main, h_tab] # 画像の縦サイズリスト |
透過処理
透過処理は「Python/OpenCVで任意色を透過させたpng画像に変換」で習得したOpenCVによるコードをそのまま使っています。
1 2 3 4 5 |
img = cv2.imread(path[j], -1) # -1はAlphaを含んだ形式(0:グレー, 1:カラー) color_lower = np.array([235, 235, 235, 235]) # 抽出する色の下限(BGR形式) color_upper = np.array([255, 255, 255, 255]) # 抽出する色の上限(BGR形式) img_mask = cv2.inRange(img, color_lower, color_upper) # 範囲からマスク画像を作成 img_bool = cv2.bitwise_not(img, img, mask=img_mask) # 元画像とマスク画像の演算(背景を白くする) |
透過の方法は以下の画像のように、色範囲(color_lower, color_upper)に該当した色を使ってマスク画像を作り、not演算(ブーリアン演算)で画素階調内Alphaチャンネルを含む全ての要素を0にしています(詳細は上記記事を参照下さい。)。
リサイズ
画像サイズをLINEガイドライン記載のサイズにきっちり収めるために「Python/OpenCVで画像をリサイズする方法」で習得したリサイズコードを使っています。
コード自体は簡単ですが、日常で使いやすく非常に便利ですね。
1 |
img_resize = cv2.resize(img_bool, (w, h)) # 透過処理済み画像をリサイズする |
余白処理(パディング)
LINEスタンプ作成ガイドラインにはイラストの周りに余白が10[px]ほど必要とありました。余白は画像の周りに一定の線を付ければ良いので、OpenCVのcopyMakeBorderで作りました。「10, 10, 10, 10」と辺毎にサイズを指定できる所が便利なので、それぞれ違う太さを与えることも出来ますね。
valueで余白部分の色を指定していますが、Alphaチャンネル(最後の要素)が0になっていれば100%透過線が作れます。
1 2 3 4 5 |
# 画像の周りにサイズ10の透過画素をパディングする img_padding = cv2.copyMakeBorder(img_resize, 10, 10, 10, 10, cv2.BORDER_CONSTANT, value=[0, 0, 0, 0]) |
ちなみに、このように画像の周りに一定画素を敷き詰めることをパディングと呼びます。この用語はCNN(畳み込みニューラルネットワーク)を学習した時に覚えたので、画像処理に興味のある方は機械学習もすんなり理解できるかも知れません(ご興味があればAIカテゴリも見てみて下さい!)。
まとめ
本ページではLINEスタンプ作成のハードルを大きく下げるスタンプ申請用自動フォーマット変換プログラムを紹介しました。
今回、実際に初めてスタンプを作ってみましたが、良い意味で適当な画像から申請用画像が自動生成できたので、作成にかかるストレスはほぼ感じませんでした。
クリエイターが増えればもっと面白いスタンプが世の中に増えると期待していますので、是非面倒で退屈なことはPythonにやらせてみましょう!
最後に宣伝ですが、ディープラーニング用語で作成したスタンプもよろしくお願いします!
初めて少し役に立つプログラムを作ったかも知れません!是非ご利用下さい!
Twitterでも関連情報をつぶやいているので、wat(@watlablog)のフォローお待ちしています!