0

I am trying to horizontally flip an image (from left to right) on Python using PyPNG, I have written the following codes but it does not seem to work, anybody have any idea what I'm doing wrong here?

def horizontal_flip(image):
    rows = len(image)
    cols = len(image[0])
    new_image = []
    for r in range(rows):
        new_row = []
        for c in range(0,cols,3):
            if c != cols/2:
                image[c:c+3], image[-c-3: -c] = image[-c-3: -c], image[c:c+3]
                new_row.append(image[r][c])
        new_image.append(new_row)
    return new_image
David Jones
  • 4,766
  • 3
  • 32
  • 45
user1009134
  • 1
  • 1
  • 1

2 Answers2

0

new_row.append(image[r][c]) should be outside of the if.

Also, you're flipping the image horizontally... twice. Make your for loop use range(0,cols/2,3). (That may also eliminate the need for that if.)

You're also modifying the original image in-place; are you sure you want to do that?

Seems a simpler solution might be to loop through each row in reverse, appending to a row for the new image.

retracile
  • 12,167
  • 4
  • 35
  • 42
0

The inner loop logic is wrong but particularly, this line:

image[c:c+3], image[-c-3: -c] = image[-c-3: -c], image[c:c+3]

You are changing the image variable in-place, but you seemed to forget the row variable r. So right now, you are changing rows. And your negative slicing is a bit off. For c=0, you'll get image[-3:0] and this is not a valid slice and it will return [].

But judging from your code you don't mean to change image in-place, you rather want to create new_image. What you should be doing is inserting slices at the end of new_row:

def horizontal_flip(image):
    rows = len(image)
    cols = len(image[0])
    new_image = []
    for r in range(rows):
        new_row = []
        for c in range(0,cols,3):
            new_row = image[r][c:c+3] + new_row
        new_image.append(new_row)
    return new_image

By the way, you can also change the image in-place, but be careful. As you are passing a list, you should copy it before changing so that original is unchanged. Here is that version:

def horizontal_flip(image):
    cols = len(image[0])/3

    #make a copy so that original image is not altered
    image = [row[:] for row in image]

    for row in image:
        for c in range(int(cols/2)): # int() is not needed for Python 2.x, since integer division yields integer
                                     # This also takes care of odd n cases, middle chunk is not changed.
            row[3*c:3*c+3], row[3*(cols-c-1):3*(cols-c-1)+3] = row[3*(cols-c-1):3*(cols-c-1)+3], row[3*c:3*c+3]

    return image

This can also be done with a list comprehension in single line, but it will be less readable. If you like, here is how you can do it:

from itertools import chain
flipped_image = [list(chain(*[row[3*i:3*i+3] for i in range(len(image[0])/3-1,-1,-1)])) for row in image]
Avaris
  • 35,883
  • 7
  • 81
  • 72