2017-11-13 18 views
1

申し訳ありませんが、私の質問のタイトルは読みにくいです。forループを一時停止してユーザ入力を待つ方法matplotlib

これは私の問題です。

私は画像ファイルを撮り、すべてのピクセルをループしようとしています。私はピクセルファイルの画像のmatplotlibのフィギュア表示する各ピクセルに

(行われています。)

図は、ユーザーがすることにより、画素の色を分類しながら、私は一時停止し、私のループを必要と表示されたら'b'または 'c'を押してから、スペースバーでFigureを閉じます。

この操作が完了したら、次のピクセルをロードします。しかし、私が持っている問題は、forループが一時停止しないということです。 forループの中にwhileループを置くと、Figureはロードを終了しません(白い画面のままで、マウスをスクロールするとローディングサークルに変わります)。

私はイベントハンドリングに新しいので、おそらく私はこれを行うにはいくつかの方法がありません。

matplotlibsインタラクティブモードで動作させることもできません。

以下は私のコードですが、それは非常に荒いです。私は今朝からそれに取り組んできました。使用されているクラスの唯一のメソッドはです。()です。

from scipy.misc import imread 
from PIL import Image 
import numpy as np 
import matplotlib.pyplot as plt 

class images(object): 

def __init__(self,img,flat=False,mod='RGB',show=True): 
    'File types to compare to' 
    file_type_list =['.jpg','.bmp','.gif','.png'] 
    'Create assertion error if not right fiel type' 
    assert(any(img[-4:] for x in file_type_list)),"Wrong file formate please use: JPEG, BMP, GIF, or PNG" 
    'Read image file to numpy array' 
    self.img=imread(img,flatten=flat,mode=mod)   
    'Show image in matplotlib plot if selected by user' 
    if show == True: 
     fig, ax = plt.subplots() 
     ax.imshow(self.img)   

def arr_to_vector(self): 
    'Convert 3D image array into 2D vector [no. pixels,3(RGB)]' 
    self.img_vector = self.img.reshape(-1,self.img.shape[2]) 
    return self.img_vector 

def gray_vector(self): 
    'Convert 3D image array into 1D vector [no. pixels in grayscale]' 
    img_vector = self.img.reshape(-1,self.img.shape[2]) 
    self.g_img_vector = np.mean(img_vector,axis=1) 
    return self.g_img_vector 

def plotter(self): 
    self.fig = plt.figure() 
    plt.imshow(self.img) 

def disp_pixel(i): 
    tmp = allsamecolor(Img.img,i) 
    fig = plt.figure() 
    plt.imshow(tmp) 
    plt.show() 
    cid = fig.canvas.mpl_connect('key_press_event',on_key) 
    return fig.number, fig 

def on_key(event): 
    if event.key == ' ': 
     plt.close(event.canvas.figure) 
     return event.key 
    else: 
     if event.key == 'b': 
      print(event.key) 
      labels.append('black') 
     elif event.key == 'c': 
      print(event.key) 
      labels.append('copper') 

def assign(x,i): 
    x = i 
    return x 

def allsamecolor(img, i): 
    fv = np.vectorize(assign) 
    ret = fv(img,i) 
    return ret 

img = 'C:/Temp/test.jpg' 

Img = images(img,show=False) 

v = Img.arr_to_vector() 

labels = [] 

n = 0 
for i in v: 
    x, fig = disp_pixel(i) 
    print(x) 
    input("Press <ENTER> to continue") 
+0

なぜ図を閉じたいのですか?それを開いたままにして、ユーザーが* space *を押したときに次の画像を表示するほうがよかったですか? – ImportanceOfBeingErnest

+0

はい、それは方法がよかったです...しかし、私はそれを行う方法について何かを見つけることができませんでした。 – awsmagala

答えて

1

以下は、新しい画像が、ユーザがスペースを押すたびに示されている更新図の一例であろう。ユーザーは、画像内に青色または赤色が多く見えるかどうかによって、bまたはrのいずれかを押す必要があります。ユーザ入力は、画像の平均値とともに格納される。 Nの画像の完成後、結果はグラフとして視覚化される。

これは、プロットウィンドウのイベントループ内で完全なコードを実行できることを示しています。

import numpy as np 
import matplotlib.pyplot as plt 

class Quest(): 
    def __init__(self, N = 5, bias=0): 
     self.bias = bias 
     self.N = N 
     self.resImage = np.zeros(self.N) 
     self.resUser = np.zeros(self.N) 
     self.mapping = {"b" : -1,"r" : 1} 

    def start(self): 
     self.fig, self.ax = plt.subplots() 
     self.i = 0 
     self.im = self.ax.imshow(np.zeros((3,3)), norm=plt.Normalize(-1,1),cmap="bwr") 
     self.cid = self.fig.canvas.mpl_connect("key_press_event", self.user_input) 
     self.next_image() 
     plt.show() 

    def next_image(self): 
     im = self.generate_image() 
     self.resImage[self.i] = im.mean() 
     self.im.set_data(im) 
     self.fig.canvas.draw_idle() 

    def user_input(self, event=None): 
     if event.key == ' ': 
      if self.i < self.N-1: 
       self.i += 1 
       self.next_image() 
      else: 
       self.show_result() 
     elif event.key in self.mapping.keys(): 
      self.resUser[self.i] = self.mapping[event.key.lower()] 
     else: 
      return 

    def show_result(self): 
     self.ax.clear() 
     self.ax.scatter(range(self.N), self.resImage, label="images") 
     self.ax.scatter(range(self.N), self.resUser, label="user") 
     self.ax.axhline(self.bias, color="k") 
     self.ax.legend() 
     self.fig.canvas.draw_idle() 


    def generate_image(self): 
     return np.random.normal(self.bias,0.7, size=(3,3)) 

q = Quest() 
q.start() 
関連する問題