简体   繁体   English

Python中的镜像对角线

[英]Mirror Image Diagonally in Python

I'm taking a programming class on python, and we're working on mirroring images by defining a mirror point and then copying a pixel from one side to the other using nested for loops. 我在python上学习编程类,我们正在通过定义镜像点然后使用嵌套for循环将像素从一侧复制到另一侧来镜像图像。 For example, mirroring 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'm currently working on an assignment question asking us to mirror an image diagonally so that the top left side gets reflected onto the bottom right side. 我正在处理一个任务问题,要求我们对角镜像,以便左上方反射到右下方。 Every example and answer that I've found so far only works for square images, and I need to be able to apply this to any image, preferably by defining a diagonal mirror point. 到目前为止,我发现的每个示例和答案仅适用于方形图像,我需要能够将其应用于任何图像,最好是通过定义对角镜像点。 I've been trying to define the mirror point using ay = mx + b style equation, but I can't figure out how to tell Python to make that a line. 我一直在尝试使用ay = mx + b样式方程来定义镜像点,但我无法弄清楚如何告诉Python使其成为一条线。 Any help not specific to square images would be appreciated! 任何不特定于方形图像的帮助将不胜感激!

Note: since I'm brand new here, I can't post images yet, but the diagonal mirror point would run from the bottom left to the top right. 注意:因为我在这里是全新的,我还不能发布图像,但是对角镜像点将从左下角到右上角。 The image in the top left triangle would be reflected to the bottom right. 左上角三角形中的图像将反射到右下角。

You can swap upper left with lower right of a non-square array 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 mirroring along the diagonal. 这适用于沿对角线镜像。 You appear to imply that you may want to mirror along some arbitrary location. 您似乎暗示您可能想要沿某个任意位置镜像。 In that case, you will need to decide how to fill in pixels that don't have a matching pixel on the opposite side of the mirror line. 在这种情况下,您需要决定如何填充镜像线另一侧没有匹配像素的像素。

You mention you are working on an assignment so you probably are required to 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 functions fliplr , flipud , and transpose . 你提到你正在进行一项任务,所以你可能需要明确地进行循环,但请注意,如果你将数据放入一个numpy数组,你可以通过numpy函数的组合轻松(并且更有效地)实现你想要的fliplrflipudtranspose

Note also that in your code example (mirroring left/right), you are copying the left pixel to the right side, but not vice versa so you are not actually mirroring the image. 另请注意,在您的代码示例中(镜像左/右),您将左侧像素复制到右侧,但反之亦然,因此您实际上并未镜像图像。

Just to share one way of mirroring diagonally, bottom-left to top-right : 只是分享一种对角镜像方式, 从左下角到右上角

The student is in charge to adapt, if he needs to mirror from "top-right to bottom-left" or to 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 were operating a vertical mirror for each line of pixels independently, along the vertical axis passing by the mirrorPt point. 注意:这表现就像我们独立地为每行像素操作一个垂直镜像,沿着垂直轴经过mirrorPt点。


Output ( Painting by Antoni Tapies ): 输出( Antoni Tapies绘画 ):


................. ................. 在此输入图像描述 ................. ................. 在此输入图像描述 .................. ..................






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's 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)




...................................................... .................................................. .... 在此输入图像描述 ...................................................... .................................................. ....


....... ....... 在此输入图像描述 .......... .......... 在此输入图像描述 .......... .......... 在此输入图像描述 .......... .......... 在此输入图像描述 ....... .......



I assume you want to mirror according to a 45 degree line, not the rectangle diagonal. 我假设您要根据45度线而不是矩形对角线进行镜像。

You have to create a new image, it's width is height of original, and it's height is width of original. 你必须创建一个新的图像,它的宽度是原始的高度,它的高度是原始的宽度。

If origin of your coordinate system is bottom left, copy the point (x, y) in the original in the (y, x) position in the new image. 如果坐标系的原点位于左下角,请复制新图像中(y,x)位置原稿中的点(x,y)。 If it's another corner, you have to think a bit more ;) 如果它是另一个角落,你必须多思考一下;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM