3

我正在学习关于 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)

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

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

4

4 回答 4

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 函数轻松(并且更有效地)实现您想要的fliplr, flipud, 和transpose.

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

于 2013-02-08T14:49:20.740 回答
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绘画):


……………………………………………………………………………………………………………… 在此处输入图像描述_ 在此处输入图像描述_ ..






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

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




..................................................... ………………………………………………………………………………………………………………………………………… 在此处输入图像描述_ ...........


……………………………………………………………………………………………………………………………………………………………………………… 在此处输入图像描述_ 在此处输入图像描述_ 在此处输入图像描述_ 在此处输入图像描述_



于 2013-06-29T12:42:04.557 回答
0

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

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

如果坐标系的原点在左下角,则将原点 (x, y) 复制到新图像的 (y, x) 位置。如果它是另一个角落,你必须多想一点;)

于 2013-02-08T14:28:54.487 回答
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) 的右上角。为了解决这个问题,您需要使用宽度和高度的百分比。

于 2021-05-10T10:36:59.390 回答