Python Forum
Get the image's coordinates not the canvas' when navigate on an image
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Get the image's coordinates not the canvas' when navigate on an image
#1
So, the idea is that I try to load an image, navigate Up, Down, Right, Left with the arrows and each time I press the mouse button to get the image's coordinates, not the canvas' coordinates. I use code from here: https://stackoverflow.com/questions/5563...s-of-the-s and from here: https://stackoverflow.com/questions/3366...arrow-keys I face difficulties in achieving that... more specifically none of the keys Up, Down, Left, Right works and also when I press the mouse button nothing happens... My code is depicted below...Do you have any idea what I wrote wrong?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
print("A")
import tkinter as tk
print("B")
from PIL import Image, ImageTk
print("C")
 
#class Example(tk.Frame):
    #print("D")
    ##def __init__(self, parent):
        ##print("0")
        ##tk.Frame.__init__(self, parent)
print("1")
WIDTH, HEIGHT = 900, 900
print("2")
topx, topy, botx, boty = 0, 0, 0, 0
print("3")
rect_id = None
print("4")
path = "test_image.jpg"
print("5")
 
def get_mouse_posn(event):
    print("6")
 
    topx, topy = event.x, event.y
    print("7")
    print("topx = ", topx)
    print("8")
    print("topy = ", topy)
    print("9")
 
def update_sel_rect(event):
    print("10")
 
    botx, boty = event.x, event.y
    print("11")
    canvas.coords(rect_id, topx, topy, botx, boty)  # Update selection rect.
    print("12")
    print("botx = ", botx)
    print("13")
    print("boty = ", boty)
 
 
window = tk.Tk()
print("14")
window.title("Select Area")
print("15")
window.geometry('%sx%s' % (WIDTH, HEIGHT))
print("16")
window.configure(background='grey')
print("17")
 
img = ImageTk.PhotoImage(Image.open(path))
print("18")
canvas = tk.Canvas(window, width=img.width(), height=img.height(),
                        borderwidth=0, highlightthickness=0)
print("19")
canvas.pack(expand=True)
print("20")
canvas.img = img  # Keep reference in case this code is put into a function.
print("21")
canvas.create_image(0, 0, image=img, anchor=tk.NW)
print("22")
 
# Create selection rectangle (invisible since corner points are equal).
rect_id = canvas.create_rectangle(topx, topy, topx, topy,
                                        dash=(2,2), fill='', outline='white')
print("23")
 
 
canvas = tk.Canvas(background="bisque")
print("24")
vsb = tk.Scrollbar(orient="vertical", command=canvas.yview)
print("25")
hsb = tk.Scrollbar(orient="horizontal", command=canvas.xview)
print("26")
canvas.configure(xscrollcommand=hsb.set, yscrollcommand=vsb.set)
print("27")
 
#canvas.grid(row=0, column=0, sticky="nsew")
print("28")
#vsb.grid(row=0, column=1, sticky="ns")
print("29")
#hsb.grid(row=1, column=0, sticky="ew")
print("30")
 
canvas.configure(scrollregion = canvas.bbox("all"))
print("31")
 
canvas.bind("<1>",     lambda event: canvas.focus_set())
print("32")
canvas.bind("<Left>"lambda event: canvas.xview_scroll(-1, "units"))
print("33")
canvas.bind("<Right>", lambda event: canvas.xview_scroll( 1, "units"))
print("34")
canvas.bind("<Up>",    lambda event: canvas.yview_scroll(-1, "units"))
print("35")
canvas.bind("<Down>"lambda event: canvas.yview_scroll( 1, "units"))
print("36")
canvas.focus_set()
print("37")
canvas.bind('<Button-1>', get_mouse_posn)
print("38")
canvas.bind('<B1-Motion>', update_sel_rect)
print("39")
 
window.mainloop()
Reply
#2
I have posted code, links, prints inside the code, I have showed effort. Can somebody help me here?
Reply
#3
Edited 6:32 EDT
In the future, please remove annoying print statements before posting.

Added bind statement after creating canvas, also renamed 'path' to 'imagefile'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import tkinter as tk
from PIL import Image, ImageTk
import os
 
 
os.chdir(os.path.abspath(os.path.dirname(__file__)))
 
WIDTH, HEIGHT = 900, 900
topx, topy, botx, boty = 0, 0, 0, 0
rect_id = None
imagefile = "test_image.jpg"
 
def get_mouse_posn(event):
    topx, topy = event.x, event.y
    print("topx = ", topx)
    print("topy = ", topy)
  
def update_sel_rect(event):
    botx, boty = event.x, event.y
    canvas.coords(rect_id, topx, topy, botx, boty)  # Update selection rect.
    print("botx = ", botx)
    print("boty = ", boty)
  
window = tk.Tk()
window.title("Select Area")
window.geometry('%sx%s' % (WIDTH, HEIGHT))
window.configure(background='grey')
 
img = ImageTk.PhotoImage(Image.open(imagefile))
canvas = tk.Canvas(window, width=img.width(), height=img.height(),
                        borderwidth=0, highlightthickness=0)
canvas.pack(expand=True)
canvas.img = img  # Keep reference in case this code is put into a function.
canvas.create_image(0, 0, image=img, anchor=tk.NW)
canvas.bind("<Button 1>", get_mouse_posn)
 
  
# Create selection rectangle (invisible since corner points are equal).
rect_id = canvas.create_rectangle(topx, topy, topx, topy,
                                        dash=(2,2), fill='', outline='white')
  
canvas = tk.Canvas(background="bisque")
vsb = tk.Scrollbar(orient="vertical", command=canvas.yview)
hsb = tk.Scrollbar(orient="horizontal", command=canvas.xview)
canvas.configure(xscrollcommand=hsb.set, yscrollcommand=vsb.set)
  
#canvas.grid(row=0, column=0, sticky="nsew")
#vsb.grid(row=0, column=1, sticky="ns")
#hsb.grid(row=1, column=0, sticky="ew")
  
canvas.configure(scrollregion = canvas.bbox("all"))
  
canvas.bind("<1>",     lambda event: canvas.focus_set())
canvas.bind("<Left>"lambda event: canvas.xview_scroll(-1, "units"))
canvas.bind("<Right>", lambda event: canvas.xview_scroll( 1, "units"))
canvas.bind("<Up>",    lambda event: canvas.yview_scroll(-1, "units"))
canvas.bind("<Down>"lambda event: canvas.yview_scroll( 1, "units"))
canvas.focus_set()
canvas.bind('<Button-1>', get_mouse_posn)
canvas.bind('<B1-Motion>', update_sel_rect)
  
window.mainloop()
hobbyist likes this post
Reply
#4
@Larz60+ Thank you so much for your time!!! The arrows do not work...what should I change?
Reply
#5
hobbyist Wrote:The arrows do not work
Very vague, be more specific.
Reply
#6
@Larz60+ I press Right, Left, Up, Down keys on the keyboard, the image is not moving...inside the canvas...
Reply
#7
In Larz60+'s post there are two canvas objects, one created in line 30 and the other in line 42. I think that was a mistake. Ends up that events are bound to different canvas widgets, and some are bound to the canvas that never gets focus. It would probably be better to have the canvas take focus when you click it

I think the answer to the original post question is that you need to find the location of the upper left corner and uses this to offset the mouse event coordinates. Look at get_mouse_posn() and update_sel_rect() in the code below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import tkinter as tk
from PIL import Image, ImageTk
 
WIDTH, HEIGHT = 900, 900
sel_rect = [0, 0, 0, 0]
imagefile = "large_image.jpg"
 
 
def get_mouse_posn(event):
    print(event.x, canvas.canvasx(0), canvas.canvasx(event.x))
    sel_rect[0] = sel_rect[2] = int(canvas.canvasx(event.x))
    sel_rect[1] = sel_rect[3] = int(canvas.canvasy(event.y))
    canvas.coords(rect_id, *sel_rect)
    canvas.focus_set()
 
 
def update_sel_rect(event):
    sel_rect[2] = int(canvas.canvasx(event.x))
    sel_rect[3] = int(canvas.canvasy(event.y))
    canvas.coords(rect_id, *sel_rect)
 
 
window = tk.Tk()
window.title("Select Area")
window.geometry("%sx%s" % (WIDTH, HEIGHT))
 
img = ImageTk.PhotoImage(Image.open(imagefile))
canvas = tk.Canvas(window, width=img.width(), height=img.height())
canvas.img = img  # Keep reference in case this code is put into a function.
canvas.create_image(0, 0, image=img, anchor=tk.NW)
canvas.bind("<Button 1>", get_mouse_posn)
 
 
# Create selection rectangle (invisible since corner points are equal).
rect_id = canvas.create_rectangle(*sel_rect, dash=(2, 2), fill="", outline="white")
 
vsb = tk.Scrollbar(orient="vertical", command=canvas.yview)
hsb = tk.Scrollbar(orient="horizontal", command=canvas.xview)
canvas.configure(xscrollcommand=hsb.set, yscrollcommand=vsb.set)
canvas.configure(scrollregion=canvas.bbox("all"))
 
canvas.bind("<Left>", lambda event: canvas.xview_scroll(-1, "units"))
canvas.bind("<Right>", lambda event: canvas.xview_scroll(1, "units"))
canvas.bind("<Up>", lambda event: canvas.yview_scroll(-1, "units"))
canvas.bind("<Down>", lambda event: canvas.yview_scroll(1, "units"))
canvas.bind("<Button-1>", get_mouse_posn)
canvas.bind("<B1-Motion>", update_sel_rect)
 
canvas.grid(row=0, column=0, sticky="nsew")
hsb.grid(row=1, column=0, sticky="ew")
vsb.grid(row=0, column=1, sticky="ns")
window.rowconfigure(0, weight=1)
window.columnconfigure(0, weight=1)
 
window.mainloop()
Another thing wrong with the original code is topx, topy, botx and boty were used inconsistently. In get_mouse_posn() and update_sel_rect() topx is a local variable, and setting the value does not change the topx value used in update_sel_rect. You could fix this by making all the variables global (using the global keyword in get_mouse_posn), but I decided to put them all together in a list. A better solution is to write this code as a class and make topx, topy, botx and boty attributes.
hobbyist likes this post
Reply
#8
@deanhystad and @Larz60+ you are awesome!!!!!! Thanks! it works!!
Reply
#9
What modifications I should do in order to print the Upper Left and Lower Right coordinates of the rectangle? I tried something but it does not work..
Reply
#10
You could print(sel_rect). It is important to note that the contents of sel_rect are not upper left and lower right, but rather two corners. Depending on how you drag the mouse the upper left corner might be the first corner (first two values) or the second (last two values in the list).

if upper left and lower right are important I would create a class that does all the rectangle selection stuff.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import tkinter as tk
from PIL import Image, ImageTk
 
WIDTH, HEIGHT = 900, 900
sel_rect = [0, 0, 0, 0]
imagefile = "large_image.jpg"
 
 
class RectangleSelection:
    """Class to encompass behavior of Rectangle selection"""
 
    def __init__(self, parent, *args, **kvargs):
        self.rect = [0, 0, 0, 0]
        self.parent = parent
        self.id = parent.create_rectangle(*self.rect, *args, **kvargs)
 
    def start(self, event):
        """Start new rectangle."""
        self.rect[0] = self.rect[2] = int(self.parent.canvasx(event.x))
        self.rect[1] = self.rect[3] = int(self.parent.canvasy(event.y))
        self.parent.coords(self.id, *self.rect)
        print(self)
 
    def extend(self, event):
        """Move corner 2"""
        self.rect[2] = int(self.parent.canvasx(event.x))
        self.rect[3] = int(self.parent.canvasy(event.y))
        canvas.coords(self.id, *self.rect)
        print(self)
 
    def upper_left(self):
        """Return x, y for upper left corner of rectangle"""
        return (min(self.rect[0], self.rect[2]), min(self.rect[1], self.rect[3]))
 
    def lower_right(self):
        """Return x, y for lower right corner of rectangle"""
        return (max(self.rect[0], self.rect[2]), max(self.rect[1], self.rect[3]))
 
    def coordinates(self):
        return (
            min(self.rect[0], self.rect[2]),
            min(self.rect[1], self.rect[3]),
            max(self.rect[0], self.rect[2]),
            max(self.rect[1], self.rect[3]),
        )
 
    def __repr__(self):
        return f"<Rectangle {self.coordinates()}>"
 
 
def button_press(event):
    rectangle.start(event)
    canvas.focus_set()
 
 
window = tk.Tk()
window.title("Select Area")
window.geometry("%sx%s" % (WIDTH, HEIGHT))
 
img = ImageTk.PhotoImage(Image.open(imagefile))
canvas = tk.Canvas(window, width=img.width(), height=img.height())
canvas.img = img  # Keep reference in case this code is put into a function.
canvas.create_image(0, 0, image=img, anchor=tk.NW)
 
# Create selection rectangle (invisible since corner points are equal).
rectangle = RectangleSelection(canvas, dash=(2, 2), fill="", outline="white")
 
vsb = tk.Scrollbar(orient="vertical", command=canvas.yview)
hsb = tk.Scrollbar(orient="horizontal", command=canvas.xview)
canvas.configure(xscrollcommand=hsb.set, yscrollcommand=vsb.set)
canvas.configure(scrollregion=canvas.bbox("all"))
 
canvas.bind("<Left>", lambda event: canvas.xview_scroll(-1, "units"))
canvas.bind("<Right>", lambda event: canvas.xview_scroll(1, "units"))
canvas.bind("<Up>", lambda event: canvas.yview_scroll(-1, "units"))
canvas.bind("<Down>", lambda event: canvas.yview_scroll(1, "units"))
canvas.bind("<Button-1>", button_press)
canvas.bind("<B1-Motion>", rectangle.extend)
 
canvas.grid(row=0, column=0, sticky="nsew")
hsb.grid(row=1, column=0, sticky="ew")
vsb.grid(row=0, column=1, sticky="ns")
window.rowconfigure(0, weight=1)
window.columnconfigure(0, weight=1)
 
window.mainloop()
hobbyist likes this post
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  image does not show with pillow Mohamad_afeff_nasser 5 1,446 Apr-13-2025, 07:53 PM
Last Post: snippsat
  Placing image button on top of background image Sintek 1 535 Mar-02-2025, 05:36 PM
Last Post: Sintek
  Problem When using canny edge detection,black image returned rickyw2777 1 492 Feb-17-2025, 03:22 AM
Last Post: rickyw2777
  Why it gives me a black image and libpng warning: iCCP rickyw2777 1 506 Feb-16-2025, 08:26 PM
Last Post: rickyw2777
  QR code creation with image Raja31 1 1,041 Jan-15-2025, 11:17 AM
Last Post: Larz60+
Photo image generation with text style Belialhun 0 693 Oct-08-2024, 01:53 PM
Last Post: Belialhun
  Product Image Download Help Required pythonustasi 5 1,423 Jul-21-2024, 08:12 PM
Last Post: snippsat
  tkinter photo image problem jacksfrustration 5 3,737 Jun-27-2024, 12:06 AM
Last Post: AdamHensley
Photo image error pyc0de 2 1,923 Mar-23-2024, 06:20 PM
Last Post: pyc0de
  Using OpenCV and image path is invalid AudunNilsen 5 2,070 Mar-18-2024, 05:28 PM
Last Post: snippsat

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020