2

Sorry my question title is not very easy to read through.

This is my problem.

I am trying to take a picture file and loop through every pixel.

On each pixel I want to display a matplotlib figure of the image of the pixel file (done.)

Once the figure is displayed I need my loop to pause while the user classifies the color of the pixel by either pressing 'b' or 'c' and then closes the figure with the space bar.

Once this operation is done I want it to load the next pixel. However the issue I am having is the for loop doesn't pause. If I put a while loop inside the for loop the figure doesn't ever finish loading (stays as a white screen and the mouse turns to the loading circle when scrolling over it).

I am new to event handling so maybe I am missing some way to do this there.

I also cannot get anything with matplotlibs interactive mode to work.

Below is my code, it is very rough I have only been working on it since this morning. The only method in the class being used is 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")
2
  • Why do you want to close the figure at all? Wouldn't it be nicer to keep it open and just show the next image inside when the user presses space. Commented Nov 13, 2017 at 20:43
  • Yes that would be way nicer...i couldn't find anything on how to do that however. Commented Nov 13, 2017 at 20:58

1 Answer 1

2

The following would be an example of an updating figure, where new images are shown each time the user presses Space. The user then needs to press either b or r depending on whether he sees more blue or more red in the picture. The user input is stored, as well as the mean values of the image. After completion of N images, the result is visualized as a graph.

The idea behind this is to show that the complete code can run inside the plotting window's event loop.

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()
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.