Mirroring an image diagonally in Python

I am taking a python programming class and we are working on mirroring images by defining the point of the mirror and then copying the pixel from one side to the other using nested for loops. For example, flipping an image vertically would use the following code:

def mirrorVertical(source):
 mirrorPoint = getWidth(source) / 2
 width = getWidth(source)
 for y in range(0,getHeight(source)):
   for x in range(0,mirrorPoint):
     leftPixel = getPixel(source,x,y)
     rightPixel = getPixel(source,width - x - 1,y)
     color = getColor(leftPixel)
     setColor(rightPixel,color)

      

I am currently working on an assignment asking us to display the image diagonally so that the upper left is reflected on the lower right side. Every example and answer I've found so far only works for square images, and I need to be able to apply that to any image, preferably by specifying a diagonal mirror point. I tried to determine the mirror point using the y = mx + b style equation, but I can't figure out how to tell Python to make this line. Any help not related to square images would be appreciated!

Note. Since I'm a newbie here, I can't post images, but the diagonal point of the mirror will work from bottom-left to top-right. The image in the upper left triangle will be displayed in the lower right corner.

+3


source to share


3 answers


You can swap the top left bottom right rectangle like this:

height = getHeight(source)
width = getWidth(source)
for i in range(height - 1):
    for j in range(int(width * float(height - i) / height)):
        # Swap pixel i,j with j,i

      

This works for diagonal mirroring. You seem to be implying that you might want to reflect in some arbitrary place. In this case, you will need to decide how to fill in pixels that do not have a corresponding pixel on the opposite side of the specular line.



You mentioned that you are working on assignment, so you should probably do the loops explicitly, but note that if you put your data into a numpy array, you can easily (and more efficiently) achieve what you want with a combination of the numpy function fliplr

, flipud

and transpose

.

Note that in the example code (left / right mirroring) you are copying the left pixel to the right side, but not vice versa, so you are not actually mirroring the image.

+3


source


Just to split one way of mirroring diagonally, bottom-left to top-right :

The student must adapt if he needs to mirror "top right to left" or use the opposite diagonal.

# !! Works only with squared pictures... !!
def diagMirrorPicture(picture):
    height = getHeight(picture)
    width = getWidth(picture)

    if (height != width):
        printNow("Error: The input image is not squared. Found [" + \
                                     str(width) + " x " + str(height) + "] !")
        return None

    newPicture = makeEmptyPicture(width, height)

    mirrorPt = 0
    for x in range(0, width, 1):
        for y in range(mirrorPt, height, 1):
            sourcePixel = getPixel(picture, x, y)
            color = getColor(sourcePixel)

            # Copy bottom-left as is
            targetPixel = getPixel(newPicture, x, y)
            setColor(targetPixel, color)

            # Mirror bottom-left to top right
            targetPixel = getPixel(newPicture, y, x)
            #                                  ^^^^  (simply invert x and y)
            setColor(targetPixel, color)

        # Here we shift the mirror point
        mirrorPt += 1

    return newPicture


file = pickAFile()
picture = makePicture(file)

picture = diagMirrorPicture(picture)

if (picture):
    writePictureTo(picture, "/home/mirror-diag2.png")
    show(picture)

      

Note. This behaves as if we are controlling a vertical mirror for each line of pixels independently of each other along a vertical axis passing through a point mirrorPt

.


Exit (painting by Anthony Tapies ):


................. enter image description here................. enter image description here................ ..








The following is experimental and just for fun ...

# Draw point, with check if the point is in the image area
def drawPoint(pic, col, x, y):
   if (x >= 0) and (x < getWidth(pic)) and (y >= 0) and (y < getHeight(pic)):
     px = getPixel(pic, x, y)
     setColor(px, col)

# Draw line segment given two points
# From Bresenham line algorithm :
# http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
def drawLine(pic, col, x0, y0, x1, y1):

   dx = abs(x1-x0)
   dy = abs(y1-y0) 
   sx = sy = 0

   #sx = 1 if x0 < x1 else -1
   #sy = 1 if y0 < y1 else -1

   if (x0 < x1): 
     sx = 1 
   else: 
     sx = -1
   if (y0 < y1):
     sy = 1 
   else: 
     sy = -1

   err = dx - dy

   while (True):

     drawPoint(pic, col, x0, y0)

     if (x0 == x1) and (y0 == y1): 
       break

     e2 = 2 * err
     if (e2 > -dy):
       err = err - dy
       x0 = x0 + sx

     if (x0 == x1) and (y0 == y1):
       drawPoint(pic, col, x0, y0)
       break

     if (e2 <  dx):
       err = err + dx
       y0 = y0 + sy 


# Works only with squared cropped areas :
# i.e. in [(x0, y0), (x1, y1)], abs(x1-x0) must be equal to abs(y1-y0)
#
# USAGE :
#    * To get bottom reflected to top use x0 > x1 
#    * To get top reflected to bottom use x0 < x1 

def diagCropAndMirrorPicture(pic, startPt, endPt):
    w = getWidth(pic)
    h = getHeight(pic)

    if (startPt[0] < 0) or (startPt[0] >= w) or \
       (startPt[1] < 0) or (startPt[1] >= h) or \
       (endPt[0] < 0) or (endPt[0] >= w) or \
       (endPt[1] < 0) or (endPt[1] >= h):
          printNow("Error: The input points must be in the image range !")
          return None

    new_w = abs(startPt[0] - endPt[0])
    new_h = abs(startPt[1] - endPt[1])

    if (new_w != new_h):
          printNow("Error: The input points do not form a square !")
          return None

    printNow("Given: (" + str(startPt[0]) + ", " + str(endPt[0]) + ") and (" \
                        + str(startPt[1]) + ", " + str(endPt[1]) + ")")

    newPicture = makeEmptyPicture(new_w, new_h)

    if (startPt[0] < endPt[0]):
        offsetX = startPt[0]
        switchX = False
        switchTB = True
    else:
        offsetX = endPt[0]
        switchX = True
        switchTB = False

    if (startPt[1] < endPt[1]):
        offsetY = startPt[1]
        switchY = False
    else:
        offsetY = endPt[1]
        switchY = True

    # (switchX  XOR  switchY)
    changeDiag = (switchX != switchY)

    mirror_pt = 0
    for x in range(0, new_w, 1):

        for y in range(mirror_pt, new_h, 1):
        #for y in range(0, new_h, 1):

            oldX = x
            oldY = y


            if (switchTB):
                sourcePixel = getPixel(picture, offsetX+new_w-1- oldX, offsetY+new_h-1- oldY)
            else:
                sourcePixel = getPixel(picture, offsetX+oldX, offsetY+oldY)
            color = getColor(sourcePixel)

            if (changeDiag):
                newX = new_w-1 - x
                newY = new_h-1 - y
                #printNow("Change Diag !")
            else:
                newX = x
                newY = y

            # Copied half
            if (switchTB):
                targetPixel = getPixel(newPicture, new_w-1- x, new_h-1- y)
            else:
                targetPixel = getPixel(newPicture, x, y)
            setColor(targetPixel, color)

            # Mirror half (simply invert x and y)
            if (switchTB):
                targetPixel = getPixel(newPicture, new_h-1- newY, new_w-1- newX)
            else:
                targetPixel = getPixel(newPicture, newY, newX)
            setColor(targetPixel, color)


        # Here we shift the mirror point
        if (not changeDiag):
            mirror_pt += 1


    return newPicture


file = pickAFile()
pic = makePicture(file)
picture = makePicture(file)

# Draw working area
drawLine(pic, white, 30, 60, 150, 180)
drawLine(pic, white, 30, 180, 150, 60)
drawLine(pic, black, 30, 60, 30, 180)
drawLine(pic, black, 30, 60, 150, 60)
drawLine(pic, black, 150, 60, 150, 180)
drawLine(pic, black, 30, 180, 150, 180)
show(pic)
writePictureTo(pic, "D:\\pic.png")

# Build cropped and mirrored areas
pic1 = diagCropAndMirrorPicture(picture, (150, 60), (30, 180))
pic2 = diagCropAndMirrorPicture(picture, (30, 180), (150, 60))
pic3 = diagCropAndMirrorPicture(picture, (150, 180), (30, 60))
pic4 = diagCropAndMirrorPicture(picture, (30, 60), (150, 180))

# Show cropped and mirrored areas
if (pic1):
    writePictureTo(pic1, "D:\\pic1.png")
    show(pic1)

if (pic2):
    writePictureTo(pic2, "D:\\pic2.png")
    show(pic2)

if (pic3):
    writePictureTo(pic3, "D:\\pic3.png")
    show(pic3)

if (pic4):
    writePictureTo(pic4, "D:\\pic4.png")
    show(pic4)

      




.................................................. .... enter image description here.............................................. ........


....... enter image description here.......... enter image description here.......... enter image description here.......... enter image description here.......



+2


source


I am assuming that you want to flip the 45 degree line and not the diagonal of the rectangle.

You need to create a new image, width is the height of the original and height is the width of the original.

If your origin is at the bottom left, copy point (x, y) in the original to position (y, x) in the new image. If it's a different angle, you need to think a little more;)

0


source







All Articles