web-dev-qa-db-ja.com

PILからピクセル値のリストを取得する

皆さん、私はちょっとした援助を探しています。私は初心者のプログラマーであり、私が今抱えている問題の1つは、白黒の_.jpg_イメージをオーディオ信号に変調できるリストに変換しようとしていることです。これはpython SSTVプログラムを作成するための大規模プロジェクトの一部です。

PILモジュールをインポートし、組み込み関数list(im.getdata())を呼び出そうとしています。私がそれを呼び出すと、pythonがクラッシュします。画像を常に320x240に分割して計算を容易にする方法はありますか?または、間違った関数を呼び出していますか?.

誰か提案があれば、発射してください。誰かがpythonを使用して変調されたオーディオトーンを生成した経験がある場合、喜んで伝えたい「知恵の真珠」を受け入れます。

31
Dave

Getdata()を呼び出してもPythonはクラッシュしません。イメージが破損しているか、PILインストールに何か問題がある可能性があります。別の画像で試すか、使用している画像を投稿してください。

これにより、イメージが希望どおりに分割されます。

from PIL import Image
im = Image.open('um_000000.png')

pixels = list(im.getdata())
width, height = im.size
pixels = [pixels[i * width:(i + 1) * width] for i in xrange(height)]
59
Nadia Alramli

numpy がインストールされている場合、次を試すことができます。

_data = numpy.asarray(im)
_

(ここで「試して」と言います。なぜgetdata()が機能しないのかは不明であり、asarrayがgetdataを使用しているかどうかはわかりませんが、テストする価値があります。)

33
tom10

TypeError: 'PixelAccess' object is not iterable...のようなエラーが発生していると思いますか?

ピクセルにアクセスする方法については、 Image.load のドキュメントをご覧ください。

基本的に、PILを使用して画像内のピクセルのリストを取得するには:

from PIL import Image
i = Image.open("myfile.png")

pixels = i.load() # this is not a list, nor is it list()'able
width, height = i.size

all_pixels = []
for x in range(width):
    for y in range(height):
        cpixel = pixels[x, y]
        all_pixels.append(cpixel)

all_pixelsにすべてのピクセルを追加します-ファイルがRGB画像の場合(白黒画像のみを含む場合でも)、これらはTupleになります。例:

(255, 255, 255)

画像をモノクロに変換するには、3つの値を平均するだけです。したがって、最後の3行のコードは次のようになります。

cpixel = pixels[x, y]
bw_value = int(round(sum(cpixel) / float(len(cpixel))))
# the above could probably be bw_value = sum(cpixel)/len(cpixel)
all_pixels.append(bw_value)

または、輝度を取得するには(加重平均):

cpixel = pixels[x, y]
luma = (0.3 * cpixel[0]) + (0.59 * cpixel[1]) + (0.11 * cpixel[2])
all_pixels.append(luma)

または、黒と白の純粋な1ビット:

cpixel = pixels[x, y]
if round(sum(cpixel)) / float(len(cpixel)) > 127:
    all_pixels.append(255)
else:
    all_pixels.append(0)

おそらくRGB -> BW変換をより速く行うPIL内のメソッドがありますが、これは機能し、特に遅くはありません。

各行でのみ計算を実行したい場合は、すべてのピクセルを中間リストに追加することをスキップできます。たとえば、各行の平均値を計算するには:

from PIL import Image
i = Image.open("myfile.png")

pixels = i.load() # this is not a list
width, height = i.size
row_averages = []
for y in range(height):
    cur_row_ttl = 0
    for x in range(width):
        cur_pixel = pixels[x, y]
        cur_pixel_mono = sum(cur_pixel) / len(cur_pixel)
        cur_row_ttl += cur_pixel_mono

    cur_row_avg = cur_row_ttl / width
    row_averages.append(cur_row_avg)

print "Brighest row:",
print max(row_averages)
14
dbr

PILではなく、 scipy.misc.imread はまだ興味深いかもしれません:

import scipy.misc
im = scipy.misc.imread('um_000000.png', flatten=False, mode='RGB')
print(im.shape)

与える

(480, 640, 3)

そのため(高さ、幅、チャネル)です。だからあなたはそれを繰り返すことができます

for y in range(im.shape[0]):
    for x in range(im.shape[1]):
        color = Tuple(im[y][x])
        r, g, b = color
2
Martin Thoma

または、白または黒のピクセルをカウントする場合

これも解決策です。

from PIL import Image
import operator

img = Image.open("your_file.png").convert('1')
black, white = img.getcolors()

print black[0]
print white[0]
2
data = numpy.asarray(im)

注意:PILでは、imgはRGBAです。 cv2では、imgはBGRAです。

私の堅牢なソリューション:

def cv_from_pil_img(pil_img):
    assert pil_img.mode=="RGBA"
    return cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGBA2BGRA)
1
sunshine

PILlowがtostring()tobytes()に変更したようです。 RGBAピクセルを抽出してOpenGLテクスチャに入れようとすると、次のことがうまくいきました(glTexImage2D簡潔にするために省略しています)。

from PIL import Image
img = Image.open("mandrill.png").rotate(180).transpose(Image.FLIP_LEFT_RIGHT)

# use img.convert("RGBA").tobytes() as texels
1
Dr. D.

上記でコメントしたように、問題はPIL内部リスト形式から標準のpythonリストタイプへの変換です。Image.tostring()の方がはるかに高速であり、私の場合、画像データのCRC32ダイジェストを計算する必要がありましたが、それはうまくいきました。

より複雑な計算を実行する必要がある場合、numpyを含むtom10応答が必要な場合があります。

1
jesjimher
pixVals = list(pilImg.getdata())

出力は、画像からのすべてのRGB値のリストです。

[(248, 246, 247), (246, 248, 247), (244, 248, 247), (244, 248, 247), (246, 248, 247), (248, 246, 247), (250, 246, 247), (251, 245, 247), (253, 244, 247), (254, 243, 247)]
0
Linda