import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import ImageGrab, ImageTk
import pytesseract
import pyperclip
import os
# --- Cấu hình đường dẫn đến tesseract ---
BASE_PATH = os.path.join(os.path.dirname(__file__), 'OCRSnipping-Data')
TESS_PATH = os.path.join(BASE_PATH, 'tesseract.exe')
TESSDATA_PATH = os.path.join(BASE_PATH, 'tessdata')
pytesseract.pytesseract.tesseract_cmd = TESS_PATH
os.environ['TESSDATA_PREFIX'] = TESSDATA_PATH
def center_window(root, width=600, height=400):
# Lấy kích thước màn hình
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
# Tính vị trí bắt đầu trục ngang và trục đứng
aaaxxx = (screen_width // 2) - (width // 2)
bbbyyy = (screen_height // 2) - (height // 2) - (40)
# Đặt geometry
root.geometry(f"{width}x{height}+{aaaxxx}+{bbbyyy}")
# --- Giao diện chính ---
class OCRSnippingApp:
def __init__(self, root):
self.root = root
self.root.title("OCR Snipping - DarkCorners")
self.root.resizable(False, False)
center_window(self.root, 600, 400)
self.lang_var = tk.StringVar(value="vie+eng+chi_tra+chi_sim")
self.status_var = tk.StringVar(value="Đã sẵn sàng")
title = tk.Label(root, text="🖼️ OCR Snipping Tool - DarkCorners", font=("Arial", 16, "bold"))
title.pack(pady=10)
frame = tk.Frame(root)
frame.pack(pady=5)
tk.Label(frame, text="Ngôn ngữ OCR (ví dụ: vie, eng, chi_tra, chi_sim):").pack()
self.lang_entry = tk.Entry(frame, textvariable=self.lang_var, width=40)
self.lang_entry.pack(pady=5)
self.snip_button = tk.Button(root, text="📸 Chụp & OCR", font=("Arial", 14), command=self.start_snipping)
self.snip_button.pack(pady=10)
self.text_box = tk.Text(root, wrap="word", height=10)
self.text_box.pack(padx=10, pady=10, fill="both", expand=True)
self.copy_button = tk.Button(root, text="📋 Sao chép văn bản", command=self.copy_to_clipboard)
self.copy_button.pack(pady=5)
self.status_label = tk.Label(root, textvariable=self.status_var, fg="green")
self.status_label.pack(pady=5)
def update_status(self, msg, error=False):
self.status_var.set(msg)
self.status_label.config(fg="red" if error else "green")
def copy_to_clipboard(self):
content = self.text_box.get("1.0", tk.END).strip()
if content:
pyperclip.copy(content)
self.update_status("Đã sao chép vào clipboard.")
else:
self.update_status("Không có nội dung để sao chép.", error=True)
def start_snipping(self):
self.root.withdraw()
self.update_status("Đang chờ chọn vùng ảnh...")
self.root.after(500, self.snip_screen)
def snip_screen(self):
self.snip_win = tk.Toplevel()
self.snip_win.attributes("-fullscreen", True)
self.snip_win.attributes("-alpha", 0.3)
self.snip_win.configure(background='gray')
self.snip_win.bind("", self.on_mouse_down)
self.snip_win.bind("", self.on_mouse_drag)
self.snip_win.bind("", self.on_mouse_up)
self.start_x = self.start_y = self.rect = None
def on_mouse_down(self, event):
self.start_x, self.start_y = event.x, event.y
self.canvas = tk.Canvas(self.snip_win, cursor="cross", bg="gray", highlightthickness=0)
self.canvas.pack(fill=tk.BOTH, expand=True)
self.rect = self.canvas.create_rectangle(self.start_x, self.start_y, self.start_x, self.start_y, outline='red', width=2)
def on_mouse_drag(self, event):
self.canvas.coords(self.rect, self.start_x, self.start_y, event.x, event.y)
def on_mouse_up(self, event):
x1, y1 = self.start_x, self.start_y
x2, y2 = event.x, event.y
self.snip_win.destroy()
self.root.deiconify()
self.root.lift()
self.extract_text_from_area(x1, y1, x2, y2)
def extract_text_from_area(self, x1, y1, x2, y2):
bbox = (min(x1, x2), min(y1, y2), max(x1, x2), max(y1, y2))
try:
img = ImageGrab.grab(bbox)
lang = self.lang_var.get().strip()
text = pytesseract.image_to_string(img, lang=lang)
self.text_box.delete("1.0", tk.END)
self.text_box.insert(tk.END, text.strip())
self.update_status("Đã nhận diện xong.")
except Exception as e:
self.update_status(f"Lỗi: {str(e)}", error=True)
# --- Khởi động ứng dụng ---
if __name__ == "__main__":
root = tk.Tk()
app = OCRSnippingApp(root)
root.mainloop()