1

写真を分析しようとしています。私は基本的に2つのステップでそれをやっています:

  1. グレースケール画像に変換する
  2. 写真の領域を取り、それらが白または黒である可能性が高いかどうかを確認します

私のプログラムはほとんどの場合うまくいきますが、すべてではありません。それは主に、写真を白黒に変換する方法がよくわからなかったからです。私は主に見つけたコードをコピーし、試行錯誤して機能させました(そのため、グレースケールのすべての非白ピクセルを黒にする方法が見つからなかったため、白黒ではなくグレースケールになりました)

私は画像操作に PIL を使用しており、画像操作の主な関数は次のようになります (convert() は一度使用され、変換された画像のすべての部分に avgcol() が使用されます。分析したい)

def convert():
    global im   
    matrix = (1.412453, 0.357580, 0.180423, 0,
           0.212671, 0.715160, 0.072169, 0,
           0.019334, 0.119193, 0.950227, 0 )
    im = im.convert("L", matrix)

def avgcol(im):
    p_colors=im.getcolors()
    cnt_pix=(im.size[0])*(im.size[1])
    avgpix=0
    for i in range(len(p_colors)):
        avgpix=avgpix+p_colors[i][0]*p_colors[i][1]
    return round(avgpix/cnt_pix  , 1)

マトリックスが何をするのか、よくわかりません(単一の値を説明するサイトが見つかりませんでした)。現在の私の具体的な問題は、緑が多すぎるピクセルを白のピクセルに変換したいということですが、それが解決されれば、何か他のものが飛び出すと確信しています。やった、素晴らしいだろう。しかし、正しい方向への指針に感謝します。そして、すべてのピクセルをforループする解決策はありません。写真はかなり大きく、プログラムは高速である必要があります。

4

1 に答える 1

3

ドキュメントを見ると、いくつかのことがわかります。

まず、convert引数が 1 つのバージョンで、mode.

RGB からグレースケールへの変換だけが必要な場合:

grey = im.convert("L")

マトリックスを提供する唯一の理由は、デフォルトの変換を使用したくない場合です。

また、バイレベルの白黒に直接変換することもできます:

bw = im.convert("1")

ドキュメントが言うように:

2 値画像 (モード "1") に変換する場合、ソース画像は最初に白黒に変換されます。127 より大きい結果の値は白に設定され、イメージはディザリングされます。他のしきい値を使用するには、ポイント メソッドを使用します。

したがって、標準のしきい値とディザリングが必要な場合は、convert. 別のしきい値が必要な場合は、次のようになります。

grey = im.convert("L")
table = [int(i>200) for i in range(256)]
bw = grey.point(table, '1')

あなたの答えでは、次のように言います。

…グレースケールのすべての非白ピクセルを黒にする方法

どうしても「純白以外」を「非白」と言うのであれば、その意味では使えませんpoint。65536 アイテムのテーブルを使用convertしても、99.998% と 100% の白を区別できず、白ではない元のピクセルの一部が間違って一致する可能性があります。そのため、おそらく元のピクセルを直接 (関数を使用して) 反復処理し、新しい画像を手動で作成する必要があります。L16pointload


マトリックスが何をするかについては… マトリックス数学の基本を理解していれば、それは非常に簡単です。(そうでない場合は、ここで説明することはできませんが、Wikipedia の記事を参考にすることをお勧めします。)

各ソース ピクセルをベクトルとして扱います (たとえば、RGBA イメージでは、ベクトル<red, green, blue, alpha>.そのベクトルに行列を掛けると、新しいベクトルが得られます。それを目的の色空間のピクセルとして扱います。

たとえば、D65 RGBA ピクセルがあり、それぞれにドキュメントで指定された 4x3 マトリックスを掛けると、結果は CIE XYZ ピクセルになります。

これは、L に変換するために 4x3 マトリックスを使用する理由がないことを意味します。必要なのは 4x1 マトリックスです。そして、デフォルトが必要ない場合のみ。ドキュメントが言うように:

カラー画像から白黒に変換する場合、ライブラリは ITU-R 601-2 輝度変換を使用します。

L = R * 299/1000 + G * 587/1000 + B * 114/1000

…これはただ(.299, .587, .114, 0)です。


だから、あなたがしたい場合:

緑が多すぎるピクセルを白のピクセルに変換する

それはやや曖昧です。しかし、そのようなことを行う少なくとも1つの方法は、グリーンを強調しすぎることです. たとえば、 を使用する(.1495, .8448 , .0057, 0)と、明るさを決定するために緑が通常より多くカウントされます (赤と青は少なくカウントされます)。


一方、質問の最後に:

そして、すべてのピクセルをforループする解決策はありません。写真はかなり大きく、プログラムは高速である必要があります。

もちろん、内部では、 のような PIL コマンドbw = grey.point([int(i>200) for i in range(256)], '1')は、実際には 内のすべてのピクセルを for ループしていgreyます。Python ではなく C でループを実行しているだけです。また、 Cythonを使用して同じことを自分で行うか、 numpyを使用して暗黙的に行うか、既存の Python インタープリターの代わりにPyPyを使用することができます (Python の for ループをほぼ C の速度まで JIT できます)。

なぜそれをしたいのですか?さて、それぞれの方法でしきい値処理のコードを見てください。

# PIL
table = [int(i>200) for i in range(256)]
bw = grey.point(table, '1')

# Python (run in PyPy) or Cython
bw = [pixel > 200 for pixel in grey]

# numpy
bw = grey > 200
于 2013-05-01T20:12:12.143 に答える