如何暂停for循环并等待用户输入matplotlib

时间:2017-11-13 20:35:34

标签: python image image-processing matplotlib

很抱歉,我的问题标题不是很容易阅读。

这是我的问题。

我正在尝试拍摄一个图片文件并遍历每个像素。

在每个像素上,我想显示像素文件图像的matplotlib图(已完成。)

一旦显示图形,我需要循环暂停,同时用户通过按“b”或“c”分类像素的颜色,然后用空格键关闭图形。

完成此操作后,我希望它加载下一个像素。但是我遇到的问题是for循环不会暂停。如果我在for循环中放置一个while循环,则该图形无法完成加载(保持为白色屏幕,滚动时鼠标转到加载圆圈)。

我是事件处理的新手,所以也许我错过了一些方法来做到这一点。

我也无法通过matplotlibs交互模式获得任何工作。

以下是我的代码,这是非常粗糙的我从今天早上才开始研究它。使用该类的唯一方法是 init ()。

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")

1 个答案:

答案 0 :(得分:2)

以下是更新图的示例,每次用户按 Space 时都会显示新图像。然后,用户需要按 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()