"Spécifiez la plage de l'image" que vous voyez souvent avec les outils de rognage etc. Je veux rendre cela possible en faisant glisser la souris tout en affichant la ligne de guidage. ↓ L'image ressemble à ceci ↓
Windows10 Home Python3.8.2(32bit) Visual Studio Code 1.45.1
Dans cet exemple, nous prévoyons de dessiner un rectangle (ligne directrice) pour la capture d'écran.
Par conséquent, prenez d'abord une capture d'écran en utilisant screenshot ()
de la bibliothèque pyautogui.
Puisque l'image préparée ne peut pas être utilisée telle quelle dans tkinter, ** utilisez ImageTk.PthoImage pour la convertir en un format pouvant être affiché dans tkinter **.
img_tk = ImageTk.PhotoImage(img)
(Notez que cette conversion donnera une erreur comme "Conversion trop tôt!" Sauf si c'est après Tk ())
(ImageTk est une méthode Pillow, elle doit donc être importée séparément)
Après cela, créez un widget Canvas avec tkinter et placez-y l'image.
canvas1 = tkinter.Canvas(root, bg="black", width=img.width, height=img.height)
canvas1.create_image(0, 0, image=img_tk, anchor=tkinter.NW)
Le canevas ne se transforme pas automatiquement pour s'adapter à l'image, vous devez donc spécifier la taille du widget pour qu'elle soit identique à l'image.
L'option ʻanchor` de create_image spécifie "où baser l'image à placer". La valeur est écrite comme «tkinter.» Et nord, sud, est et ouest, et l'image est N: Nord ⇒ nord = haut. Autre que N, écrivez W: gauche, S: bas, E: droite, CENTRE: centre. Dans le cas de l'exemple, NW = en haut à gauche de l'image de img_tk sera placé à coordonnée x = 0 et coordonnée y = 0 (spécifiée par les premier et deuxième arguments).
Tout d'abord, spécifiez ce qui se passe lorsque vous commencez à faire glisser sur Canvas.
widget de toile.bind("<ButtonPress-1>", <Fonction de rappel>)
Le traitement des dessins de lignes directrices est effectué dans la fonction de rappel appelée. (Lectangle signifie rectangle)
Widget de toile.create_rectangle(Coordonnée X du point de départ,Coordonnée Y du point de départ,Coordonnée X du point final,Coordonnée Y du point final, outline="Couleur de la ligne" ,tag="Nom de la balise")
Comme le rectangle dessiné sera transformé ultérieurement, il est nécessaire de spécifier le nom de la balise avec l'option tag
.
Si l'événement d'argument est spécifié lors de la déclaration de la fonction de rappel, ʻevent.x, event.y` Puisque vous pouvez obtenir les coordonnées de la souris au moment du clic, définissez cette valeur sur les coordonnées du point de départ (le point final est approprié)
Ensuite, spécifiez l'opération lorsque la souris se déplace tout en faisant glisser avec Canvas.
Widget de toile.bind("<Button1-Motion>", <Fonction de rappel>)
Décrivez le processus de transformation de la ligne directrice dans la fonction de rappel appelée.
Widget de toile.coords("Nom de tag de la figure à transformer",Coordonnée X du point de départ,Coordonnée Y du point de départ,Coordonnée X du point final,Coordonnée Y du point final)
Vous pouvez modifier la taille de la figure dessinée avec. (Coords semble signifier coordination) Lors de la modification de la taille du rectangle en faisant glisser, j'ai fait attention aux deux irrégularités suivantes.
Si vous définissez les coordonnées graphiques actuelles sur les coordonnées du point de départ sans penser à rien, Cela provoque un bug lorsque la souris glissante se déplace vers la gauche ou au-dessus du point de départ. .. (Les informations de coordonnées du point de départ seront réécrites aux coordonnées après le glissement) Par conséquent, en stockant les informations de coordonnées dans la variable globale lorsque la souris est cliquée et en utilisant cette valeur comme coordonnée du point de départ au moment du redessiner, Remplacement empêché ↓
#Événement au début du glissement- - - - - - - - - - - - - - - - - - - - - - - - - -
def start_point_get(event):
global start_x, start_y #Déclaré pour écrire dans des variables globales
:
(Dessin)
:
#Stocker les coordonnées dans des variables globales
start_x, start_y = event.x, event.y
#Événements glissés- - - - - - - - - - - - - - - - - - - - - - - - - -
def rect_drawing(event):
:
# "rect1"Redessiner l'image du tag
canvas1.coords("rect1", start_x, start_y, event.x, event.y)
Dans ce cas, si la souris sort de la zone de dessin, les coordonnées du bord de l'écran seront conservées. Par conséquent, selon que les coordonnées de la souris sont "zone de dessin (0 <x ≤ largeur de l'image)", "en dehors de la zone de dessin (x <0)" ou "en dehors de la zone de dessin (largeur <x)". Vous devez réécrire les coordonnées du point final. Vous pouvez chevaucher deux instructions if, mais cette fois, j'ai essayé de raccourcir le code en utilisant la fonction min. (Si vous le réorganisez, vous pouvez utiliser la fonction max)
if event.x < 0:
end_x = 0 #Définir 0 si les coordonnées acquises sont égales ou inférieures à 0
else:
end_x = min(img.width, event.x) #Définissez la largeur de l'image ou les coordonnées acquises, selon la plus petite des deux
Spécifiez l'opération pour que les coordonnées puissent être acquises lorsque le glissement est terminé.
Widget de toile.bind("<ButtonRelease-1>", <Fonction de rappel>)
Vous pouvez utiliser la méthode coords
décrite ci-dessus pour obtenir les coordonnées de la figure.
start_x, start_y, end_x, end_y =Widget de toile.coords("Nom de la balise")
Dans ce cas, il est difficile d'afficher une capture d'écran en plein écran dans la fenêtre tk, donc
J'affiche une version un peu réduite et je dessine un rectangle dessus.
Par conséquent, si vous voulez obtenir des coordonnées de taille réelle, vous devez multiplier les coordonnées obtenues par coords
par le grossissement de réduction.
Cette fois, j'ai utilisé la notation d'inclusion de liste et j'ai écrit le code aussi court que possible.
start_x, start_y, end_x, end_y = [
round(n * RESIZE_RETIO) for n in canvas1.coords("rect1")]
Ce qui précède est une série d'étapes. Je vous remercie pour votre travail acharné.
import tkinter
import time
import pyautogui #Bibliothèque externe
from PIL import Image, ImageTk #Bibliothèque externe
RESIZE_RETIO = 2 #Régulation du rapport de réduction
#Événement au début du glissement- - - - - - - - - - - - - - - - - - - - - - - - - -
def start_point_get(event):
global start_x, start_y #Déclaré pour écrire dans des variables globales
canvas1.delete("rect1") #Déjà"rect1"Supprimer n'importe quelle forme d'étiquette
#Dessinez un rectangle sur canvas1 (rectangle signifie rectangle)
canvas1.create_rectangle(event.x,
event.y,
event.x + 1,
event.y + 1,
outline="red",
tag="rect1")
#Stocker les coordonnées dans des variables globales
start_x, start_y = event.x, event.y
#Événements glissés- - - - - - - - - - - - - - - - - - - - - - - - - -
def rect_drawing(event):
#Traitement lorsque le pointeur de la souris lors du glissement sort de la zone
if event.x < 0:
end_x = 0
else:
end_x = min(img_resized.width, event.x)
if event.y < 0:
end_y = 0
else:
end_y = min(img_resized.height, event.y)
# "rect1"Redessiner l'image du tag
canvas1.coords("rect1", start_x, start_y, end_x, end_y)
#Événement lorsque la traînée est relâchée- - - - - - - - - - - - - - - - - - - - - - - - - -
def release_action(event):
# "rect1"Récupérez les coordonnées de l'image de l'étiquette à l'échelle d'origine
start_x, start_y, end_x, end_y = [
round(n * RESIZE_RETIO) for n in canvas1.coords("rect1")
]
#Afficher les coordonnées acquises
pyautogui.alert("start_x : " + str(start_x) + "\n" + "start_y : " +
str(start_y) + "\n" + "end_x : " + str(end_x) + "\n" +
"end_y : " + str(end_y))
#Traitement principal- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if __name__ == "__main__":
#Acquisition de l'image à afficher (capture d'écran)
img = pyautogui.screenshot()
#Redimensionnement de l'image car l'image de la capture d'écran ne peut pas être affichée
img_resized = img.resize(size=(int(img.width / RESIZE_RETIO),
int(img.height / RESIZE_RETIO)),
resample=Image.BILINEAR)
root = tkinter.Tk()
root.attributes("-topmost", True) #Amenez toujours la fenêtre tkinter au premier plan
#Conversion d'image pour qu'elle puisse être affichée avec tkinter
img_tk = ImageTk.PhotoImage(img_resized)
#Widget de dessin de canevas
canvas1 = tkinter.Canvas(root,
bg="black",
width=img_resized.width,
height=img_resized.height)
#Dessinez l'image acquise sur le widget Canvas
canvas1.create_image(0, 0, image=img_tk, anchor=tkinter.NW)
#Placez le widget Canvas et définissez divers événements
canvas1.pack()
canvas1.bind("<ButtonPress-1>", start_point_get)
canvas1.bind("<Button1-Motion>", rect_drawing)
canvas1.bind("<ButtonRelease-1>", release_action)
root.mainloop()
Maintenant que nous avons une interface pour spécifier la plage de l'image, je voudrais la connecter à divers outils. Par exemple, un outil qui "coupe en continu de l'écran de capture d'écran ⇒ enregistre comme nom à l'heure actuelle" Outils tels que "OCR à partir de la plage spécifiée". Non seulement l'écran de capture d'écran, mais aussi les outils qui traitent les images dans le presse-papiers peuvent être intéressants.
Transformez le rectangle affiché sur le canevas Python
Recommended Posts