Python中的镜像对角线

时间:2013-02-08 14:00:39

标签: python image jython mirror jes

我正在使用python上的编程类,我们正在通过定义镜像点然后使用嵌套for循环将像素从一侧复制到另一侧来镜像图像。例如,垂直镜像图像将使用以下代码:

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)

我正在处理一个任务问题,要求我们对角镜像,以便左上侧反射到右下方。到目前为止,我发现的每个示例和答案仅适用于方形图像,我需要能够将其应用于任何图像,最好是通过定义对角镜像点。我一直在尝试使用y = mx + b样式方程定义镜像点,但我无法弄清楚如何告诉Python使这一行成为一条线。任何不特定于方形图像的帮助都将不胜感激!

注意:由于我在这里是全新的,我还不能发布图像,但是对角镜像点将从左下角到右上角。左上角三角形中的图像将反射到右下角。

4 个答案:

答案 0 :(得分:3)

您可以将左上角与非方阵列的右下角交换,如下所示:

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

这适用于沿对角线镜像。您似乎暗示您可能想要沿某个任意位置镜像。在这种情况下,您需要决定如何填充镜像线另一侧没有匹配像素的像素。

你提到你正在进行一项任务,所以你可能需要明确地进行循环,但请注意,如果你将数据放入一个numpy数组中,你可以轻松(并且更有效地)实现你想要的结合numpy函数fliplrflipudtranspose

另请注意,在您的代码示例中(镜像左/右),您将左侧像素复制到右侧,但反之亦然,因此您实际上并未镜像图像。

答案 1 :(得分:2)

只是分享对角镜像的一种方式,从左下角到右上角

学生负责适应,如果他需要从“从右上角到左下角”镜像或使用相反的对角线。

# !! 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)

注意:这就好像我们独立地为每行像素操作一个垂直镜像,沿着垂直轴经过mirrorPt点。


输出( Antoni Tapies绘画 ):


................. enter image description here {................. {0}} ... ...............






以下是实验性的,只是为了好玩...

# 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)




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


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



答案 2 :(得分:0)

我假设您要根据45度线而不是矩形对角线进行镜像。

你必须创建一个新的图像,它的宽度是原始的高度,它的高度是原始的宽度。

如果坐标系的原点位于左下角,请复制新图像中(y,x)位置原稿中的点(x,y)。如果它是另一个角落,你必须多考虑一点;)

答案 3 :(得分:0)

这是一个相对简单的解决方案,适用于矩形图像。 此示例代码假设 sourceImage 来自 Python Pillow 库,但概念是通用的。

## WORKS WITH RECTANGLES! 
def mirrorDiagonal(sourceImage):
    copyImage = sourceImage
    width = copyImage.width
    height = copyImage.height
    for y in range(0,height):
        ##The for loop for X is bounded by a slope of width to height.
        mirrorPoint = int((width/height)*y)
        for x in range(0, mirrorPoint):
            leftPixel = copyImage.getpixel((x,y))
            percentageX = float(x / width)
            percentageY = float(y / height)
            rightPixel = sourceImage.getpixel((width*percentageY, height*percentageX))
            copyImage.putpixel((x,y),rightPixel)
    return copyImage

本质上,您按照其他人提到的方法来交换 x 和 y 坐标。但是,对于矩形,如果您只是交换坐标,则会得到一条不会从角到角的对角线。例如,对于 1000 x 2000 像素的图像,交换角 (1000, 0) 会给你 (0, 1000),只有图像的一半。

我假设您真正想要的是将 (0, 2000) 的左下角反射到 (1000, 0) 的右上角。要解决此问题,您需要使用宽度和高度的百分比。