Python Imaging Library を使用して、色の関係を定義するルックアップテーブルで白黒画像を色付けしています。ルックアップテーブルは、RGBタプルの256要素のリストです。
_>>> len(colors)
256
>>> colors[0]
(255, 237, 237)
>>> colors[127]
(50, 196, 33)
>>>
_
私の最初のバージョンでは、getpixel()
メソッドとputpixel()
メソッドを使用しました。
_ for x in range(w):
for y in range(h):
pix = img.getpixel((x,y))
img.putpixel((x,y), colors[pix[0]])
_
これはひどく遅かった。 profile
レポートは、putpixel
メソッドとgetpixel
メソッドを原因として指摘しています。少し調べて(つまり、ドキュメントを読んで)、「この方法は比較的遅いことに注意してください。」re:putpixel
。 (実際のランタイム:1024x1024イメージの場合はputpixel
で53秒およびgetpixel
で50秒)
ドキュメントの提案に基づいて、代わりにim.load()
と直接ピクセルアクセスを使用しました。
_ pixels = img.load()
for x in range(w):
for y in range(h):
pix = pixels[x, y]
pixels[x, y] = colors[pix[0]]
_
処理は桁違いに高速化されますが、1024x1024の画像を処理するには、それでも遅い:約3.5秒です。
PILドキュメントのより徹底的な調査は、Image.point()
が正確にこの目的を目的としていることを示しているようです。
im.point(table)
=>画像
im.point(function)
=>画像指定されたテーブルを介して各ピクセルがマッピングされた画像のコピーを返します。テーブルには、画像のバンドごとに256個の値が含まれている必要があります。代わりに関数を使用する場合は、単一の引数を取る必要があります。この関数は、可能なピクセル値ごとに1回呼び出され、結果のテーブルが画像のすべてのバンドに適用されます。
私はインターフェースをハッキングするのにしばらく時間を費やしましたが、それを正しく理解することができないようです。私の無知を許してください、しかし、PILのドキュメントは素っ気なくて、私は多くの画像処理経験を持っていません。私は少しググっていくつかの例を見つけましたが、使用法を「クリック」させるものは何もありませんでした。したがって、最後に、私の質問:
Image.point()
はこの仕事に適したツールですか?Image.point()
はどのフォーマット/構造をテーブルに期待しますか?Image.point()はこの仕事に適したツールですか?
はい、確かに、Image.point()
はこの仕事に最適です
Image.point()はどのフォーマット/構造をテーブルに期待しますか?
[(12, 140, 10), (10, 100, 200), ...]
の代わりに次のようにリストをフラット化する必要があります:
[12, 140, 10, 10, 100, 200, ...]
これが私が試した簡単な例です:
im = im.point(range(256, 0, -1) * 3)
ちなみに、色をより細かく制御する必要があり、Image.pointが適切でないと思われる場合は、Image.getdata
とImage.putdata
を使用して、両方のload
よりもすばやく色を変更することもできます。およびputpixel
。ただし、Image.point
よりも低速です。
Image.getdata
は、すべてのピクセルのリストを提供し、それらを変更して、Image.putdata
を使用して書き戻します。とても簡単です。ただし、最初にImage.point
を使用して実行してみてください。
[〜#〜]編集[〜#〜]
私は最初の説明を間違えました、私は今正しく説明します:
カラーテーブルは実はこんな感じ
[0, 1, 2, 3, 4, 5, ...255, 0, 1, 2, 3, ....255, 0, 1, 2, 3, ...255]
各バンドの範囲は隣り合っています。色(0、0、0)を(10、100、10)に変更するには、次のようにする必要があります。
[10, 1, 2, 3, 4, 5, ...255, 100, 1, 2, 3, ....255, 10, 1, 2, 3, ...255]
カラーリストを正しい形式に変換するには、次のことを試してください。
table = sum(Zip(*colors), ())
私の最初の例はあなたのためにギ酸塩を示すべきだと思います。
私はそれがそのようにバンドごとにpoint
するのがより典型的かもしれないと思います(PILから直接持ち上げられます チュートリアル ):
# split the image into individual bands
source = im.split()
R, G, B = 0, 1, 2
# select regions where red is less than 100
mask = source[R].point(lambda i: i < 100 and 255)
# process the green band
out = source[G].point(lambda i: i * 0.7)
# paste the processed band back, but only where red was < 100
source[G].paste(out, None, mask)
# build a new multiband image
im = Image.merge(im.mode, source)