Как использовать «blit» в matplotlib для написания программы, которая может использовать движение «drag» для просмотра другой части изображения - PullRequest
0 голосов
/ 28 января 2020

Я пытаюсь использовать matplotlib для написания программы, которая после масштабирования изображения, отображаемого на объекте plt.figure, когда я выполняю движение "щелчок и перетаскивание мышью", отображающая часть будет двигаться в направлении моего перетаскивания, поэтому я могу увидеть другую часть изображения с помощью установки предела x / y.

Я знаю, что самый простой способ - использовать функцию canvas.draw () после сброса предела x / y, например

ax.set_xlim([x1,x2])
ax.set_ylim([y1,y2])
ax.figure.canvas.draw()

Но в моей формальной программе на рисунке будет не только изображение, но и множество других объектов, таких как текст или линия, и если я использую canvas.draw (), он будет перерисовывать все, включая те объекты, которые не меняются вообще и серьезно повредят производительности программы. Чтобы использовать наименьшее количество ресурсов для функции перетаскивания, я решил использовать функцию «blit», вот мой игрушечный пример

import matplotlib.pyplot as plt

class toy(object):
 def dragstart(self, event):
    # 'button_press_event'

    if not event.inaxes:
        return
    if event.button == 1:
        self.dragstate = 'move'
        x, y = event.xdata, event.ydata
        self.mouseloc = [x, y]


 def dragstop(self, event):
    # 'button_release_event'
    if event.button == 1:
        self.dragstate = 'stop'


 def drag(self, event):
    #Prevent multiple event happening
    if self.dragprocessing:
        return
    self.dragprocessing = True


    if not event.inaxes or self.dragstate != 'move':

        self.dragprocessing = False
        return


    #Calculate the displacement
    xloc, yloc = event.xdata, event.ydata
    xdelta = -(xloc - self.mouseloc[0])
    ydelta = -(yloc - self.mouseloc[1])
    self.mouseloc = [xloc, yloc]

    newxleft = self.last[0] + xdelta
    newxright = self.last[1] + xdelta
    newyup = self.last[2] + ydelta
    newydown = self.last[3] + ydelta

    #Border check
    if newxright > self.limit[0] - 0.5:
        over = newxright - (self.limit[0] - 0.5)
        newxright = self.limit[0] - 0.5
        newxleft -= over

    if newxleft < -0.5:
        over = -0.5 - newxleft
        newxleft = -0.5
        newxright += over


    if newydown > self.limit[1] - 0.5:
        over = newydown - (self.limit[1] - 0.5)
        newydown = self.limit[1] - 0.5
        newyup -= over

    if newyup < -0.5:
        over = -0.5 - newyup
        newyup = -0.5
        newydown += over
    newposition = [newxleft, newxright, newyup, newydown]


    #Set new limit
    self.ax.set_xlim([newxleft, newxright])
    self. ax.set_ylim([newydown, newyup])


    #Only draw the changing part
    #The formal project contents lots of other objects such as text or line, redraw everything will be slow
    self.ax.draw_artist(self.ax.images[0])
    self.ax.draw_artist(self.ax.yaxis)
    self.ax.draw_artist(self.ax.xaxis)
    self.ax.figure.canvas.blit()


    self.last = newposition
    self.mouseloc = [xloc + xdelta, yloc + ydelta]
    self.dragprocessing = False

  def __call__(self, images):


    fig, ax = plt.subplots()
    ax.imshow(images)
    h = images.shape[0]
    w = images.shape[1]
    self.limit = [w, h]
    ax.set_ylim([400, 200])#just an example
    ax.set_xlim([200, 400])#just an example

    self.dragprocessing = False
    self.last = [200, 400, 200, 400]#present x/y limit
    self.dragstate = 'stop'

    self.ax=ax
    self.fig=fig
    fig.canvas.mpl_connect('button_press_event', self.dragstart)
    fig.canvas.mpl_connect('button_release_event', self.dragstop)
    fig.canvas.mpl_connect('motion_notify_event', self.drag)

    plt.show()


 imagenow = plt.imread("path/to/my/image")
 test=toy()
 test(imagenow)

Обратите внимание, что я использую «self.ax.figure.canvas.blit». () "вместо" self.ax.figure.canvas.blit (self.ax.bbox) ", поскольку последний ничего не обновит на оси.
Проблема в том, что стержень оси x / y будет перекрывать каждый время обновления x / y лимита, как это Example of dragging

Есть ли какое-то неправильное использование в моем игрушечном примере "blit", который вызывает проблему? Как это исправить или есть лучший способ сделать работу?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...