Remove Black Background In Images – DarkCorners

Date: 17/12/2025

Category: Python

  • Phần mềm hỗ trợ chỉnh sửa kích thước và xóa nền đen trong ảnh hàng loạt.
  • Hỗ trợ nhiều định dạng hình ảnh khác nhau.
  1. Khởi động phần mềm.
  2. Chọn thư mục chứa toàn bộ ảnh cần xử lý.
  3. Chọn thư mục xuất file ảnh đã chỉnh sửa.
  4. Nhấn nút [Bắt Đầu].
  5. Theo dõi lịch trình xử lý.
import tkinter as tk
from tkinter import filedialog, scrolledtext
import os
import cv2
import numpy as np
import threading
import queue
import time

def center_window(root, width=800, height=500):
    # 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}")

class DarkCornersRemover:
    def __init__(self, root):
        self.root = root
        self.root.title("Remove Black Background In Images - DarkCorners")
        self.root.resizable(False, False)
        center_window(self.root, 800, 500)
        self.input_dir = tk.StringVar()
        self.output_dir = tk.StringVar()
        self.processing = False
        self.thread = None
        self.log_queue = queue.Queue()
        self.build_gui()
        self.root.after(100, self.update_log)

    def build_gui(self):
        # Hàng 1: Tiêu đề
        tk.Label(self.root, text="Remove Black Background In Images - DarkCorners", font=("Arial", 18, "bold")).pack(pady=10)

        # Hàng 2: Chọn thư mục input/output
        frame_paths = tk.Frame(self.root)
        frame_paths.pack(pady=10, fill='x', padx=20)
        # Input
        frame_input = tk.Frame(frame_paths)
        frame_input.pack(side='left', expand=True, fill='x', padx=(0, 10))
        tk.Entry(frame_input, textvariable=self.input_dir, width=40).pack(side='left', expand=True, fill='x')
        tk.Button(frame_input, text="Chọn Input", command=self.select_input_dir).pack(side='left', padx=5)
        # Output
        frame_output = tk.Frame(frame_paths)
        frame_output.pack(side='left', expand=True, fill='x')
        tk.Entry(frame_output, textvariable=self.output_dir, width=40).pack(side='left', expand=True, fill='x')
        tk.Button(frame_output, text="Chọn Output", command=self.select_output_dir).pack(side='left', padx=5)

        # Hàng 3: Các nút
        frame_buttons = tk.Frame(self.root)
        frame_buttons.pack(pady=10)
        tk.Button(frame_buttons, text="Bắt Đầu", command=self.start_processing, width=15).pack(side='left', padx=10)
        tk.Button(frame_buttons, text="Tạm Dừng", command=self.stop_processing, width=15).pack(side='left', padx=10)
        tk.Button(frame_buttons, text="Thoát", command=self.root.quit, width=15).pack(side='left', padx=10)

        # Hàng 4: Logs
        tk.Label(self.root, text="Logs:", font=("Arial", 12, "bold")).pack(anchor='w', padx=20)
        self.log_area = scrolledtext.ScrolledText(self.root, width=95, height=25, state='disabled', bg="#f4f4f4")
        self.log_area.pack(padx=20, pady=10)

    def log(self, message):
        self.log_queue.put(message)

    def update_log(self):
        while not self.log_queue.empty():
            message = self.log_queue.get()
            self.log_area.config(state='normal')
            self.log_area.insert(tk.END, message + "\n")
            self.log_area.see(tk.END)
            self.log_area.config(state='disabled')
        self.root.after(100, self.update_log)

    def select_input_dir(self):
        path = filedialog.askdirectory()
        if path:
            self.input_dir.set(path)

    def select_output_dir(self):
        path = filedialog.askdirectory()
        if path:
            self.output_dir.set(path)

    def start_processing(self):
        if self.processing:
            self.log("Đang xử lý rồi...")
            return
        if not self.input_dir.get() or not self.output_dir.get():
            self.log("Vui lòng chọn thư mục Input và Output.")
            return
        self.processing = True
        self.thread = threading.Thread(target=self.process_images)
        self.thread.start()

    def stop_processing(self):
        if self.processing:
            self.processing = False
            self.log("Đã yêu cầu dừng xử lý...")

    def process_images(self):
        input_folder = self.input_dir.get()
        output_folder = self.output_dir.get()
        os.makedirs(output_folder, exist_ok=True)
        files = [f for f in os.listdir(input_folder) if f.lower().endswith(('.jpg', '.jpeg', '.png'))]
        if not files:
            self.log("Không tìm thấy ảnh trong thư mục input.")
            self.processing = False
            return
        for filename in files:
            if not self.processing:
                self.log("Quá trình đã dừng.")
                break
            input_path = os.path.join(input_folder, filename)
            output_path = os.path.join(output_folder, filename)
            self.log(f"Đang xử lý: {filename}")
            success = self.crop_black_border(input_path, output_path)
            if success:
                self.log(f"✔ Đã lưu: {output_path}")
            else:
                self.log(f"✖ Lỗi khi xử lý: {filename}")

            time.sleep(0.1)  # Delay nhỏ để log hiển thị từ từ
        self.processing = False
        self.log("✅ Hoàn tất xử lý.")

    def crop_black_border(self, image_path, output_path):
        try:
            image = cv2.imread(image_path)
            if image is None:
                return False
            gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
            _, thresh = cv2.threshold(gray, 10, 255, cv2.THRESH_BINARY)
            contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
            if not contours:
                return False
            x, y, w, h = cv2.boundingRect(np.vstack(contours))
            cropped = image[y:y+h, x:x+w]
            cv2.imwrite(output_path, cropped)
            return True
        except Exception as e:
            self.log(f"❗ Lỗi: {e}")
            return False

# Khởi chạy ứng dụng
if __name__ == "__main__":
    root = tk.Tk()
    app = DarkCornersRemover(root)
    root.mainloop()
pyinstaller --noconsole --onefile --windowed --add-data "4-RemoveBlackBackgroundInImages-icon.ico;." --icon=4-RemoveBlackBackgroundInImages-icon.ico 4-RemoveBlackBackgroundInImages-Source.py

Để lại một bình luận