import\x20os\nimport\x20shutil\nimport\x20tkinter\x20as\x20tk\nfrom\x20tkinter\x20import\x20filedialog\nfrom\x20PIL\x20import\x20Image,\x20ImageTk\n\nclass\x20ImageClassifier:\n\x20\x20def\x20__init__(self,\x20root):\n\x20\x20\x20\x20self.root\x20=\x20root\n\x20\x20\x20\x20self.root.title("图片分类工具")\n\x20\x20\x20\x20self.root.geometry("800x500")\n\x20\x20\x20\x20self.root.bind("",\x20self.key_press_event)\n\n\x20\x20\x20\x20self.image_paths\x20=\x20[]\n\x20\x20\x20\x20self.current_index\x20=\x200\n\x20\x20\x20\x20self.display_images\x20=\x20[]\n\x20\x20\x20\x20self.display_images_buttons\x20=\x20[]\n\x20\x20\x20\x20self.num_display_images\x20=\x203\x20#\x20Number\x20of\x20images\x20to\x20display\x20in\x20each\x20row\n\x20\x20\x20\x20self.num_classify_buttons\x20=\x204\x20#\x20Number\x20of\x20classify\x20buttons\n\n\x20\x20\x20\x20self.image_frame\x20=\x20tk.Frame(self.root)\n\x20\x20\x20\x20self.image_frame.pack(pady=50)\n\n\x20\x20\x20\x20self.button_frame\x20=\x20tk.Frame(self.root)\n\x20\x20\x20\x20self.button_frame.pack(pady=10)\n\n\x20\x20\x20\x20self.save_buttons_frame\x20=\x20tk.Frame(self.root)\n\x20\x20\x20\x20self.save_buttons_frame.pack(pady=10)\n\n\x20\x20\x20\x20self.save_paths\x20=\x20[]\n\x20\x20\x20\x20self.save_path_entries\x20=\x20[]\n\x20\x20\x20\x20self.save_buttons\x20=\x20[]\n\n\x20\x20\x20\x20self.next_button\x20=\x20tk.Button(self.button_frame,\x20text="下一组",\x20command=self.next_images,\x20width=10,\x20height=2)\n\x20\x20\x20\x20self.next_button.pack(side=tk.RIGHT,\x20padx=10)\n\n\x20\x20\x20\x20self.prev_button\x20=\x20tk.Button(self.button_frame,\x20text="上一组",\x20command=self.prev_images,\x20width=10,\x20height=2)\n\x20\x20\x20\x20self.prev_button.pack(side=tk.RIGHT,\x20padx=10)\n\n\x20\x20\x20\x20self.load_button\x20=\x20tk.Button(self.button_frame,\x20text="打开图片",\x20command=self.load_folder,\x20width=10,\x20height=2)\n\x20\x20\x20\x20self.load_button.pack(side=tk.LEFT,\x20padx=10)\n\n\x20\x20\x20\x20self.classify_buttons_frame\x20=\x20tk.Frame(self.root)\n\x20\x20\x20\x20self.classify_buttons_frame.pack(pady=10)\n\n\x20\x20\x20\x20self.classify_buttons\x20=\x20[]\n\x20\x20\x20\x20for\x20i\x20in\x20range(self.num_classify_buttons):\n\x20\x20\x20\x20\x20\x20classify_button\x20=\x20tk.Button(self.classify_buttons_frame,\x20text="类别 {}".format(i+1),\x20command=lambda\x20i=i:\x20self.classify_images(i),\x20width=10,\x20height=2)\n\x20\x20\x20\x20\x20\x20classify_button.pack(side=tk.LEFT,\x20padx=10)\n\x20\x20\x20\x20\x20\x20self.classify_buttons.append(classify_button)\n\n\x20\x20\x20\x20for\x20i\x20in\x20range(self.num_display_images):\n\x20\x20\x20\x20\x20\x20self.display_images_buttons.append([])\n\n\x20\x20\x20\x20self.root.mainloop()\n\n\x20\x20def\x20load_folder(self):\n\x20\x20\x20\x20folder_path\x20=\x20filedialog.askdirectory()\n\x20\x20\x20\x20self.image_paths\x20=\x20[]\n\x20\x20\x20\x20for\x20file_name\x20in\x20sorted(os.listdir(folder_path)):\n\x20\x20\x20\x20\x20\x20if\x20file_name.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')):\n\x20\x20\x20\x20\x20\x20\x20\x20self.image_paths.append(os.path.join(folder_path, file_name))\n\x20\x20\x20\x20self.current_index\x20=\x200\n\x20\x20\x20\x20self.next_images()\n\n\x20\x20def\x20next_images(self):\n\x20\x20\x20\x20if\x20self.current_index\x20+\x20len(self.display_images)\x20<\x20len(self.image_paths):\n\x20\x20\x20\x20\x20\x20self.current_index\x20+=\x20len(self.display_images)\n\x20\x20\x20\x20\x20\x20self.display_images\x20=\x20[]\n\x20\x20\x20\x20\x20\x20for\x20i\x20in\x20range(len(self.display_images_buttons)):\n\x20\x20\x20\x20\x20\x20\x20\x20for\x20button\x20in\x20self.display_images_buttons[i]:\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20button.destroy()\n\x20\x20\x20\x20\x20\x20\x20\x20self.display_images_buttons[i]\x20=\x20[]\n\x20\x20\x20\x20\x20\x20for\x20i\x20in\x20range(min(len(self.image_paths)-self.current_index,\x20self.num_display_images)):\n\x20\x20\x20\x20\x20\x20\x20\x20self.display_images.append(self.image_paths[self.current_index\x20+\x20i])\n\x20\x20\x20\x20\x20\x20\x20\x20image\x20=\x20Image.open(self.image_paths[self.current_index\x20+\x20i])\n\x20\x20\x20\x20\x20\x20\x20\x20#\x20Calculate\x20the\x20aspect\x20ratio\x20of\x20the\x20image\n\x20\x20\x20\x20\x20\x20\x20\x20width,\x20height\x20=\x20image.size\n\x20\x20\x20\x20\x20\x20\x20\x20aspect_ratio\x20=\x20width\x20/\x20height\n\x20\x20\x20\x20\x20\x20\x20\x20#\x20Resize\x20the\x20image\x20while\x20maintaining\x20the\x20aspect\x20ratio\n\x20\x20\x20\x20\x20\x20\x20\x20new_width\x20=\x20400\n\x20\x20\x20\x20\x20\x20\x20\x20new_height\x20=\x20int(new_width\x20/\x20aspect_ratio)\n\x20\x20\x20\x20\x20\x20\x20\x20image\x20=\x20image.resize((new_width,\x20new_height))\n\x20\x20\x20\x20\x20\x20\x20\x20photo\x20=\x20ImageTk.PhotoImage(image)\n\x20\x20\x20\x20\x20\x20\x20\x20label\x20=\x20tk.Label(self.image_frame,\x20image=photo)\n\x20\x20\x20\x20\x20\x20\x20\x20label.image\x20=\x20photo\n\x20\x20\x20\x20\x20\x20\x20\x20label.grid(row=0,\x20column=i,\x20padx=10)\n\x20\x20\x20\x20\x20\x20\x20\x20self.display_images_buttons[i].append(label)\n\n\x20\x20def\x20prev_images(self):\n\x20\x20\x20\x20if\x20self.current_index\x20-\x20len(self.display_images)\x20>=\x200:\n\x20\x20\x20\x20\x20\x20self.current_index\x20-=\x20len(self.display_images)\n\x20\x20\x20\x20\x20\x20self.display_images\x20=\x20[]\n\x20\x20\x20\x20\x20\x20for\x20i\x20in\x20range(len(self.display_images_buttons)):\n\x20\x20\x20\x20\x20\x20\x20\x20for\x20button\x20in\x20self.display_images_buttons[i]:\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20button.destroy()\n\x20\x20\x20\x20\x20\x20\x20\x20self.display_images_buttons[i]\x20=\x20[]\n\x20\x20\x20\x20\x20\x20for\x20i\x20in\x20range(min(len(self.image_paths)-self.current_index,\x20self.num_display_images)):\n\x20\x20\x20\x20\x20\x20\x20\x20self.display_images.append(self.image_paths[self.current_index\x20+\x20i])\n\x20\x20\x20\x20\x20\x20\x20\x20image\x20=\x20Image.open(self.image_paths[self.current_index\x20+\x20i])\n\x20\x20\x20\x20\x20\x20\x20\x20#\x20Calculate\x20the\x20aspect\x20ratio\x20of\x20the\x20image\n\x20\x20\x20\x20\x20\x20\x20\x20width,\x20height\x20=\x20image.size\n\x20\x20\x20\x20\x20\x20\x20\x20aspect_ratio\x20=\x20width\x20/\x20height\n\x20\x20\x20\x20\x20\x20\x20\x20#\x20Resize\x20the\x20image\x20while\x20maintaining\x20the\x20aspect\x20ratio\n\x20\x20\x20\x20\x20\x20\x20\x20new_width\x20=\x20400\n\x20\x20\x20\x20\x20\x20\x20\x20new_height\x20=\x20int(new_width\x20/\x20aspect_ratio)\n\x20\x20\x20\x20\x20\x20\x20\x20image\x20=\x20image.resize((new_width,\x20new_height))\n\x20\x20\x20\x20\x20\x20\x20\x20photo\x20=\x20ImageTk.PhotoImage(image)\n\x20\x20\x20\x20\x20\x20\x20\x20label\x20=\x20tk.Label(self.image_frame,\x20image=photo)\n\x20\x20\x20\x20\x20\x20\x20\x20label.image\x20=\x20photo\n\x20\x20\x20\x20\x20\x20\x20\x20label.grid(row=0,\x20column=i,\x20padx=10)\n\x20\x20\x20\x20\x20\x20\x20\x20self.display_images_buttons[i].append(label)\n\n\x20\x20def\x20classify_images(self,\x20index):\n\x20\x20\x20\x20button\x20=\x20self.classify_buttons[index]\n\x20\x20\x20\x20if\x20hasattr(button,\x20'save_path'):\n\x20\x20\x20\x20\x20\x20folder_path\x20=\x20button.save_path\n\x20\x20\x20\x20else:\n\x20\x20\x20\x20\x20\x20folder_path\x20=\x20filedialog.askdirectory()\n\x20\x20\x20\x20\x20\x20button.save_path\x20=\x20folder_path\n\n\x20\x20\x20\x20for\x20image_path\x20in\x20self.display_images:\n\x20\x20\x20\x20\x20\x20image_name\x20=\x20os.path.basename(image_path)\n\x20\x20\x20\x20\x20\x20new_path\x20=\x20os.path.join(folder_path,\x20image_name)\n\x20\x20\x20\x20\x20\x20shutil.copyfile(image_path,\x20new_path)\n\x20\x20\x20\x20\x20\x20print("图片 {} 移动到了 {}".format(image_name,\x20new_path))\n\n\x20\x20def\x20key_press_event(self,\x20event):\n\x20\x20\x20\x20if\x20event.char.lower()\x20==\x20'a':\n\x20\x20\x20\x20\x20\x20self.prev_images()\n\x20\x20\x20\x20elif\x20event.char.lower()\x20==\x20'd':\n\x20\x20\x20\x20\x20\x20self.next_images()\n\n\x20\x20def\x20save_images(self,\x20index):\n\x20\x20\x20\x20folder_path\x20=\x20filedialog.askdirectory()\n\x20\x20\x20\x20self.save_paths[index]\x20=\x20folder_path\n\x20\x20\x20\x20self.save_path_entries[index].delete(0,\x20tk.END)\n\x20\x20\x20\x20self.save_path_entries[index].insert(0,\x20folder_path)\n\nroot\x20=\x20tk.Tk()\napp\x20=\x20ImageClassifier(root)\n