Last active
February 23, 2026 20:55
-
-
Save eros18123/3e31601f3632f3ba294498d9a73b9062 to your computer and use it in GitHub Desktop.
kanji pdf 2136 + 1 extra
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import fitz # PyMuPDF | |
| import os | |
| import tkinter as tk | |
| from tkinter import messagebox | |
| from PIL import Image, ImageTk | |
| from tqdm import tqdm | |
| import numpy as np | |
| PDF_PATH = "kanji_poster.pdf" | |
| OUTPUT_FOLDER = "kanji_images" | |
| TOTAL_KANJI = 2136 | |
| class CalibrationGUI: | |
| def __init__(self, pil_image): | |
| self.root = tk.Tk() | |
| self.root.title("CALIBRAÇÃO KANJI - PRECISÃO TOTAL") | |
| self.points = [] | |
| self.pil_image = pil_image | |
| # Lista de Kanjis para clicar (Sem repetir o 1) | |
| self.anchors_to_click = [101, 201, 301, 401, 501, 601, 701, 801, 901, 1001, | |
| 1101, 1201, 1301, 1401, 1501, 1601, 1701, 1801, 1901, 2001, 2101] | |
| self.instructions = [ | |
| "1. CLIQUE NO CANTO SUPERIOR ESQUERDO DO KANJI 1 (Início de tudo)", | |
| "2. CLIQUE NO CANTO INFERIOR DIREITO DO KANJI 1 (Define o tamanho do card)", | |
| "3. CLIQUE NO CANTO SUPERIOR ESQUERDO DO KANJI 10 (Define largura das colunas)", | |
| "4. CLIQUE NO CANTO SUPERIOR ESQUERDO DO KANJI 91 (Define altura das linhas - Fim da 1ª coluna)" | |
| ] | |
| for num in self.anchors_to_click: | |
| self.instructions.append(f"CLIQUE NO CANTO SUPERIOR ESQUERDO DO KANJI {num}") | |
| # Label de Instrução | |
| self.label_inst = tk.Label(self.root, text=self.instructions[0], font=("Arial", 12, "bold"), fg="red", bg="yellow") | |
| self.label_inst.pack(fill=tk.X) | |
| # Frame Principal | |
| frame = tk.Frame(self.root) | |
| frame.pack(fill=tk.BOTH, expand=True) | |
| # Canvas | |
| self.canvas = tk.Canvas(frame, cursor="cross", bg="gray") | |
| self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) | |
| # Scrollbars | |
| vbar = tk.Scrollbar(frame, orient=tk.VERTICAL, command=self.canvas.yview) | |
| vbar.pack(side=tk.RIGHT, fill=tk.Y) | |
| hbar = tk.Scrollbar(self.root, orient=tk.HORIZONTAL, command=self.canvas.xview) | |
| hbar.pack(side=tk.BOTTOM, fill=tk.X) | |
| self.canvas.config(xscrollcommand=hbar.set, yscrollcommand=vbar.set) | |
| # Imagem | |
| self.tk_img = ImageTk.PhotoImage(pil_image) | |
| self.canvas.create_image(0, 0, image=self.tk_img, anchor="nw") | |
| self.canvas.config(scrollregion=self.canvas.bbox(tk.ALL)) | |
| # Lupa (Janela flutuante) | |
| self.lupa_size = 200 | |
| self.lupa_window = tk.Toplevel(self.root) | |
| self.lupa_window.overrideredirect(True) # Sem bordas | |
| self.lupa_canvas = tk.Canvas(self.lupa_window, width=self.lupa_size, height=self.lupa_size, highlightthickness=2, highlightbackground="green") | |
| self.lupa_canvas.pack() | |
| # Eventos | |
| self.canvas.bind("<Button-1>", self.on_click) | |
| self.canvas.bind("<Motion>", self.update_lupa) | |
| self.root.bind("<Control-z>", lambda e: self.undo()) | |
| def update_lupa(self, event): | |
| x = self.canvas.canvasx(event.x) | |
| y = self.canvas.canvasy(event.y) | |
| # Posiciona a janela da lupa perto do mouse | |
| self.lupa_window.geometry(f"+{self.root.winfo_pointerx() + 20}+{self.root.winfo_pointery() + 20}") | |
| # Recorte para a lupa (Zoom 2x do que já está em 4x) | |
| crop_x = x - 50 | |
| crop_y = y - 50 | |
| crop = self.pil_image.crop((crop_x, crop_y, crop_x + 100, crop_y + 100)) | |
| crop = crop.resize((self.lupa_size, self.lupa_size), Image.NEAREST) | |
| self.tk_lupa = ImageTk.PhotoImage(crop) | |
| self.lupa_canvas.create_image(0, 0, image=self.tk_lupa, anchor="nw") | |
| # Cruz central da lupa | |
| self.lupa_canvas.create_line(100, 0, 100, 200, fill="green") | |
| self.lupa_canvas.create_line(0, 100, 200, 100, fill="green") | |
| def on_click(self, event): | |
| x = self.canvas.canvasx(event.x) | |
| y = self.canvas.canvasy(event.y) | |
| self.points.append((x, y)) | |
| idx = len(self.points) | |
| tag = f"pt_{idx}" | |
| self.canvas.create_oval(x-3, y-3, x+3, y+3, fill="red", tags=tag) | |
| self.canvas.create_text(x+10, y+10, text=str(idx), fill="red", font=("Arial", 10, "bold"), tags=tag) | |
| if idx < len(self.instructions): | |
| self.label_inst.config(text=self.instructions[idx]) | |
| else: | |
| self.lupa_window.destroy() | |
| self.root.destroy() | |
| def undo(self): | |
| if self.points: | |
| idx = len(self.points) | |
| self.points.pop() | |
| self.canvas.delete(f"pt_{idx}") | |
| self.label_inst.config(text=self.instructions[len(self.points)]) | |
| def run(self): | |
| self.root.mainloop() | |
| return self.points | |
| def processar(): | |
| if not os.path.exists(OUTPUT_FOLDER): os.makedirs(OUTPUT_FOLDER) | |
| print("Renderizando PDF...") | |
| doc = fitz.open(PDF_PATH) | |
| page = doc[0] | |
| pix = page.get_pixmap(matrix=fitz.Matrix(4, 4)) | |
| img_pil = Image.frombytes("RGB", [pix.width, pix.height], pix.samples) | |
| gui = CalibrationGUI(img_pil) | |
| points = gui.run() | |
| if len(points) >= 4: | |
| # 1. Tamanho do card (Baseado no Kanji 1) | |
| x1, y1 = points[0] | |
| x_br, y_br = points[1] | |
| w, h = int(abs(x_br - x1)), int(abs(y_br - y1)) | |
| # 2. Passos de grade | |
| step_x = (points[2][0] - points[0][0]) / 9.0 | |
| step_y = (points[3][1] - points[0][1]) / 9.0 # Do 1 ao 91 são 9 pulos de linha | |
| # 3. Âncoras (O primeiro ponto é o Kanji 1) | |
| anchors = [points[0]] + points[4:] | |
| print(f"\nIniciando corte. Tamanho: {w}x{h}, StepY: {step_y}") | |
| count = 0 | |
| for i in tqdm(range(TOTAL_KANJI), desc="Cortando"): | |
| anchor_idx = i // 100 | |
| if anchor_idx >= len(anchors): anchor_idx = len(anchors) - 1 | |
| ax, ay = anchors[anchor_idx] | |
| rel_i = i % 100 | |
| row = rel_i // 10 | |
| col = rel_i % 10 | |
| # Cálculo final | |
| cur_x = int(ax + col * step_x) | |
| cur_y = int(ay + row * step_y) | |
| crop = img_pil.crop((cur_x, cur_y, cur_x + w, cur_y + h)) | |
| crop.save(os.path.join(OUTPUT_FOLDER, f"{i + 1}.jpg"), quality=95) | |
| count += 1 | |
| print(f"\nSucesso! {count} imagens salvas.") | |
| if __name__ == "__main__": | |
| processar() |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
kanji pdf e cards