Я загружаю фигуру jpeg (large: 1300x2000) в matplotlib, рисуя сетку из 50x50 квадратов над ней и нажимая на каждый квадрат, чтобы присвоить цветному коду. Тем не менее, я замечаю, что программа значительно отстает от моих кликов и занимает до 30 секунд, чтобы догнать, если я быстро разберусь на 50 квадратов с разумной скоростью. Мне интересно, сможет ли кто-то ускорить работу. Ниже приведен мой сценарий, который готов к работе, если вы скопируете/вставьте его (и имеете scipy, numpy, matplotlib, pillow и tkinter).Ускорьте мой интерактивный рисунок matplotlib
Любые советы приветствуются. Я ученый-медик, так пожалуйста, прости меня, если код не очень хорошо объяснил:
import matplotlib
import matplotlib.pyplot as plt
import tkinter
import tkinter.filedialog
from matplotlib.figure import Figure
import math, sys
import numpy as np
import scipy.io as sio
from PIL import Image
from numpy import arange, sin, pi
#from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
#matplotlib.matplotlib_fname()
import os, re
global stridesize, classnumber,x, im,fn, plt, fig, mask
classnumber = 1
def onmove(eve):
global x,im, plt
print(eve.ydata)
print(eve.button)
if (eve.ydata !=None) and (eve.xdata !=None):
if eve.button==1:
print(eve.button)
xcoord = int(eve.xdata)
ycoord = int(eve.ydata)
startX = math.floor(xcoord/stridesize)*stridesize
startY = math.floor(ycoord/stridesize)*stridesize
# print(eve.xdata, int(eve.ydata), stridesize)
if(classnumber==1):
mask[startY:startY+stridesize,startX:startX+stridesize,:]=np.array([255,0,0])
if(classnumber==2):
mask[startY:startY+stridesize,startX:startX+stridesize,:]=np.array([0,255,0])
if(classnumber==3):
mask[startY:startY+stridesize,startX:startX+stridesize,:]=np.array([0,0,255])
if(classnumber==4):
mask[startY:startY+stridesize,startX:startX+stridesize,:]=np.array([255,0,255])
if(classnumber==5):
mask[startY:startY+stridesize,startX:startX+stridesize,:]=np.array([255,255,0])
if(classnumber==6):
mask[startY:startY+stridesize,startX:startX+stridesize,:]=np.array([0,255,255])
if(classnumber==7):
mask[startY:startY+stridesize,startX:startX+stridesize,:]=np.array([100,255,50])
if eve.button==3:
xcoord = int(eve.xdata)
ycoord = int(eve.ydata)
startX = math.floor(xcoord/stridesize)*stridesize
startY = math.floor(ycoord/stridesize)*stridesize
print(eve.xdata, int(eve.ydata), stridesize)
mask[startY:startY+stridesize,startX:startX+stridesize,:]=np.array([0,0,0])
im.set_data(mask)
fig.canvas.draw()
def onclick(event):
if (event.ydata !=None) and (event.xdata !=None):
global x, im, fig
if event.button==1:
xcoord = int(event.xdata)
ycoord = int(event.ydata)
startX = math.floor(xcoord/stridesize)*stridesize
startY = math.floor(ycoord/stridesize)*stridesize
print(event.xdata, int(event.ydata), stridesize)
if(classnumber==1):
mask[startY:startY+stridesize,startX:startX+stridesize,:]=np.array([255,0,0])
if(classnumber==2):
mask[startY:startY+stridesize,startX:startX+stridesize,:]=np.array([0,255,0])
if(classnumber==3):
mask[startY:startY+stridesize,startX:startX+stridesize,:]=np.array([0,0,255])
if(classnumber==4):
mask[startY:startY+stridesize,startX:startX+stridesize,:]=np.array([255,0,255])
if(classnumber==5):
mask[startY:startY+stridesize,startX:startX+stridesize,:]=np.array([255,255,0])
if(classnumber==6):
mask[startY:startY+stridesize,startX:startX+stridesize,:]=np.array([0,255,255])
if(classnumber==7):
mask[startY:startY+stridesize,startX:startX+stridesize,:]=np.array([100,255,50])
im.set_data(mask)
if event.button==3:
xcoord = int(event.xdata)
ycoord = int(event.ydata)
startX = math.floor(xcoord/stridesize)*stridesize
startY = math.floor(ycoord/stridesize)*stridesize
print(event.xdata, int(event.ydata), stridesize)
mask[startY:startY+stridesize,startX:startX+stridesize,:]=np.array([0,0,0])
im.set_data(mask)
fig.canvas.draw()
def onpress(event):
global classnumber, mask
if (event.key == 'e'):
print("YO")
mask[:,:,:]=0;
im.set_data(mask)
fig.canvas.draw()
if (event.key=='s'):
savemask(fn)
if (event.key=='r'):
plt.figure();
plt.imshow(mask);
plt.show();
if int(event.key) > 0 and int(event.key) <9 :
classnumber = int(event.key)
print(classnumber)
def onrelease(event):
print(event.button)
# im.set_data(mask)
def savemask(fn):
# matrixname =os.path.basename(filename)
# matrixname = re.sub(r'\.jpg','',matrixname)
pre, ext = os.path.splitext(fn)
savename_default = os.path.basename(pre)
options = {}
options['defaultextension'] = ''
options['filetypes'] = [('mat files', '.mat')]
options['initialdir'] = ''
options['initialfile'] = savename_default
options['title'] = 'Save file'
f = tkinter.filedialog.asksaveasfile(**options)
if f is None: # asksaveasfile return `None` if aadialog closed with "cancel".
return
name = f.name
sio.savemat(name,{'mask':mask},do_compression=True)
f.close()
root = tkinter.Tk()
root.withdraw()
options = {}
options['defaultextension'] = '.jpg'
options['filetypes'] = [('Jpeg', '.jpg')]
options['initialdir'] = 'C:\\'
options['initialfile']= ''
options['parent'] = root
options['title'] = 'This is a title'
fn= tkinter.filedialog.askopenfilename(**options)
img = Image.open(fn)
x = np.asarray(img)
x.setflags(write=1)
#masksize= (x.shape[0],x.shape[1],4)
mask= np.zeros(x.shape,'uint8')
#mask[:,:,3]=0.2
fig = plt.figure()
fig.suptitle(r'Key codes: 1 = Tumour, 2 = stroma-hypocellular, 3=stroma cellular (inflammatory)' '\n4 = proteinaceous, 5= red cells, 6,7: anyother,''\nRight click: clear square''\n r: review mask, e: erase mask, o : open mask image, s : save mask image;')
im=plt.imshow(x)
im=plt.imshow(mask,alpha=.25)
ax = plt.gca();
stridesize = 50;
plt.rcParams['keymap.save']=''
ax.set_yticks(np.arange(0, x.shape[0], stridesize));
ax.set_xticks(np.arange(0, x.shape[1], stridesize));
cid = fig.canvas.mpl_connect('button_press_event', onclick)
cod = fig.canvas.mpl_connect('key_press_event', onpress)
#cdd = fig.canvas.mpl_connect('motion_notify_event', onmove)
cdr = fig.canvas.mpl_connect('button_release_event', onrelease)
plt.grid(b=True, which='both', color='black',linestyle='-')
#
plt.show()
plt.ion()
Для тех, кто заинтересован в том, чтобы знать, что было в корне неправильно с помощью кода выше, изменение одной линии удвоило скорость. Поэтому я изменил каждый вызов: fig.canvas.draw() на fig.canvas.draw_idle() – Maelstorm