画像をPython使って徐々にモザイク画像になるよう変換してみた

ツールがない時でも画像処理はPythonにお任せ! 今回はモザイク画像への変換をPythonコードでする時のお話です。
2022.08.03

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

皆さんこんにちは。hotoke_nekoです。

簡単にモザイク画像を作る方法としては、Windowsであればペイント、MacであればSkitchがオススメです。 今回はそういった画像単体を作るのでなく、gif画像で徐々にモザイク画像になるようなものを作成します。

今回の記事内で使用する画像はこちらになります。

yumekawa_animal_neko

いらすとやさんから画像をダウンロードできます。

モザイク画像にするには?

先に結論を述べると、必要な範囲の画素数を落とすとモザイク画像になります。 Pythonでのコードでは、画像のサイズをモザイクにする部分を一度小さくした後に元のサイズに戻すとモザイクになります。 コードを絡めて、画像全体をモザイクにする例を見てみましょう。

まず以下のコードをモザイク加工したい画像に対して実行します。

convert_to_mosaic_picture.py

import matplotlib.pyplot as plt
import cv2

# 画像読み込み
pic = cv2.imread(<対象画像のファイルパスを文字列で入れてください>)

# 画像の縦横比をfx,fyを使って縮小
small_pic= cv2.resize(pic, None, fx=0.1, fy=0.1,interpolation=cv2.INTER_NEAREST)

# imshowメソッドで表示するときには配列のRGBの順番がBGRとなっているので修正
plt.imshow(cv2.cvtColor(cv2.resize(small_pic,None,fx=10,fy=10), cv2.COLOR_BGR2RGB))

cv2.resizeメソッドの引数fxは幅の比率、引数fyは高さの比率を指定できます。 cv2.cvtColorメソッドの引数cv2.COLOR_BGR2RGBは、画像のBGRの並び順をRGBにするために使用しています。

5行目で書かれている'interpolation=cv2.INTER_NEAREST'という引数は無くとも動作しますが、よりモザイクらしい画像が生成できると判断したため入れております。

コードを実行すると、画像は次のようなものになります。

mosaic_picture_yume_neko

このようにPythonで画像サイズを小さくして元のサイズに戻すとモザイク画像になります。

徐々にモザイク画像に変化する画像を作る

徐々にモザイク画像にするというアニメーションをgif画像で実現します。 gif画像とは、複数枚の画像を一つの画像内で、次々と表示する画像の事です。

したがって、モザイクにする過程を表した画像を次々に表示していく事で、徐々にモザイク画像に変換されている様子を表現する事が可能となります。

次のコードを実行します。

convert_to_mosaic_gif_picture.py

import cv2
from PIL import Image

# モザイク画像を作成するメソッド
def mosaic_pic(pic,rate):
  small_pic= cv2.resize(pic, None, fx=rate, fy=rate, interpolation=cv2.INTER_NEAREST)
  return cv2.resize(small_pic, pic.shape[:2][::-1], interpolation=cv2.INTER_NEAREST)


# 画像を読み込み
pic = cv2.cvtColor(cv2.imread(<対象画像のファイルパスを文字列で入れてください>), 
                   cv2.COLOR_BGR2RGB)

# 内包表記を用いて複数枚のモザイク画像を作成
pics = [Image.fromarray(mosaic_pic(pic, 1 / i)) for i in range(1, 20)]

# モザイク画像を保存
pics[0].save(<保存先のファイルパス/ファイル名.gifを文字列で入力>,save_all=True, append_images=pics[1:],loop=0)

コードの説明

概要

mosaic_picメソッドと内包表記を用いて複数枚の画像をlistへ格納しています。格納する画像は、徐々に荒さが増したものを作成しています。

画像を格納するときには、cv2.resizeメソッドの返り値がnumpy.ndarray型なのでImage.fromarrayメソッドで型を忘れずにImage型に変換します。

その後、Image型の変数pics[0]でsaveメソッドを使って画像を保存しています。

引数の説明

  • mosaic_picメソッド
    • cv2.resizeメソッドの第二引数に画像のサイズを指定できるのですが、渡す値は(幅、高さ)の順番なので注意が必要です。
    • 引数で受け取ったpicの2番目までの要素(高さ、幅)を[::-1]で指定して逆順に見た時のshape(幅、高さ)という形で渡すようにしています。(cv2.imreadメソッドで読み込んだ画像のshapeは高さ、幅、色の順です。)
  • saveメソッド
    • append_imagesでは、2番目の画像から渡すようにします。そうしないと最初の画像が2枚にダブってしまいます。
    • loopでは、指定した数値分だけgifアニメーションを最初から終わりまで実行します。0を指定すると無限ループになります。

画像の保存方法については、公式サイトが参考になります。

実際に生成した画像がこちらになります。

yumekawa_animal_neko.gif

終わりに

今回は、モザイク画像への変換方法とモザイクのアニメーションを表示するgif画像へ変換する方法をお伝えしました。

今回お伝えしていない事柄で、画像の一部分のみを対象にモザイク加工をするという事も可能なので色々と応用が効きそうです。 また今回の本題から少し外れるのですが、convert_to_mosaic_gif_picture.pyファイル12行目の直下に'pics+=pics[-2::-1]'というコードを追記すると、元画像からモザイク画像へ変化後、モザイク画像から元画像へ滑らかに遷移するgif画像を生成できます。

本日はここまで。

それでは、また!