4

PIL画像の強度を再スケーリングする最も簡単でクリーンな方法は何ですか?

12ビットカメラからの16ビット画像があるとすると、0〜4095の値のみが使用されます。0〜65535の範囲全体が使用されるように、強度を再スケーリングしたいと思います。画像がPILの画像タイプとして表されている場合、これを行う最も簡単でクリーンな方法は何ですか?

私がこれまでに思いついた最善の解決策は次のとおりです。

pixels = img.getdata()
img.putdata(pixels, 16)

これは機能しますが、常に最下位4ビットを空白のままにします。理想的には、各値を4ビット左にシフトしてから、最上位4ビットを最下位4ビットにコピーします。私はそれを速くする方法がわかりません。

4

5 に答える 5

3

ピクセル値が0〜4095であることを知っているので、これよりも速い方法を見つけることはできません。

new_image= image.point(lambda value: value<<4 | value>>8)

ドキュメントによると、ラムダ関数は、画像のサイズに関係なく、最大で4096回呼び出されます。

編集:ポイントに与えられた関数は画像内の形式でなければならないので、これは関数を使用して可能な限り最良です:argument * scale + offsetIpoint

new_image= image.point(lambda argument: argument*16)

最大出力ピクセル値は65520になります。

2番目のテイク:

itertools効率を向上させるために使用する、独自のソリューションの修正バージョン:

import itertools as it # for brevity
import operator

def scale_12to16(image):
    new_image= image.copy()
    new_image.putdata(
        it.imap(operator.or_,
            it.imap(operator.lshift, image.getdata(), it.repeat(4)),
            it.imap(operator.rshift, image.getdata(), it.repeat(8))
        )
    )
    return new_image

pointこれにより、関数の引数の制限が回避されます。

于 2009-09-16T02:42:59.757 に答える
2

4msbを4lsbにコピーして戻したいのはなぜですか?ピクセルあたりの情報は12ビットしかありません。あなたがすることはそれを改善しません。ほとんどのアプリケーションで問題ない4Kの強度しかない場合は、ソリューションは正しく、おそらく最適です。より多くのレベルのシェーディングが必要な場合は、Davidが投稿したように、ヒストグラムを使用して再計算します。ただし、これは大幅に遅くなります。

しかし、4msbを4lsbにコピーするのは道ではありません:)

于 2009-08-25T13:49:39.217 に答える
2

ヒストグラム均等化ではなく、ヒストグラムストレッチ私が回答した同様の質問へのリンク)を実行する必要があります: ヒストグラムストレッチhttp://cct.rncan.gc.ca/resource/tutor/fundam/images/linstre.gif

画像ソース

あなたの場合、すべてのピクセル値に16を掛ける必要があります。これは、2つのダイナミックレンジ(65536/4096)の間の係数です。

于 2009-08-26T12:45:18.910 に答える
1

あなたがする必要があるのはヒストグラム均等化です。Pythonとpilでそれを行う方法については:

編集:各値を4ビット左にシフトし、4つの最上位ビットを4つの最下位ビットにコピーするコード...

def f(n):
   return  n<<4 + int(bin(n)[2:6],2)

print(f(0))
print(f(2**12))

# output
>>> 0
    65664 # Oops > 2^16
于 2009-08-25T12:31:36.787 に答える
0

たぶん、16(int)ではなく16(float)を渡す必要があります。私はそれをテストしようとしましたが、何らかの理由でputdataはまったく乗算されません...だから私はそれがあなたのためにうまくいくことを願っています。

于 2009-09-11T13:48:17.053 に答える