【问题标题】:pyplot figure only updating after second call to ginput()pyplot 图仅在第二次调用 ginput() 后更新
【发布时间】:2020-06-23 06:52:22
【问题描述】:

我有一个方法,它使用 matplotlib.pyplot.ginput() 从坐标区收集单击的位置,然后将图像放置在同一图中现有的坐标轴阵列中的该位置。

视觉只在第二次调用 ginput() 后更新,这意味着它的响应与用户的点击相比是滞后的,只有当他们选择下一个位置时,他们刚刚放置的图像才会显示。这是有问题的,因为放置的随机图片可能会影响他们接下来要点击的位置。

调用方法如下所示,虽然这里是绘制轴而不是添加图像:

%matplotlib
from matplotlib import pyplot
import numpy
import random

dimensions = [10,10]

visual_width = 1366
visual_height = 768
print("Established screen dimensions as "+str(visual_width)+","+str(visual_height))
         
fig, axarr = pyplot.subplots(dimensions[1],dimensions[0]
                               , num="Live game visualised"
                            , figsize=(visual_width, visual_height)
                            , clear=True)
fig.set_size_inches(visual_width, visual_height, forward=False)
overax = fig.add_subplot(111)
overax.axis("off")
#remove axes for initial rendering
for horizontal in range(0, dimensions[0]):
    for vertical in range(0, dimensions[1]):
        axarr[vertical, horizontal].axis('off')
text = fig.text(0,0, "", va="bottom", ha="left")

# test repeated interactions with figure, through successively adding tiles to the play area
playing = True
while playing:
    click = pyplot.ginput()
    if not click:
        break
    
    horizontal = int(click[0][0]*dimensions[0])
    vertical = dimensions[1] - int(click[0][1]*dimensions[1])
    print(str(horizontal)+","+str(vertical))
    text.set_text(str(horizontal)+","+str(vertical))
    axarr[vertical-1, horizontal].axis("on")

我的 python 3 脚本在 jupyter notebook 中,但我使用默认的 %matplotlib 后端弹出视觉效果。我在 Ubuntu 上使用 Chrome。

【问题讨论】:

  • 显示运行的东西。编写与您的项目无关的最少代码,以重现相同的错误。在你完成之前,你怎么能说你知道问题是什么,更不用说让别人帮你解决了?
  • 在上面,但同时希望有人能认出 ginput 行为...
  • 我不相信它是 ginput。这就是为什么我认为您应该首先正确隔离问题
  • 感谢@MadPhysicist 的推动。我现在已将其清理为运行并重现行为的上述脚本。

标签: python python-3.x matplotlib ginput


【解决方案1】:

这是一个 hacky 且不令人满意的解决方案,但我的解决方法是提示双击,并接受对 ginput 的第一次调用是将存储到分配给第二次调用的变量的数据:

%matplotlib
from matplotlib import pyplot
import numpy
import random

dimensions = [10,10]

visual_width = 1366
visual_height = 768
print("Established screen dimensions as "+str(visual_width)+","+str(visual_height))
         
fig, axarr = pyplot.subplots(dimensions[1],dimensions[0]
                               , num="Live game visualised"
                            , figsize=(visual_width, visual_height)
                            , clear=True)
fig.set_size_inches(visual_width, visual_height, forward=False)
overax = fig.add_subplot(111)
overax.axis("off")
#remove axes for initial rendering
for horizontal in range(0, dimensions[0]):
    for vertical in range(0, dimensions[1]):
        axarr[vertical, horizontal].axis('off')
text = fig.text(0,0, "", va="bottom", ha="left")

# test repeated interactions with figure, through successively adding tiles to the play area
playing = True
while playing:
    pyplot.ginput()
    click = pyplot.ginput()
    if not click:
        break
    
    horizontal = int(click[0][0]*dimensions[0])
    vertical = dimensions[1] - int(click[0][1]*dimensions[1])
    print(str(horizontal)+","+str(vertical))
    text.set_text(str(horizontal)+","+str(vertical))
    axarr[vertical-1, horizontal].axis("on")
    
    text.set_text("Double click to make your next move")   

【讨论】:

    【解决方案2】:

    我想我的问题和你的类似。我正在使用我自己的方法放大ginput 选择的图像区域。

    这是我使用plt.ionplt.draw 的解决方案,在我的脚本中运行良好。 image super resolution 方法被删除。

    #!/usr/bin/env python
    import matplotlib.pyplot as plt
    import numpy as np
    
    import argparse
    import sys
    
    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument(
        "-i", "--image_name", type=str, default="test.jpg", help="Input image path"
    )
    args = parser.parse_known_args(sys.argv[1:])[0]
    
    plt.ion()  # works in `.py` scripts
    imm = plt.imread(args.image_name)
    fig = plt.figure()
    plt.imshow(imm)
    plt.tight_layout()
    plt.show()
    
    imms = [imm]
    while True:
        aa = plt.ginput(2, timeout=-1)
        aa = np.array(aa)
    
        left, right = int(aa[:, 0].min()), int(aa[:, 0].max())
        top, bottom = int(aa[:, 1].min()), int(aa[:, 1].max())
    
        if right - left < 1 or bottom - top < 1:  # Double click to return
            if len(imms) > 1:
                imms.pop(-1)
            else:
                break
        else:
            sub_image = imms[-1][top:bottom, left:right, :]
            imms.append(sub_image)
        plt.imshow(imms[-1])
        plt.draw()  # works in `ipython` environment
    

    在我的测试中:

    • 在不添加最后一个 plt.draw 的情况下添加 plt.ion.py 脚本中仍然有效。
    • 添加最后一个 plt.draw 而不添加 plt.ionipython 环境中有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-25
      • 1970-01-01
      • 2022-11-11
      • 2022-01-20
      • 1970-01-01
      相关资源
      最近更新 更多