【问题标题】:Mirror Image Diagonally in Python在Python中对角镜像
【发布时间】:2013-01-24 07:36:21
【问题描述】:

我正在学习关于 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 让它成为一条线。任何不特定于方形图像的帮助将不胜感激!

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

【问题讨论】:

    标签: python image jython mirror jes


    【解决方案1】:

    这是一个相对简单的解决方案,适用于矩形图像。 此示例代码假设 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) 的右上角。要解决此问题,您需要使用宽度和高度的百分比。

    【讨论】:

      【解决方案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)
      




      ..................................................... ...................................................... ......


      ..............................@ 987654327@.......



      【讨论】:

      • 你好! ;) 很高兴你喜欢它。我正在精确地对我新发布的答案链接进行分组,以指向您,以便向您发送电子邮件……但您已经找到它们了……
      • 好的,那我用法语给你写信!
      • 应该的。你确定你使用完全“平方”的图片作为输入吗?你得到什么错误?我在我的答案中添加了一张支票以拒绝非平方图片。干杯。
      • @Yve 如果您仍然对翻转和/或镜像图像感兴趣,我使用更完整的算法增强了上面的答案,允许在对角线镜像时所有 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 函数 fliplrflipudtranspose

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

      【讨论】:

        【解决方案4】:

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-04-11
          • 1970-01-01
          相关资源
          最近更新 更多