【工具】旋转图片-数据集制作工具, 开源!

news/2024/7/10 21:00:06 标签: dubbo, 验证码, 工具, 旋转, 图片, 开源, python

转载请注明出处:小锋学长生活大爆炸[xfxuezhang.cn]

Github:https://github.com/1061700625/small_tools_v2

        之前做了一个下载百度的旋转图片验证码工具(多进程下载百度旋转验证码图片-制作数据集),那么拿到了图片数据,就需要手动校正调整来制作数据集,所以出了这个工具

        效果演示:

        源码:

python">import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
import os

class ImageRotatorApp(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("旋转图像器 by 小锋学长生活大爆炸")
        self.resizable(False, False)
        width = 400
        height = 600
        self.geometry(f'{width}x{height}')
        # 计算屏幕中心坐标
        screen_width = self.winfo_screenwidth()  
        screen_height = self.winfo_screenheight()
        x = (screen_width/2) - (width/2)
        y = (screen_height/2) - (height/2)
        # 设置窗口中心坐标
        self.geometry('{}x{}+{}+{}'.format(width, height, int(x), int(y)))

        # Initialize source and result directories
        self.source_directory = 'images'
        self.result_directory = 'result'
        self.original_image = None
        self.rotate_value = 0

        # Frame for source directory selection and display
        self.source_frame = tk.Frame(self)
        self.source_frame.pack(fill='x')
        
        self.select_source_button = tk.Button(self.source_frame, text="选择图像目录", command=self.select_source_directory)
        self.select_source_button.pack(side='left', padx=10, pady=5)
        
        self.source_directory_label = tk.Label(self.source_frame, text=self.source_directory)
        self.source_directory_label.pack(side='left')

        # Frame for result directory selection and display
        self.result_frame = tk.Frame(self)
        self.result_frame.pack(fill='x')

        self.select_result_button = tk.Button(self.result_frame, text="选择保存目录", command=self.select_result_directory)
        self.select_result_button.pack(side='left', padx=10, pady=5)
        
        self.result_directory_label = tk.Label(self.result_frame, text=self.result_directory)
        self.result_directory_label.pack(side='left')

        # Image display frame
        self.img_display = tk.Label(self, width=400, height=400)
        self.img_display.pack(expand=True, fill='both')

        # Slider for rotation
        self.rotation_slider = tk.Scale(self, from_=0, to=360, length=300, orient="horizontal", command=self.rotate_image)
        self.rotation_slider.pack(fill='x')

        self.button_frame = tk.Frame(self)
        self.button_frame.pack(side='bottom', fill='x')
        self.prev_button = tk.Button(self.button_frame, text="上一张", command=self.load_prev_image)
        self.prev_button.config(height=2, width=10)  
        self.prev_button.pack(expand=True, fill='x', side='left', padx=10, pady=5)
        # Button to save the image
        self.save_button = tk.Button(self.button_frame, text="保存", command=self.save_image)
        self.save_button.config(height=2, width=10)  # Make the button larger
        self.save_button.pack(expand=True, fill='x', side='left', padx=10, pady=5)
        # Next image button 
        self.next_button = tk.Button(self.button_frame, text="下一张", command=self.load_next_image) 
        self.next_button.config(height=2, width=10)  # Make the button larger
        self.next_button.pack(expand=True, fill='x', side='left', padx=10, pady=5)

        # 信息显示标签  
        self.info_label = tk.Label(self, text='')
        self.info_label.config(height=1)
        self.info_label.pack(side='bottom', fill='x')
        
        # Update the display with the first image from the source directory
        self.load_first_image_from_source()

    def show_debug_msg(self, msg):
        self.info_label.config(text=msg)
                               
    def select_source_directory(self):
        directory = filedialog.askdirectory()
        if directory:  # Update the directory only if a choice was made
            self.source_directory = directory
            self.source_directory_label.config(text=self.source_directory)
        self.load_first_image_from_source()

    def select_result_directory(self):
        directory = filedialog.askdirectory()
        if directory:  # Update the directory only if a choice was made
            self.result_directory = directory
            self.result_directory_label.config(text=self.result_directory)

    def load_next_image(self):
        if self.original_image:
            img_files = [f for f in os.listdir(self.source_directory) if f.endswith(('.png', '.jpg', '.jpeg'))]
            curr_idx = img_files.index(self.img_name)
            next_idx = curr_idx + 1 if curr_idx < len(img_files) - 1 else 0
            next_img_name = img_files[next_idx]
            self.original_image = Image.open(os.path.join(self.source_directory, next_img_name))
            self.show_debug_msg(f"当前图片[{next_idx+1}/{len(img_files)}]: {os.path.join(self.source_directory, next_img_name)}")
            self.image = self.original_image
            self.img_name = next_img_name
            self.update_image_display()
    
    def load_prev_image(self):
        if self.original_image:
            img_files = [f for f in os.listdir(self.source_directory) if f.endswith(('.png', '.jpg', '.jpeg'))]
            curr_idx = img_files.index(self.img_name)
            prev_idx = curr_idx - 1 if curr_idx > 0 else len(img_files) - 1
            prev_img_name = img_files[prev_idx]
            self.original_image = Image.open(os.path.join(self.source_directory, prev_img_name))
            self.show_debug_msg(f"当前图片[{prev_idx+1}/{len(img_files)}]: {os.path.join(self.source_directory, prev_img_name)}")
            self.image = self.original_image
            self.img_name = prev_img_name
            self.update_image_display()
        
    def load_first_image_from_source(self):
        try:
            img_lists = [f for f in os.listdir(self.source_directory) if f.endswith(('.png', '.jpg', '.jpeg'))]
            self.img_name = img_lists[0] if img_lists else None
            if self.img_name:
                self.original_image = Image.open(os.path.join(self.source_directory, self.img_name))
                self.image = self.original_image
                self.show_debug_msg(f"当前图片[{1}/{len(img_lists)}]: {os.path.join(self.source_directory, self.img_name)}")
            else:
                self.original_image = None
                self.image = None
            self.update_image_display()
        except FileNotFoundError:
            self.original_image = None
            self.image = None
            self.img_display.config(image='')
            self.show_debug_msg(f"'{self.source_directory}'路径下没有图片.")

    def rotate_image(self, value):
        if self.original_image:
            angle = int(value)
            self.rotate_value = angle
            self.image = self.original_image.rotate(-angle, resample=Image.Resampling.BILINEAR, fillcolor=(255, 255, 255))  # Negative for correct rotation direction
            self.update_image_display()

    def update_image_display(self):
        if self.image:
            # 缩放图片
            image_w, image_h = self.image.size
            if image_w > 400 or image_h > 400: 
                self.image.thumbnail((400,400))
            self.tk_image = ImageTk.PhotoImage(self.image)
            self.img_display.config(image=self.tk_image)
        else:
            # Clear the image in the Tkinter label
            self.img_display.config(image='')

    def save_image(self):
        if self.image:
            # Save the rotated image to the selected result directory
            save_path = os.path.join(self.result_directory, self.img_name.split('.')[0] + f'_{self.rotate_value}.' + self.img_name.split('.')[1])
            self.image.save(save_path)
            self.show_debug_msg(f"图片保存成功: {save_path}")
        else:
            self.show_debug_msg("没有图片要保存.")

# Create the 'images' and 'result' directories if they don't exist
os.makedirs('images', exist_ok=True)
os.makedirs('result', exist_ok=True)

# Run the app
app = ImageRotatorApp()
app.mainloop()


http://www.niftyadmin.cn/n/5162881.html

相关文章

java后端debug排查问题思路

问题排查思路 这里说的是主要是debug以及线上问题排查的思路. 解决问题的步骤 确认环境、确定问题、复现问题、查看日志、定位问题 、解决问题 确认环境/url/参数 确认是哪个环境。 是开发环境&#xff0c;测试环境&#xff0c;还是生产环境。 如果问题是在测试环境&…

如何利用浏览器的可见性API优化网站性能

最近在使用微软AI聊天工具Bing时&#xff0c;发现一个有趣的东西。我向它提问后&#xff0c;它在持续输出的过程中&#xff0c;如果我离开了当前它的浏览器会话&#xff0c;比如切屏&#xff0c;看当前浏览器的其它标签页&#xff0c;它会默认停止它的输出&#xff0c;等我回来…

“百人专家团”背书 袋鼠妈妈“双十一”蓄势待发

从万千商家的角度来看,“双十一”实际上就是一场没有硝烟的“战争”,只有用心做产品的品牌才能成为常胜将军,要想在双十一脱颖而出在同品类榜单上占据有利位置,品牌力和产品力二者缺一不可。而专注母婴护肤10年的袋鼠妈妈品牌便是如此,从品牌诞生以来,始终专注母婴用户需求,打造…

Java6种单例模式写法

单例模式 某个类任何情况下只有一个实例&#xff0c;并提供一个全局访问点来获取该实例懒汉式 synchronized延迟加载 volatilesynchronized双检锁 饿汉式 类加载时初始化静态实例 在静态代码块里初始化实例 静态内部类 调用静态内部类时&#xff0c;在静态内部类里初始…

Go语言开发环境安装,hello world!

1. Go开发包SDK https://golang.google.cn/dl/&#xff08;国内也可以安装&#xff09; 根据自己电脑下载对应的安装包&#xff0c;我懒下载了msi安装 然后一路点确定安装Go 2.安装GoLand https://www.jetbrains.com/go/download/#sectionwindows 下载安装包 一路确定安装完…

JavaScript 作用域链(Scope Chain)是什么?有什么作用?

结论先行&#xff1a; 当在函数内部访问一个变量的时候&#xff0c;&#xff08;JS 引擎&#xff09;程序会先在当前作用域中查找&#xff08;是否存在该变量&#xff09;&#xff0c;如果找到了就直接使用。否则就会向上层作用域逐级查找&#xff0c;直到找到全局作用域为止。…

万字长文 - Python 日志记录器logging 百科全书 之 基础配置

万字长文 - Python 日志记录器logging 百科全书 之 基础配置 前言 在日常的开发中工作中&#xff0c;日志记录扮演着不可或缺的角色。它不仅能让我们了解应用程序的运行状况&#xff0c;还能帮助我们定位并解决各种问题。 最基本的&#xff0c;它记录了应用程序的运行情况&am…

【深度神经网络(DNN)】实现车牌识别

文章目录 前言一、数据集介绍二、步骤1.导包2.参数配置3.数据处理4.模型定义5.模型训练6.模型预测 总结 前言 课内实践作业 车牌识别 一、数据集介绍 1.车牌识别数据集&#xff1a;VehicleLicense车牌识别数据集包含16151张单字符数据&#xff0c;所有的单字符均为严格切割且…