upscaler / app.py
Serg4451D's picture
Update app.py
8bb0c57 verified
import gradio as gr
from PIL import Image, ImageFilter
import numpy as np
def lossless_compression(image, reduction_percent, target_size_kb, auto_mode):
"""
Сжимает изображение без потерь качества, уменьшая количество пикселей и применяя алгоритмы для сохранения деталей.
Args:
image: Входное изображение (PIL Image).
reduction_percent: Процент уменьшения пикселей по горизонтали (0-100).
target_size_kb: Желаемый размер файла в килобайтах (используется в автоматическом режиме).
auto_mode: Флаг автоматического режима (True/False).
Returns:
Сжатое изображение (PIL Image).
"""
if auto_mode:
# Автоматический подбор параметров сжатия
reduction_percent, quality = auto_adjust_compression(image, target_size_kb)
else:
# Ручной режим, используем заданный процент уменьшения
quality = 95 # Базовое качество JPEG, можно настроить
# 1. Уменьшение количества пикселей по горизонтали
width, height = image.size
new_width = int(width * (1 - reduction_percent / 100))
resized_image = image.resize((new_width, height), Image.LANCZOS)
# 2. Растягивание обратно фильтром Ланцоша
stretched_image = resized_image.resize((width, height), Image.LANCZOS)
# 3. Адаптивное размытие (уменьшение шума и артефактов)
blurred_image = adaptive_blur(stretched_image)
# 4. Повышение резкости (компенсация размытия)
sharpened_image = blurred_image.filter(ImageFilter.UnsharpMask(radius=1, percent=150, threshold=3))
# 5. Сохранение с оптимизированными параметрами
output_image = sharpened_image
# Преобразование изображения в формат, пригодный для сохранения в буфер
if output_image.mode != "RGB":
output_image = output_image.convert("RGB")
return output_image, reduction_percent, quality
def auto_adjust_compression(image, target_size_kb):
"""
Автоматически подбирает параметры сжатия для достижения целевого размера файла.
Args:
image: Входное изображение (PIL Image).
target_size_kb: Желаемый размер файла в килобайтах.
Returns:
Оптимальный процент уменьшения, оптимальное качество JPEG.
"""
# Очень грубая эвристика для начальной оценки. Нужно тестировать и улучшать
initial_reduction = min(50, int(100 * (1 - target_size_kb * 1024 / len(image.tobytes()))))
reduction_percent = initial_reduction
quality = 95
# Итеративно подбираем параметры, если нужно.
# В реальном приложении здесь может быть более сложный алгоритм
# с бинарным поиском или другими методами оптимизации.
return reduction_percent, quality
def adaptive_blur(image):
"""
Применяет адаптивное размытие к изображению.
Args:
image: Входное изображение (PIL Image).
Returns:
Изображение с адаптивным размытием (PIL Image).
"""
# Преобразуем изображение в массив NumPy для анализа
img_array = np.array(image)
# Простой пример адаптивного размытия:
# Сильнее размываем области с меньшим количеством деталей (меньше дисперсия)
# Это очень базовый пример, нужно улучшать в зависимости от задачи
std_dev = np.std(img_array)
if std_dev < 20: # Порог стандартного отклонения - настраиваемый параметр
# Применяем более сильное размытие
blurred_image = image.filter(ImageFilter.GaussianBlur(radius=2))
else:
# Применяем слабое размытие
blurred_image = image.filter(ImageFilter.GaussianBlur(radius=1))
return blurred_image
def save_compressed_image(image, quality, filename="compressed_image.jpg"):
"""
Сохраняет сжатое изображение с указанным качеством.
Args:
image: PIL Image.
quality: Качество JPEG (0-100).
filename: Имя файла для сохранения.
"""
image.save(filename, "JPEG", optimize=True, quality=quality)
# Интерфейс Gradio
def gradio_interface(image, reduction_percent, target_size_kb, auto_mode):
compressed_image, used_reduction, used_quality = lossless_compression(image, reduction_percent, target_size_kb, auto_mode)
save_compressed_image(compressed_image, used_quality)
return compressed_image, f"Использованное уменьшение: {used_reduction:.2f}%, Качество JPEG: {used_quality}"
iface = gr.Interface(
fn=gradio_interface,
inputs=[
gr.Image(type="pil", label="Исходное изображение"),
gr.Slider(0, 50, step=1, value=12, label="Процент уменьшения пикселей по горизонтали (ручной режим)"),
gr.Slider(1, 200, step=1, value=50, label="Желаемый размер файла в KB (автоматический режим)"),
gr.Checkbox(label="Автоматический режим"),
],
outputs=[
gr.Image(type="pil", label="Сжатое изображение"),
gr.Textbox(label="Параметры сжатия")
],
title="Сжатие изображений без потерь",
description="Уменьшает размер изображения, сохраняя визуальное качество. "
"Выберите автоматический режим или введите желаемый размер файла "
"или процент уменьшения пикселей вручную.",
)
iface.launch()