経緯
小さな画像を連続させて模様を作りたかったのですが、Python3でやろうとするとPillowを使うかOpenCV使うかで悩んだので、この際どっちの方が良いのか実験してみました。
自分用のメモです。
環境
- Windowns10
- Python 3.7.9
- ライブラリ
- numpy : 1.20.2
- opencv-python : 4.5.1.48
- Pillow : 8.3.1
連続画像の作り方
同じ画像を連続させた画像をPythonで作る場合、やり方はまぁまぁたくさんあります。今回はPillowで読み込んだ場合とOpenCVで読み込んだ場合を比較しました(自分がよく使うので)
やり方は次の通り。各々元の画像を縦に3回、横に4回繰り返し、12枚の元画像が並んだ画像を生成します。
元画像のサイズは128×128
です。
- Pillow
- 背景画像(大きさを「元画像の大きさ×連続させたい縦横の数」で定義しておく)に、元画像を貼り付ける
from PIL import Image
img1 = Image.open(pic_path) # 画像読み込み
img2 = Image.new('RGBA', (img1.size[0] * 4, img1.size[1] * 3)) # 背景画像定義
for i in range(4):
for k in range(3):
img2.paste(img1, (i * img1.size[0], k * img1.size[1])) # 元画像を指定位置に貼り付け
- OpenCV (& numpy)
- ライブラリの関数で読み込んでarray化した画像を、
numpy
のnp.tile
で連続させたい数だけ繰り返す
- ライブラリの関数で読み込んでarray化した画像を、
import numpy as np
import cv2
img3 = cv2.imread(pic_path) # 画像読み込み
img4 = np.tile(img3, (3, 4, 1)) # 繰り返し画像の定義
結果
上のやり方を各100,000回繰り返し、それぞれ時間を測定。一回当たりの時間の平均値を計算しました。(計算)
| * | mean (1回あたりの処理時間) |
| --- | --: | --: |
| OpenCV(numpy) | 0.00074 (秒) |
| Pillow | 0.00126 (秒) |
考察
まぁ予想通りでした。for使ったほうが遅いに決まってる。
画像系のライブラリって混ぜて使うと混乱の元なのであまりやりたくないんですが、画像を任意の角度で回転する関数がPillowにしかなかったり、OpenCVの方がメンドクサイ処理には向いていたりと長短があるので考えて使っていこうと思います。
とりあえず、繰り返しで画像生成しなきゃいけないときは
- 画像はarrayで読み込んで、繰り返し画像は
np
で生成する - 回転処理等かけるときはPillowに変換して使う
でやろうと思います。