0

PIL のミラーまたはフリップ モジュールを使用せずに、イメージを取得してミラー イメージを返す関数を作成する必要があります (Y 座標は変更されません)。
私はそれを自分で書かなければなりません。エラーメッセージが表示されます:

IndexError: image index out of range

ここで何が欠けていますか?

ありがとうございました。

from os.path import exists
import tkMessageBox, tkFileDialog
from PIL import Image, ImageTk, ImageFilter

def flip(im):
    '''Flips a picutre horizontally, and returns a new image that is a mirror view of the original'''
    org=Image.open(im)
    new=Image.new("RGB",org.size)   
    for x in range(org.size[0]):
        a=org.size[0]
        for y in range(org.size[1]):
            pixel=org.getpixel((x,y))
            new.putpixel((a,y),pixel)
            a-=1
    new.save("new.bmp","bmp")
4

2 に答える 2

16

ImageOps.mirror(image)を使用して、画像を水平方向に反転します。

import Image
import ImageOps

img = Image.open(FILENAME)
mirror_img = ImageOps.mirror(img)

あなたのコードは動作に非常に近いです。「オフバイワン」エラーがあります。

a=org.size[0]
...
new.putpixel((a,y),pixel)

org幅が 100 ピクセルだとしましょう。次に、ループを初めて通過するときに、ピクセルを に配置し(100,y)ます。ただし、ピクセルには 0 ~ 99 のインデックスが付けられます。これが、 IndexError: image index out of range例外が発生する理由 (および場所) です。


また、ループのどこで初期化およびデクリメントを行っているかにも注意してくださいa。実際には、まったく使用しないことをお勧めaします。

むしろ、使用する

w,h = org.size
for x in range(w):
    for y in range(h):
        pixel = org.getpixel((x, y))
        new.putpixel(EXPRESSION, pixel)

EXPRESSION を、色を付けたいピクセルの位置の式に置き換えるだけです。

于 2013-01-06T13:48:27.047 に答える
3

0ベースと1ベースのインデックスを混同しています。xの範囲0org.size[0]-1。ただし、a範囲はからです。これは、最初に減算せずに、それから始めて使用するorg.size[0]ため1です。a=org.size[0]

ほとんどの場合、エラーはこの行のどこかから発生します。

new.putpixel((a,y),pixel)

…最初の呼び出しで、(0-279、0-279)からのみ実行される画像にピクセル(280、0)を書き込もうとしたとき。

したがって、これの代わりに:

for x in range(org.size[0]):
    a=org.size[0]
    for y in range(org.size[1]):
        pixel=org.getpixel((x,y))
        new.putpixel((a,y),pixel)
        a-=1

これを行う:

for x in range(org.size[0]):
    a=org.size[0]-1
    for y in range(org.size[1]):
        pixel=org.getpixel((x,y))
        new.putpixel((a,y),pixel)
        a-=1

しかし、これを修正すると、別の問題が発生します。初めてではなく、外側のループを通過するたびに設定aします。org.size[0]そしてa、外側のループではなく、内側のループを通過するたびにデクリメントします。したがって、元の画像の各線を(279,0)から(0,279)までの対角線にコピーすることになります。

したがって、これを行う必要があります。

a=org.size[0]-1
for x in range(org.size[0]):
    for y in range(org.size[1]):
        pixel=org.getpixel((x,y))
        new.putpixel((a,y),pixel)
    a-=1

この種のことは、まさにこのように手動でインデックスを変更することを避けるように努めるべきである理由です。あなたは最初の試みでそれを正しく理解することは決してありません。3回目の試行では、正しく見えるものが得られますが、テストスイートになかった最初の画像を試行するとすぐにクラッシュします。カウントダウンするのではなく、値を計算することをお勧めします。例えば:

for x in range(org.size[0]):
    flipped_x = org.size[0] - x - 1
    for y in range(org.size[1]):
        pixel=org.getpixel((x,y))
        new.putpixel((flipped_x,y),pixel)

その間、PIL 1.1.6以降を要求/依存できる場合は、によって返される配列を使用するImage.load()方がはるかに簡単で、はるかに効率的で、多くの場合、デバッグが簡単です。

orgpixels, newpixels = org.load(), new.load()
for x in range(org.size[0]):
    flipped_x = org.size[0] - x - 1
    for y in range(org.size[1]):
        pixel=orgpixels[x, y]
        newpixels[flipped_x, y] = pixel

1.1.6に頼ることができない場合はgetdata、ピクセルの反復可能なシーケンスを取得するために使用でき、それを使用して新しいlistシーケンスまたは他のシーケンスを生成できます(つまり、リスト内包表記を使用して、たとえば、経由でmapそれらをフィードすることもできます。 )、次にを使用して、結果から新しい画像を作成します。numpynp.array(org.getdata()).reshape(org.size)putdata

もちろんgetdataputdata1Dシーケンスを扱いますが、2Dシーケンスとして扱いたい場合もあります。幸いなことに、ドキュメントgrouper内の関数(コピーして貼り付けることも、単に貼り付けることもできます)は、通常、まさに必要なものです。itertoolspip install more-itertool

orgrows = more_itertools.grouper(org.size[0], org.getdata())
newrows = [list(reversed(row)) for row in orgrows]
new.putdata(newrows)

注意すべき点の1つは、Image.open(im)必ずしもRGBモードの画像が返されるとは限らないことです。たとえば、XYZまたはP画像からRGBにピクセルをコピーするだけでは、それぞれ変色したゴミまたは赤チャンネルだけになります。あなたはprint org.mode、そしておそらくprint org.pixel((0, 0))それが実際に3つのチャンネルを持っていることを確認したいと思うかもしれません(そしてそれらはRGBのように見えます)`。

それを回避する最も簡単な方法は、他のことをする前に変換orgすることです。

org=Image.open(im).convert('RGB')

もちろん、一部のフォーマットには直接変換がないか、明示的なマトリックスまたはカラーパレットが必要です。を取得した場合はValueError、入力タイプの変換について確認する必要があります。

于 2013-01-06T14:10:26.733 に答える