/
karik
/
fifth
Обзор
Документация
Войти
/
karik
/
fifth
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
5.py
308 строк
14 KB
karik
upload files
10 ноя 2025, 15:16
10 ноя 2025, 15:16
58c30a4
Код
Авторство
О чём код?
import tkinter as tk from tkinter import filedialog, messagebox from PIL import Image, ImageTk, ImageChops # ----------------------------- # Обработка изображений # ----------------------------- def brightness(pixel): """Возвращает яркость пикселя (0-255).""" r, g, b = pixel return 0.299 * r + 0.587 * g + 0.114 * b def max_contrast_above_20(img): """Увеличивает до максимума контраст точек, яркость которых превышает 20%.""" img = img.convert("RGB") pixels = img.load() w, h = img.size # 20% от максимальной яркости (255) threshold = 0.2 * 255 for y in range(h): for x in range(w): r, g, b = pixels[x, y] current_brightness = brightness((r, g, b)) # Если яркость превышает 20%, увеличиваем контраст до максимума if current_brightness > threshold: # Нормализуем значения в диапазон [0, 1] r_norm = r / 255.0 g_norm = g / 255.0 b_norm = b / 255.0 # Применяем сильную S-образную кривую для увеличения контраста def enhance_contrast(channel): if channel < 0.5: return 0 # Все тени делаем черными else: return 1 # Все света делаем белыми r_enhanced = enhance_contrast(r_norm) g_enhanced = enhance_contrast(g_norm) b_enhanced = enhance_contrast(b_norm) # Возвращаем в диапазон [0, 255] pixels[x, y] = ( int(r_enhanced * 255), int(g_enhanced * 255), int(b_enhanced * 255) ) return img def multiply_blend(img1, img2): """Наложение методом 'Умножение' по формуле: C_res = C1 * C2""" # Приводим оба изображения к одинаковому размеру img2 = img2.resize(img1.size) # Приводим оба изображения к одинаковому режиму (RGB) if img1.mode != img2.mode: img1 = img1.convert("RGB") img2 = img2.convert("RGB") # Создаем новое изображение для результата result = Image.new("RGB", img1.size) pixels1 = img1.load() pixels2 = img2.load() pixels_result = result.load() w, h = img1.size for y in range(h): for x in range(w): r1, g1, b1 = pixels1[x, y] r2, g2, b2 = pixels2[x, y] # Нормализуем значения в диапазон [0, 1] r1_norm = r1 / 255.0 g1_norm = g1 / 255.0 b1_norm = b1 / 255.0 r2_norm = r2 / 255.0 g2_norm = g2 / 255.0 b2_norm = b2 / 255.0 # Применяем формулу умножения: C_res = C1 * C2 r_res = r1_norm * r2_norm g_res = g1_norm * g2_norm b_res = b1_norm * b2_norm # Возвращаем в диапазон [0, 255] pixels_result[x, y] = ( int(r_res * 255), int(g_res * 255), int(b_res * 255) ) return result def resize_image(img, max_width=300, max_height=300): """Масштабирует изображение с сохранением пропорций""" width, height = img.size # Вычисляем новые размеры с сохранением пропорций ratio = min(max_width/width, max_height/height) new_width = int(width * ratio) new_height = int(height * ratio) return img.resize((new_width, new_height), Image.Resampling.LANCZOS) # ----------------------------- # Обработчики кнопок # ----------------------------- def open_first(): global img1, tk_img1 path = filedialog.askopenfilename( title="Выберите первое изображение", filetypes=[("Изображения", "*.jpg *.jpeg *.png *.bmp *.gif *.pbm *.pgm *.ppm"), ("Netpbm", "*.pbm *.pgm *.ppm"), ("Все файлы", "*.*")] ) if not path: return try: img1 = Image.open(path) # Масштабируем изображение для отображения display_img = resize_image(img1) tk_img1 = ImageTk.PhotoImage(display_img) label1.config(image=tk_img1, text="") # Обновляем размер метки под изображение label1.config(width=display_img.width, height=display_img.height) print(f"Первое изображение загружено: {path}") except Exception as e: messagebox.showerror("Ошибка", f"Не удалось загрузить изображение:\n{str(e)}") def open_second(): global img2, tk_img2 path = filedialog.askopenfilename( title="Выберите второе изображение", filetypes=[("Изображения", "*.jpg *.jpeg *.png *.bmp *.gif *.pbm *.pgm *.ppm"), ("Netpbm", "*.pbm *.pgm *.ppm"), ("Все файлы", "*.*")] ) if not path: return try: img2 = Image.open(path) # Масштабируем изображение для отображения display_img = resize_image(img2) tk_img2 = ImageTk.PhotoImage(display_img) label2.config(image=tk_img2, text="") # Обновляем размер метки под изображение label2.config(width=display_img.width, height=display_img.height) print(f"Второе изображение загружено: {path}") except Exception as e: messagebox.showerror("Ошибка", f"Не удалось загрузить изображение:\n{str(e)}") def process(): global result_img, tk_result, contrast_enhanced_img try: if img1 is None: messagebox.showwarning("Предупреждение", "Сначала загрузите первое изображение.") return if img2 is None: messagebox.showwarning("Предупреждение", "Сначала загрузите второе изображение.") return # Сохраняем промежуточное изображение с увеличенным контрастом contrast_enhanced_img = max_contrast_above_20(img1.copy()) # Применяем наложение методом "Умножение" result_img = multiply_blend(contrast_enhanced_img, img2) # Масштабируем результат для отображения display_result = resize_image(result_img) tk_result = ImageTk.PhotoImage(display_result) label_result.config(image=tk_result, text="") # Обновляем размер метки под изображение label_result.config(width=display_result.width, height=display_result.height) print("Обработка завершена успешно") except Exception as e: messagebox.showerror("Ошибка", f"Ошибка обработки:\n{str(e)}") def save_contrast_enhanced(): """Сохраняет изображение с увеличенным контрастом""" if contrast_enhanced_img is None: messagebox.showwarning("Нет результата", "Сначала обработайте изображения.") return path = filedialog.asksaveasfilename( title="Сохранить изображение с увеличенным контрастом", defaultextension=".ppm", filetypes=[("PPM", "*.ppm"), ("PGM", "*.pgm"), ("PBM", "*.pbm"), ("PNG", "*.png"), ("JPEG", "*.jpg"), ("Все файлы", "*.*")] ) if path: try: # Определяем формат на основе расширения if path.lower().endswith(('.pbm', '.pgm', '.ppm')): # Для Netpbm форматов нужно преобразовать в соответствующий режим if path.lower().endswith('.pbm'): # PBM - черно-белое (1 бит) save_img = contrast_enhanced_img.convert('1') elif path.lower().endswith('.pgm'): # PGM - оттенки серого save_img = contrast_enhanced_img.convert('L') else: # PPM - цветное save_img = contrast_enhanced_img.convert('RGB') save_img.save(path) else: contrast_enhanced_img.save(path) messagebox.showinfo("Сохранено", f"Изображение с увеличенным контрастом сохранёно в:\n{path}") print(f"Изображение с увеличенным контрастом сохранено: {path}") except Exception as e: messagebox.showerror("Ошибка", f"Не удалось сохранить файл:\n{str(e)}") def save_result(): if result_img is None: messagebox.showwarning("Нет результата", "Сначала обработайте изображения.") return path = filedialog.asksaveasfilename( title="Сохранить результат", defaultextension=".ppm", filetypes=[("PPM", "*.ppm"), ("PGM", "*.pgm"), ("PBM", "*.pbm"), ("PNG", "*.png"), ("JPEG", "*.jpg"), ("Все файлы", "*.*")] ) if path: try: # Определяем формат на основе расширения if path.lower().endswith(('.pbm', '.pgm', '.ppm')): # Для Netpbm форматов нужно преобразовать в соответствующий режим if path.lower().endswith('.pbm'): # PBM - черно-белое (1 бит) save_img = result_img.convert('1') elif path.lower().endswith('.pgm'): # PGM - оттенки серого save_img = result_img.convert('L') else: # PPM - цветное save_img = result_img.convert('RGB') save_img.save(path) else: result_img.save(path) messagebox.showinfo("Сохранено", f"Результат сохранён в:\n{path}") print(f"Изображение сохранено: {path}") except Exception as e: messagebox.showerror("Ошибка", f"Не удалось сохранить файл:\n{str(e)}") # ----------------------------- # Интерфейс # ----------------------------- # Инициализация глобальных переменных img1 = None img2 = None contrast_enhanced_img = None result_img = None tk_img1 = None tk_img2 = None tk_result = None # Создание главного окна root = tk.Tk() root.title("Обработка изображений") root.geometry("900x600") # Фрейм для изображений frame_images = tk.Frame(root) frame_images.pack(pady=15) # Метки для изображений БЕЗ фиксированных размеров label1 = tk.Label(frame_images, text="Изображение 1\n(Нажмите кнопку загрузки)", bg="#f0f0f0", relief="solid", borderwidth=1) label1.grid(row=0, column=0, padx=10, pady=5) label2 = tk.Label(frame_images, text="Изображение 2\n(Нажмите кнопку загрузки)", bg="#f0f0f0", relief="solid", borderwidth=1) label2.grid(row=0, column=1, padx=10, pady=5) label_result = tk.Label(frame_images, text="Результат\n(Нажмите кнопку обработки)", bg="#f0f0f0", relief="solid", borderwidth=1) label_result.grid(row=0, column=2, padx=10, pady=5) # Фрейм для кнопок button_frame = tk.Frame(root) button_frame.pack(pady=15) # Кнопки btn1 = tk.Button(button_frame, text="Загрузить 1-е изображение", command=open_first, width=25) btn1.grid(row=0, column=0, padx=5, pady=5) btn2 = tk.Button(button_frame, text="Загрузить 2-е изображение", command=open_second, width=25) btn2.grid(row=0, column=1, padx=5, pady=5) btn3 = tk.Button(button_frame, text="Обработать", command=process, width=25, bg="#90EE90") btn3.grid(row=1, column=0, padx=5, pady=5) btn4 = tk.Button(button_frame, text="Сохранить наложение", command=save_result, width=25, bg="#ADD8E6") btn4.grid(row=1, column=1, padx=5, pady=5) btn5 = tk.Button(button_frame, text="Сохранить преобразование", command=save_contrast_enhanced, width=25, bg="#FFB6C1") btn5.grid(row=2, column=0, columnspan=2, padx=5, pady=5) # Запуск главного цикла root.mainloop()