mieki256's diary



2022/07/07(木) [n年前の日記]

#1 [python] Pillowのgetpixel()は本当に遅いのか気になったので確認してみた

Python で画像を扱える Pillow (PIL)モジュールについて、1ドット単位で値を読んだり書いたりできる .getpixel()/.putpixel() というメソッドがあるのだけど。巷の各種記事では処理速度が遅いと書いてあって、本当にそうなのかなと気になってきた。

そんなわけで、ベンチマークを取ってみた。環境は、Windows10 x64 21H2 + Python 3.9.13 64bit + Pillow 9.1.1。CPU は AMD Ryzen 5 5600X (6コア12スレッド、ベースクロック3.7GHz)。

4288x2848ドットの画像に対してひたすらドットを読むだけの処理をしてみた。ちなみに利用した画像は以下。

_十代の少女 可愛い 肖像画 - Pixabayの無料写真


ソースは以下。

_05getpixel_bench.py
from PIL import Image
from benchmarker import Benchmarker

infile = "teen-girl-4467541_4288x2848.jpg"


def main():
    im = Image.open(infile)
    width, height = im.size
    print("%d x %d" % (width, height))

    with Benchmarker(100) as bench:
        @bench(".getdata()")
        def _(bm):
            im = Image.open(infile)
            dt = im.getdata()
            for y in range(height):
                idx = width * y
                for x in range(width):
                    _ = dt[idx + x]

        @bench(".load()")
        def _(bm):
            im = Image.open(infile)
            src = im.load()
            for y in range(height):
                for x in range(width):
                    _ = src[x, y]

        @bench(".getpixel()")
        def _(bm):
            im = Image.open(infile)
            for y in range(height):
                for x in range(width):
                    _ = im.getpixel((x, y))


if __name__ == '__main__':
    main()

動作には、Pillow と benchmarker が必要。
pip install Pillow -U
pip install Benchmarker -U

結果は以下のような感じになった。

> py 05getpixel_bench.py
4288 x 2848
## benchmarker:         release 4.0.1 (for python)
## python version:      3.9.13
## python compiler:     MSC v.1929 64 bit (AMD64)
## python platform:     Windows-10-10.0.19044-SP0
## python executable:   C:\Python\Python39-64\python.exe
## cpu model:           AMD64 Family 25 Model 33 Stepping 2, AuthenticAMD
## parameters:          loop=100, cycle=1, extra=0

##                                       real    (total    = user    + sys)
.getdata()                             0.7155    0.7188    0.6875    0.0312
.load()                                0.7961    0.7969    0.7969    0.0000
.getpixel()                            6.2659    6.2656    6.2656    0.0000

## Ranking                               real
.getdata()                             0.7155  (100.0) ********************
.load()                                0.7961  ( 89.9) ******************
.getpixel()                            6.2659  ( 11.4) **

## Matrix                                real    [01]    [02]    [03]
[01] .getdata()                        0.7155   100.0   111.3   875.8
[02] .load()                           0.7961    89.9   100.0   787.1
[03] .getpixel()                       6.2659    11.4    12.7   100.0


.getdata() を使えばたしかに速くなるけれど、一次元配列に対してアクセスするような書き方になるので、可読性はほんのちょっと、若干かすかに、ビミョーに悪くなるような気もする。

対して、.load() を使ったアクセスなら、.getpixel() と同様に x, y を指定してアクセスできるし、しかも .getdata() を使った場合とそれほど処理速度も変わらないわけで…。

個人的には、.getdata() より、可読性と処理速度の両方をそこそこ得られる .load() を使ったほうがいいのではないかと思えてきた。

余談。手元で実験に使ってるスクリプトが、とにかく遅くて…。.load() を使って画像の各ドットにアクセスしていたのだけど、.getdata() を使ったらもっと速く処理できないかと少し期待しながらベンチマークを取ったわけで。ある意味、残念な結果になってしまった。今回、そこらへんを変えてみても結果は変わらないようだなと…。

以上です。

過去ログ表示

Prev - 2022/07 - Next
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

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project