1

I'm trying to write a script that will allow the user to select a folder with images and then save the coordinates of the user's clicks on each image. To do this I would like to display each image file on a Tkinter canvas, save click locations, then when the canvas is closed, open the next image.

I can get this to work for a single image with the code below (adapted from this question). I was hoping the for File in imgs loop would keep opening the next image, but it does not. I suspect I need a on_closing function to tell Tkinter to open another image.

What's the proper way to have Tkinter open the next image after closing an image?

from Tkinter import *
from tkFileDialog import askopenfilenames, askopenfilename, askdirectory
from PIL import Image, ImageTk
import cv2
import numpy as np
import os

if __name__ == "__main__":
    root = Tk()

    #setting up a tkinter canvas with scrollbars
    frame = Frame(width=1920, height=1080, bd=2, relief=SUNKEN)
    frame.grid_rowconfigure(0, weight=1)
    frame.grid_columnconfigure(0, weight=1)
    xscroll = Scrollbar(frame, orient=HORIZONTAL)
    xscroll.grid(row=1, column=0, sticky=E+W)
    yscroll = Scrollbar(frame)
    yscroll.grid(row=0, column=1, sticky=N+S)
    canvas = Canvas(frame, bd=0, xscrollcommand=xscroll.set, yscrollcommand=yscroll.set)
    canvas.config(width=1920, height=1080)
    canvas.grid(row=0, column=0, sticky=N+S+E+W)
    xscroll.config(command=canvas.xview)
    yscroll.config(command=canvas.yview)
    frame.pack(fill=BOTH,expand=1)

    # Function to be called when mouse is clicked
    def save_coords(event):
        coords.append([event.x, event.y])

    # def on_closing():
        # Open the next image file


    # Create empty list for coordinate arrays to be appended to
    coords = []

    # Choose multiple images
    img_dir = askdirectory(parent=root, initialdir="D:/Temp/", title='Choose folder')
    os.chdir(img_dir)
    imgs = os.listdir(img_dir)
    #imgs = askopenfilenames(parent=root, initialdir="D:/Temp/cvCal/", title='Choose images')
    for File in imgs:
        img = ImageTk.PhotoImage(Image.open(File).resize((1280,720), Image.ANTIALIAS))
        canvas.create_image(0,0,image=img,anchor="nw")
        canvas.config(scrollregion=canvas.bbox(ALL))
        canvas.bind("<Button 1>",save_coords)
        # on_closing()...

    root.mainloop()
Community
  • 1
  • 1
Evan
  • 1,960
  • 4
  • 26
  • 54
  • Why do you want a Canvas rather than a Label to show the image? Do you need the image to be scrollable? – Novel May 03 '17 at 21:10
  • It doesn't need to be scrollable, I just need to get the click locations. I've never used the Label widget, so I don't really have a good answer to your question, but I'm open to suggestions. – Evan May 03 '17 at 21:15

1 Answers1

3

It would be a lot easier if you can use a Label instead:

Also, note there is no reason to use ImageTk since loading an image from a file is built into tkinter as Tkinter.PhotoImage.

Also, I converted your wildcard import to a normal import; wildcard imports are messy and against PEP8.

Lastly, I don't know what you mean with 'on closing', so I added a button to advance to the next image. This will throw a StopIteration error on the last image that you will need to handle.

import Tkinter as tk
from tkFileDialog import askdirectory
import os

# Create empty list for coordinate arrays to be appended to
coords = []

# Function to be called when mouse is clicked
def save_coords(event):
    click_loc = [event.x, event.y]
    print "you clicked on", click_loc
    coords.append(click_loc)

# Function to load the next image into the Label
def next_img():
    img_label.img = tk.PhotoImage(file=next(imgs))
    img_label.config(image=img_label.img)

root = tk.Tk()

# Choose multiple images
img_dir = askdirectory(parent=root, initialdir="D:/Temp/", title='Choose folder')
os.chdir(img_dir)
imgs = iter(os.listdir(img_dir))

img_label = tk.Label(root)
img_label.pack()
img_label.bind("<Button-1>",save_coords)

btn = tk.Button(root, text='Next image', command=next_img)
btn.pack()

next_img() # load first image

root.mainloop()

print coords
Novel
  • 13,406
  • 2
  • 25
  • 41
  • That works great, thanks! I was using the ImageTk part to open png files, which doesn't seem to work with just the regular tkinter. Great to learn a new tkinter widget, too. – Evan May 03 '17 at 23:00