Comment afficher l'image et obtenir la coordonnée de clic de souris sur elle [fermé]

je me demande s'il est possible en Python (Windows) de montrer une image, puis cliquer avec la souris sur cette image et obtenir les coordonnées de ce clic par rapport aux bords de l'image.

Merci!

24
demandé sur mizo 2011-03-31 18:06:30
la source

6 ответов

Oui c'est possible et assez facile une fois que vous comprenez tkinter, voici un petit script:

from Tkinter import *
from tkFileDialog import askopenfilename
import Image, ImageTk

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

    #setting up a tkinter canvas with scrollbars
    frame = Frame(root, 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.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)

    #adding the image
    File = askopenfilename(parent=root, initialdir="C:/",title='Choose an image.')
    img = ImageTk.PhotoImage(Image.open(File))
    canvas.create_image(0,0,image=img,anchor="nw")
    canvas.config(scrollregion=canvas.bbox(ALL))

    #function to be called when mouse is clicked
    def printcoords(event):
        #outputting x and y coords to console
        print (event.x,event.y)
    #mouseclick event
    canvas.bind("<Button 1>",printcoords)

    root.mainloop()

non édité il s'imprimera en utilisant le système de coordonnées de fenêtre par défaut à la console. Le widget de toile rend le coin supérieur gauche le 0,0 point de sorte que vous pouvez avoir à jouer avec la fonction printcoords. Pour obtenir la dimension de l'image chargée vous utiliseriez la toile.bbox(TOUS), et vous pouvez passer à l'utilisation de canvasx et canvasy coords au lieu de la façon dont il est. Si vous êtes nouveau à tkinter; google devrait être en mesure pour vous aider à terminer d'ici :).

31
répondu Symon 2011-03-31 20:18:48
la source

Voici une version que j'avais concoctée il y a quelque temps en utilisant wxPython et divers tutoriels wxPython. Cela imprime les coordonnées de clic de souris dans une fenêtre de sortie séparée. (Utilise Python 2.6.2, wxPython 2.8.10.1)

Entrez le chemin de votre image dans le filepath variable en bas.

import wx

class MyCanvas(wx.ScrolledWindow):
    def __init__(self, parent, id = -1, size = wx.DefaultSize, filepath = None):
        wx.ScrolledWindow.__init__(self, parent, id, (0, 0), size=size, style=wx.SUNKEN_BORDER)

        self.image = wx.Image(filepath)
        self.w = self.image.GetWidth()
        self.h = self.image.GetHeight()
        self.bmp = wx.BitmapFromImage(self.image)

        self.SetVirtualSize((self.w, self.h))
        self.SetScrollRate(20,20)
        self.SetBackgroundColour(wx.Colour(0,0,0))

        self.buffer = wx.EmptyBitmap(self.w, self.h)
        dc = wx.BufferedDC(None, self.buffer)
        dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
        dc.Clear()
        self.DoDrawing(dc)

        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_LEFT_UP, self.OnClick)

    def OnClick(self, event):
        pos = self.CalcUnscrolledPosition(event.GetPosition())
        print '%d, %d' %(pos.x, pos.y)

    def OnPaint(self, event):
        dc = wx.BufferedPaintDC(self, self.buffer, wx.BUFFER_VIRTUAL_AREA)

    def DoDrawing(self, dc):
        dc.DrawBitmap(self.bmp, 0, 0)

class MyFrame(wx.Frame): 
    def __init__(self, parent=None, id=-1, filepath = None): 
        wx.Frame.__init__(self, parent, id, title=filepath)
        self.canvas = MyCanvas(self, -1, filepath = filepath)

        self.canvas.SetMinSize((self.canvas.w, self.canvas.h))
        self.canvas.SetMaxSize((self.canvas.w, self.canvas.h))
        self.canvas.SetBackgroundColour(wx.Colour(0, 0, 0))
        vert = wx.BoxSizer(wx.VERTICAL)
        horz = wx.BoxSizer(wx.HORIZONTAL)
        vert.Add(horz,0, wx.EXPAND,0)
        vert.Add(self.canvas,1,wx.EXPAND,0)
        self.SetSizer(vert)
        vert.Fit(self)
        self.Layout()

if __name__ == '__main__':
    app = wx.App()
    app.SetOutputWindowAttributes(title='stdout')  
    wx.InitAllImageHandlers()

    filepath = 'ENTER FILEPATH HERE'
    if filepath:
        print filepath
        myframe = MyFrame(filepath=filepath)
        myframe.Center()
        myframe.Show()
        app.MainLoop()
6
répondu bigjim 2011-03-31 20:28:16
la source

Voici une version révisée de la réponse de bigjim. Il fonctionne en Python 3.4+ (n'a rien testé d'autre). Je ne me suis pas embêté avec la partie PIL car la PhotoImage de tkinter peut gérer gif et pgm ce qui est suffisant pour démontrer ceci.

la fonction lambda gère la conversion entre les coordonnées d'événement (fenêtre) et les coordonnées d'image.

j'ai aussi ajouté le support pour press vs release puisque j'avais besoin de cette fonctionnalité particulière.

from tkinter import *
from tkinter.filedialog import askopenfilename

event2canvas = lambda e, c: (c.canvasx(e.x), c.canvasy(e.y))

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

    #setting up a tkinter canvas with scrollbars
    frame = Frame(root, 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.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)

    #adding the image
    File = askopenfilename(parent=root, initialdir="M:/",title='Choose an image.')
    print("opening %s" % File)
    img = PhotoImage(file=File)
    canvas.create_image(0,0,image=img,anchor="nw")
    canvas.config(scrollregion=canvas.bbox(ALL))

    #function to be called when mouse is clicked
    def printcoords(event):
        #outputting x and y coords to console
        cx, cy = event2canvas(event, canvas)
        print ("(%d, %d) / (%d, %d)" % (event.x,event.y,cx,cy))
    #mouseclick event
    canvas.bind("<ButtonPress-1>",printcoords)
    canvas.bind("<ButtonRelease-1>",printcoords)

    root.mainloop()
4
répondu RagingRoosevelt 2017-02-02 23:08:17
la source

vous pouvez utiliser Tkinter pour faire ceci et son intégré à python déjà.

http://www.pythonware.com/library/tkinter/introduction/

2
répondu Baz 2011-03-31 18:18:34
la source

une bonne alternative à Tkinter est D'utiliser QT en Python. Vous pouvez le faire avec PyQT

-3
répondu B4NZ41 2011-03-31 18:25:12
la source

Autres questions sur