Je dois trier beaucoup d'images au travail. Je pense que si vous utilisez un logiciel libre, vous pouvez trier efficacement, mais malheureusement, nous interdisons le logiciel libre en principe. Ensuite, dans l'esprit de le faire, j'ai créé ** une visionneuse d'images avec une fonction de tri simple **.
Exemple: Une image de chien qui a été confondue dans une image de chat est extraite avec une étiquette "1".
Cliquez ici pour le corps principal de l'outil de tri ↓
Outil de tri.py
from file_walker import folder_walker #Fonction auto-fabriquée
from folder_selecter import file_selecter #Fonction auto-fabriquée
import os
import shutil
import subprocess
import tkinter as tk
from tkinter import Label, Tk, StringVar
from PIL import Image, ImageTk #Bibliothèque externe
#Lecture de fichiers- - - - - - - - - - - - - - - - - - - - - - - -
def load_file(event):
global img_num, item, dir_name
#Lisez le dossier
tex_var.set("Chargement du fichier...")
dir_name = file_selecter(dir_select=True)
if not dir_name == None:
file_list = folder_walker(dir_name)
#Répertoriez les images pouvant être lues à partir du fichier
for f in file_list:
try:
img_lst.append(Image.open(f))
filename_lst.append(f)
except:
pass
#Redéfinissez la taille de la toile pour l'adapter à la taille de la fenêtre
window_resize()
#Conversion d'image
for f in img_lst:
#Redimensionné pour s'adapter à l'intérieur de la toile
resized_img = img_resize_for_canvas(f, image_canvas)
#Conversion d'image pour qu'elle puisse être affichée avec tkinter
tk_img_lst.append(ImageTk.PhotoImage(
image=resized_img, master=image_canvas))
#Obtenez le centre de la toile
c_width_half = round(int(image_canvas["width"]) / 2)
c_height_half = round(int(image_canvas["height"]) / 2)
#Affichage sur toile
img_num = 0
item = image_canvas.create_image(
c_width_half, c_height_half, image=tk_img_lst[0], anchor=tk.CENTER)
#Réécriture d'étiquettes
tex_var.set(filename_lst[img_num])
#Masquer le bouton de chargement
load_btn.pack_forget()
#Disposition des boutons d'exécution du tri
assort_btn.pack()
#Vers l'image suivante- - - - - - - - - - - - - - - - - - - - - - - -
def next_img(event):
global img_num
#Obtenez le nombre d'images en cours de chargement
img_count = len(tk_img_lst)
#Déterminez si l'image n'est pas la dernière
if img_num >= img_count - 1:
pass
else:
#Numéro d'image affiché.Mettre à jour et afficher
img_num += 1
image_canvas.itemconfig(item, image=tk_img_lst[img_num])
#Réécriture d'étiquettes
tex_var.set(filename_lst[img_num])
#Afficher l'étiquetage
if filename_lst[img_num] in assort_dict:
assort_t_var.set(assort_dict[filename_lst[img_num]])
else:
assort_t_var.set("")
#Vers l'image précédente- - - - - - - - - - - - - - - - - - - - - - - -
def prev_img(event):
global img_num
#Déterminez si l'image n'est pas la première
if img_num <= 0:
pass
else:
#Numéro d'image affiché.Mettre à jour et afficher
img_num -= 1
image_canvas.itemconfig(item, image=tk_img_lst[img_num])
#Réécriture d'étiquettes
tex_var.set(filename_lst[img_num])
#Afficher l'étiquetage
if filename_lst[img_num] in assort_dict:
assort_t_var.set(assort_dict[filename_lst[img_num]])
else:
assort_t_var.set("")
#Redéfinir la taille de la toile à partir de la taille de la fenêtre- - - - - - - - - - - - - - - - -
def window_resize():
image_canvas["width"] = image_canvas.winfo_width()
image_canvas["height"] = image_canvas.winfo_height()
#Réduire l'image pour l'adapter à la taille de la toile- - - - - - - - - - - - - - - - - - - -
def img_resize_for_canvas(img, canvas, expand=False):
size_retio_w = int(canvas["width"]) / img.width
size_retio_h = int(canvas["height"]) / img.height
if expand == True:
size_retio = min(size_retio_w, size_retio_h)
else:
size_retio = min(size_retio_w, size_retio_h, 1)
resized_img = img.resize((round(img.width * size_retio),
round(img.height * size_retio)))
return resized_img
#Affichage de l'image- - - - - - - - - - - - - - - - - - - - - - - -
def image_show(event):
img_lst[img_num].show()
#Étiquetage des images- - - - - - - - - - - - - - - - - - - - - - - -
def file_assort(event):
if str(event.keysym) in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]:
assort_dict[filename_lst[img_num]] = str(event.keysym)
elif str(event.keysym) == "0":
del assort_dict[filename_lst[img_num]]
#Afficher l'étiquetage
if filename_lst[img_num] in assort_dict:
assort_t_var.set(assort_dict[filename_lst[img_num]])
else:
assort_t_var.set("")
print(assort_dict[filename_lst[img_num]])
#Exécution de la division des dossiers- - - - - - - - - - - - - - - - - - - - - - - -
def assort_go(event):
global f_dir
for f in assort_dict:
#Obtenez le nom du fichier / nom du dossier avant et après le tri
f_dir = os.path.dirname(f)
f_basename = os.path.basename(f)
new_dir = os.path.join(f_dir, assort_dict[f])
new_path = os.path.join(new_dir, f_basename)
#Vérification de l'existence du répertoire
if not os.path.exists(new_dir):
os.mkdir(new_dir)
#Déplacer le fichier
shutil.move(f, new_path)
#Afficher / masquer divers boutons
assort_btn.pack_forget()
open_folder_btn.pack()
print(new_path)
#Dossier ouvert- - - - - - - - - - - - - - - - - - - - - - - -
def folder_open(event):
#Convertir le chemin pour ouvrir dans l'Explorateur
open_dir_name = f_dir.replace("/", "\\")
#Ouvrir dans l'explorateur
subprocess.Popen(['explorer', open_dir_name])
#Fermez la fenêtre tkinter
root.destroy()
print(open_dir_name)
#Traitement principal-------------------------------------------------------
if __name__ == "__main__":
#Variables globales
img_lst, tk_img_lst = [], []
filename_lst = []
assort_file_list = []
assort_dict = {}
img_num = 0
f_basename = ""
#paramètres de dessin tkinter
root = tk.Tk()
root.title(u"Outil d'affichage / tri")
root.option_add("*font", ("Meiryo UI", 11))
#Charger les paramètres de dessin du bouton
load_btn = tk.Button(root, text="Lis")
load_btn.bind("<Button-1>", load_file)
load_btn.pack()
#Paramètres de dessin de canevas
image_canvas = tk.Canvas(root,
width=640,
height=480)
image_canvas.pack(expand=True, fill="both")
#Affichage des résultats de tri
assort_t_var = tk.StringVar()
assort_label = tk.Label(
root, textvariable=assort_t_var, font=("Meiryo UI", 14))
assort_label.pack()
#Paramètres de dessin d'étiquette de nom de fichier
tex_var = tk.StringVar()
tex_var.set("nom de fichier")
lbl = tk.Label(root, textvariable=tex_var, font=("Meiryo UI", 8))
lbl["foreground"] = "gray"
lbl.pack()
#Réglage de fonctionnement pour alimenter les images avec les touches droite et gauche
root.bind("<Key-Right>", next_img)
root.bind("<Key-Left>", prev_img)
# 「Ctrl」+Affichage de l'image avec "P"
root.bind("<Control-Key-p>", image_show)
#Tri des paramètres cibles avec les touches numériques
root.bind("<Key>", file_assort)
#Bouton d'exécution de tri
assort_btn = tk.Button(root, text="Exécution du tri")
assort_btn.bind("<Button-1>", assort_go)
#Bouton pour ouvrir le dossier
open_folder_btn = tk.Button(root,text="Dossier ouvert")
open_folder_btn.bind("<Button-1>", folder_open)
root.mainloop()
La fonction d'auto-création créée a été utilisée pour l'opération de spécification du dossier et l'opération d'acquisition de la liste de fichiers à partir du dossier spécifié. Stockez le fichier .py suivant dans le même dossier que l'outil de tri ci-dessus .py.
file_selector.py
import os
import sys
import tkinter as f_tk
from tkinter import filedialog
def file_selecter(ini_folder_path = str(os.path.dirname(sys.argv[0])),
multiple= False, dir_select = False):
"""
Ouvrez une boîte de dialogue et sélectionnez un fichier ou un dossier.
Si vous ne spécifiez pas le dossier initial, le dossier du fichier lui-même est ouvert.
Vous pouvez sélectionner la sélection de dossier et la sélection de fichier (multiple / unique) comme options.
Parameters
----------
ini_folder_path : str
Le dossier à ouvrir initialement. La valeur par défaut est le chemin du dossier du fichier exécutable
multiple : bool
S'il faut autoriser la sélection de plusieurs fichiers. La valeur par défaut est False, qui est une sélection unique.
dir_select : bool
Mode de sélection de dossier. La valeur par défaut est False, qui est en mode de sélection de fichier.
"""
root_fileselect=f_tk.Tk()
root_fileselect.withdraw() #Masquer la fenêtre
if os.path.isfile(ini_folder_path):
ini_folder_path = os.path.dirname(ini_folder_path) #Si le nom de fichier est inclus dans la spécification de dossier initiale, le dossier du fichier est renvoyé.
if dir_select:
select_item = f_tk.filedialog.askdirectory(initialdir=ini_folder_path) #Mode de sélection de répertoire
elif multiple:
select_item = f_tk.filedialog.askopenfilenames(initialdir=ini_folder_path) #Mode de sélection de fichier (multiple)
else:
select_item = f_tk.filedialog.askopenfilename(initialdir=ini_folder_path) #Mode de sélection de fichier (unique)
root_fileselect.destroy()
if not select_item =="":
return select_item
file_walker.py
import os
import pathlib
def folder_walker(folder_path, recursive = True, file_ext = ".*"):
"""
Obtenez une liste de fichiers dans le dossier spécifié.
Il peut être obtenu de manière récursive ou non récursive en spécifiant un argument.
Parameters
----------
folder_path : str
Chemin du dossier cible
recursive : bool
S'il faut l'obtenir récursivement. La valeur par défaut est True, qui est acquise de manière récursive.
file_ext : str
Spécifiez l'extension du fichier à lire. Exemple:".jpg "Besoin d'une période comme. La valeur par défaut est".*"Non spécifié dans
"""
p = pathlib.Path(folder_path)
if recursive:
return list(p.glob("**/*" + file_ext)) # **/*Obtenez des fichiers de manière récursive avec
else:
return list(p.glob("*" + file_ext)) #Ne pas récupérer les fichiers de manière récursive
J'utilise également le fileialog
de Tkinter pour sélectionner le dossier, mais au début, j'ai essayé de dessiner la racine de la fenêtre principale après avoir sélectionné le dossier. Ensuite, j'ai eu du mal car la racine principale ne s'affichait pas correctement ou devenait inactive, probablement à cause de l'héritage.
Après tout, si j'appelais fileialog après avoir dessiné la racine principale, je pourrais dessiner la racine sans problème.
Au début, j'étais impatient car le contenu du canevas et l'étiquette avec tk.StringVar ()
intégré n'étaient pas affichés du tout.
À la suite de diverses enquêtes, python a un concept appelé garbage collection, et le contenu des variables jugées inutiles (= inaccessibles) est automatiquement supprimé. Par conséquent, lorsque le canevas a tenté de faire référence à l'objet, il n'a pas pu être dessiné car son contenu était perdu.
Pour éviter cela, vous pouvez soit le charger en tant que variable globale à l'avance, soit demander à une instance de la classe de charger l'objet. Voir ci-dessous pour plus de détails.
Page de référence: [Python] Que faire lorsque des objets tels que des images ne peuvent pas être dessinés avec Tkinter
https://daeudaeu.com/create_image_problem/
J'ai eu du mal à trouver un moyen de référencer les paramètres du widget. Après tout, tout ce que j'avais à faire était de l'obtenir avec ** nom du widget ["nom du paramètre"] ** comme indiqué ci-dessous.
canvas_w = int(image_canvas["width"])
(Dans ce cas, étant donné que la taille de la fenêtre a été rendue variable, il était nécessaire d'obtenir la taille du canevas afin que le centre du canevas puisse être déterminé.)
Je pensais que ce serait facile à faire car c'était une opération simple, mais j'ai eu du mal à l'improviste en raison d'un manque de connaissances. À l'avenir, j'aimerais apporter diverses modifications basées sur celle créée cette fois pour en faire un outil plus convivial. En particulier,
etc.
Recommended Posts