4

私はPythonが初めてで、Arduinoプロジェクトに必要な解析タスクを実行するためにPILを使用しようとしています。この質問はImage.convert()、カラー パレット、ディザリングなどの方法とオプションに関するものです。

一度に 16 色しか画像を表示できないハードウェアがあります (ただし、RGB トリプレットを指定できます)。したがって、任意のトゥルーカラー PNG 画像を取得し、それを表す「最適な」16 色パレットを選択し、その画像を 16 色の​​みを含むパレット化されたものに変換するタスクを自動化したいと考えています。

ディザリングを使いたい。問題は、image.convert()メソッドが少しファンキーに動作しているように見えることです。その引数は完全に文書化されていないため( Image.convert() の PIL ドキュメント)、それが私のせいなのか、メソッドにバグがあるのか​​ わかりません。

私のコードの簡単なバージョンは次のとおりです。

import Image
MyImageTrueColor = Image.new('RGB',100,100) # or whatever dimension...

# I paste some images from several other PNG files in using MyImageTrueColor.paste()

MyImageDithered = MyImageTrueColor.convert(mode='P',
    colors=16,
    dither=1
    )

私が行ったいくつかの検索に基づいて (例: How to reduce color palette with PIL )、この方法は私が望むことを行うべきだと思いますが、うまくいきません。画像をディザリングしますが、16 色を超える画像が生成されます。

念のために、「ディザ」引数を削除しました。同じ出力。

「dither=1」引数を再度追加し、Image.ADAPTIVE 引数 (上記のリンクに示されているように) を投入して、何が起こったかを確認しました。これにより、16 色を含むイメージが作成されましたが、ディザリングはありません。

ここで何か不足していますか?PIL はバグがありますか? 私が思いついた解決策は2つのステップを実行することでしたが、それはずさんで不必要なようです. これを正しく行う方法を理解したい :-) 完全を期すために、正しい結果が得られるコードのバージョンを次に示しますが、それはずさんな方法で行われます。(最初のステップでは 16 色以上のディザリングされたイメージが生成され、2 番目のステップでは 16 色の​​みを含むイメージが生成されます。)

MyImage_intermediate = MyImageTrueColor.convert(mode='P',
    colors=16
    )
MyImageDithered = MyImage_intermediate.convert(mode='P',
    colors=16,
    dither=1,
    palette=Image.ADAPTIVE
    )

ありがとう!

4

1 に答える 1

7

まあ、あなたは正しく呼び出していないので、機能しないはずです... しかし、正しく呼び出していたとしても、うまくいくかどうかはわかりません。

まず、PIL ハンドブックの「公式」無料版は不完全であり、時代遅れです。http://effbot.org/imagingbook/image.htmにあるドラフト バージョンは、それほど不完全ではなく、古くなっています。

im.convert(“P”, **options) ⇒ 画像

同じですが、「RGB」画像を 8 ビット パレット画像に変換する際の制御が向上します。利用可能なオプションは次のとおりです。

ディザ=。ディザリングを制御します。デフォルトは FLOYDSTEINBERG で、エラーを隣接するピクセルに分散します。ディザリングを無効にするには、NONE を使用します。

パレット=. パレットの生成を制御します。デフォルトは、標準の 216 色の​​「Web パレット」である WEB です。最適化されたパレットを使用するには、ADAPTIVE を使用します。

色=。パレットが ADAPTIVE の場合に、パレットに使用される色の数を制御します。デフォルトは最大値の 256 色です。

colorsしたがって、まず、 —なしでは使用できませんADAPTIVE。理由は明らかです。他の唯一の選択肢はWEB、固定の 216 色パレットのみを処理する です。

1次に、 に渡すことはできませんdither。それがたまたま の値であった場合、それはうまくいくかもしれませんが、それはFLOYDSTEINBERGです3。したがって、文書化されていない値を渡しています。それが何をするか誰が知っていますか?特に、ディザリング アルゴリズムの可能な名前のように聞こえるすべての定数を調べると、値が 1 になるものはありません。

したがって、dither=Image.FLOYDSTEINBERG( とともにpalette=Image.ADAPTIVE) に変更してみて、違いが生じるかどうかを確認してください。

しかし、コードを見ると、これは何の役にも立たないように見えます。

if mode == "P" and palette == ADAPTIVE:
    im = self.im.quantize(colors)
    return self._new(im)

これは、ディザリング コードに到達する前に発生します。したがって、(現在は非推奨/プライベート) メソッド quantize を呼び出すのとまったく同じです。

convert複数のスレッドは、高レベル関数が「Web パレットへのディザリング」または「最も近い N 色へのマップ」を公開することのみを意図していたことを示唆しています。これは 1.1.6 以降でわずかに変更されたようですが、ドキュメントと実装はどちらもまだ不完全です。http://comments.gmane.org/gmane.comp.python.image/2947で、開発者の 1 人が PIL/Image.py ソースを読むことを推奨しています。

だから、それがあなたがする必要があることのようです。Image.convertモードで行うことは何でもImage.WEB、それを行いたいのですがImage.quantize(colors)、Web パレットではなく、 によって生成されるパレットを使用します。

もちろん、その大部分は C コード ( 、 などの下) で発生しself.im.quantizeますself.im.convertが、次の疑似コードのようなことができる場合があります。

dummy = img.convert(mode='P', paletter='ADAPTIVE', colors=16)
intermediate = img.copy()
intermediate.setpalette(dummy.palette)
dithered = intermediate._new(intermediate.im.convert('P', Image.FLOYDSTEINBERG))

繰り返しますが、そうでない場合があります。調べるには、C ヘッダーまたはソースを調べる必要がある場合があります。または、PIL メーリング リストで質問してください。

PS、PIL の内臓に慣れていない場合はimg.im、PIL Image オブジェクトの下にある C イメージング オブジェクトimgです。私の過去の経験から、これは最初の 3 回は PIL コードをざっと見ただけではわかりませんが、突然すべてがより理にかなっています。

于 2012-09-28T19:36:26.783 に答える