acdr/acdr-ui/tootls/imgtools.py

151 lines
5.9 KiB
Python
Raw Permalink Normal View History

2024-09-08 14:01:29 +08:00
import os
import cv2
import numpy as np
import re
from tkinter import *
from tkinter import filedialog, messagebox, colorchooser
from PIL import Image
import tkinter as tk
# 主应用类
class ImageSplitterApp:
def __init__(self, root):
self.root = root
self.root.title("图像分割工具")
self.root.geometry("500x450")
# 文件或文件夹路径
self.file_path = None
self.folder_path = None
self.selected_color = (0, 0, 0) # 默认黑色
# 创建选择文件按钮
Button(self.root, text="选择单个文件", command=self.select_file).pack(pady=10)
Button(self.root, text="选择文件夹", command=self.select_folder).pack(pady=10)
# 选择颜色按钮
Label(self.root, text="选择分割线颜色:").pack(pady=10)
Button(self.root, text="打开取色器", command=self.pick_color).pack(pady=5)
# 当前选择的颜色显示
self.color_label = Label(self.root, text=f"当前颜色: {self.selected_color}")
self.color_label.pack(pady=5)
# 命名规则
Label(self.root, text="请输入保存图片的命名规则(支持正则):").pack(pady=10)
self.naming_entry = Entry(self.root)
self.naming_entry.insert(0, r"sub_image_{idx}") # 默认命名规则
self.naming_entry.pack(pady=5)
# 分割按钮
Button(self.root, text="开始分割", command=self.split_image).pack(pady=20)
# 选择保存文件夹
self.save_folder_path = None
Button(self.root, text="选择保存文件夹", command=self.select_save_folder).pack(pady=10)
def select_file(self):
self.file_path = filedialog.askopenfilename(filetypes=[("Image Files", "*.png *.jpg *.jpeg")])
if self.file_path:
messagebox.showinfo("文件选择", f"已选择文件: {self.file_path}")
def select_folder(self):
self.folder_path = filedialog.askdirectory()
if self.folder_path:
messagebox.showinfo("文件夹选择", f"已选择文件夹: {self.folder_path}")
def select_save_folder(self):
self.save_folder_path = filedialog.askdirectory()
if self.save_folder_path:
messagebox.showinfo("保存文件夹选择", f"已选择保存文件夹: {self.save_folder_path}")
# 颜色取色器
def pick_color(self):
color = colorchooser.askcolor(title="选择分割线颜色")
if color:
self.selected_color = tuple(map(int, color[0])) # 颜色转换为整数的 (r, g, b)
self.color_label.config(text=f"当前颜色: {self.selected_color}")
# 查找分割线的位置 (通过指定颜色)
def find_dividing_lines(self, image, line_color):
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 将图像转换为灰度图
_, binary = cv2.threshold(gray, 128, 255, cv2.THRESH_BINARY_INV) # 进行二值化
# 查找水平和垂直线条
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25, 1))
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 25))
# 水平线
horizontal_lines = cv2.morphologyEx(binary, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
# 垂直线
vertical_lines = cv2.morphologyEx(binary, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
return horizontal_lines, vertical_lines
# 分割图像
def split_image(self):
# 提取颜色
line_color = self.selected_color
# 读取命名规则
naming_rule = self.naming_entry.get()
# 处理单个文件
if self.file_path:
self.process_file(self.file_path, line_color, naming_rule)
# 处理文件夹中的所有文件
if self.folder_path:
for file_name in os.listdir(self.folder_path):
if file_name.endswith(('.png', '.jpg', '.jpeg')):
file_path = os.path.join(self.folder_path, file_name)
self.process_file(file_path, line_color, naming_rule)
# 处理单个文件的分割
def process_file(self, file_path, line_color, naming_rule):
image = cv2.imread(file_path)
if image is None:
messagebox.showerror("错误", f"无法加载图像: {file_path}")
return
horizontal_lines, vertical_lines = self.find_dividing_lines(image, line_color)
sub_images = self.split_image_by_lines(image, horizontal_lines, vertical_lines)
# 保存分割后的图像
self.save_sub_images(sub_images, naming_rule)
# 根据分割线分割图像
def split_image_by_lines(self, image, horizontal_lines, vertical_lines):
horizontal_coords = np.where(np.any(horizontal_lines > 0, axis=1))[0]
vertical_coords = np.where(np.any(vertical_lines > 0, axis=0))[0]
sub_images = []
for i in range(len(horizontal_coords) - 1):
for j in range(len(vertical_coords) - 1):
x1, x2 = vertical_coords[j], vertical_coords[j + 1]
y1, y2 = horizontal_coords[i], horizontal_coords[i + 1]
sub_image = image[y1:y2, x1:x2]
sub_images.append(sub_image)
return sub_images
# 保存分割后的图像,支持正则命名规则
def save_sub_images(self, sub_images, naming_rule):
if not self.save_folder_path:
messagebox.showerror("错误", "请先选择保存文件夹")
return
for idx, img in enumerate(sub_images):
filename = re.sub(r'{idx}', str(idx), naming_rule) # 使用正则表达式进行命名
save_path = os.path.join(self.save_folder_path, f"{filename}.png")
cv2.imwrite(save_path, img)
messagebox.showinfo("完成", f"图像已分割并保存到 {self.save_folder_path}")
# 运行图形界面应用
if __name__ == "__main__":
root = tk.Tk()
app = ImageSplitterApp(root)
root.mainloop()