图片无损放大,无需AI模型一个脚本搞定

查看 81|回复 11
作者:thisbug   
[color=]把我经常用的代码合集一个一个放出来分享给大家
经常在某些网站或应用上上传图片说分辨率太小什么的,直接用这个脚本就行
[color=]本地运行,无需网络,上万张图片无损放大几分钟就搞定
这个脚本一键搞定一个目录下所有图片三倍无损放大(递归处理)并覆盖原图
[Python] 纯文本查看 复制代码import os
from PIL import Image
import shutil
def resize_and_replace(image_path):
    """放大图片并覆盖原文件(通过临时文件确保原子性操作)"""
    try:
        # 打开图片并计算新尺寸
        with Image.open(image_path) as img:
            width, height = img.size
            new_size = (width * 3, height * 3)
            # 使用高质量插值算法放大图像
            resized_img = img.resize(new_size, Image.Resampling.LANCZOS)
            # 根据原格式保存参数优化
            file_ext = os.path.splitext(image_path)[1].lower()
            temp_path = image_path + ".tmp"
            save_args = {'format': img.format, 'quality': 95} if file_ext in ('.jpg', '.jpeg') \
                else {'format': img.format, 'optimize': True} if file_ext == '.png' \
                else {'format': img.format}
            # 保存到临时文件后覆盖原文件
            resized_img.save(temp_path, **save_args)
            os.replace(temp_path, image_path)
            print(f"已处理: {image_path}")
    except Exception as e:
        print(f"处理失败: {image_path} - 错误: {str(e)}")
        if os.path.exists(temp_path):
            os.remove(temp_path)
def process_directory(root_dir):
    """递归处理目录下的所有图片"""
    for foldername, _, filenames in os.walk(root_dir):
        for filename in filenames:
            file_path = os.path.join(foldername, filename)
            # 检查文件大小和扩展名
            if os.path.getsize(file_path) >= 50 * 1024:
                continue
            if not file_path.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif', '.tiff')):
                continue
            resize_and_replace(file_path)
'''
图片三倍无损放大
'''
if __name__ == "__main__":
    target_dir = input("请输入目标文件夹路径: ").strip()
    if os.path.isdir(target_dir):
        process_directory(target_dir)
    else:
        print("路径无效!")

微软, 图片

thisbug
OP
  

对了,脚本是检测小于50k的图片直接三倍无损放大
可以按需自己修改
netdna518   

楼主这个很赞!但是加上界面会更好点吧。
[Python] 纯文本查看 复制代码import os
import threading
from tkinter import (
    Tk, Label, Entry, Button, StringVar, IntVar, Checkbutton, Text,
    filedialog, Frame, ttk, DISABLED, NORMAL
)
from PIL import Image
class ImageResizerApp:
    def __init__(self, root):
        self.root = root
        self.root.title("图片批量无损放大工具")
        self.center_window(858, 600)  # 居中窗口
        self.stop_flag = False
        self.supported_exts = ['.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff']
        self.selected_exts = []
        self.processed_count = 0
        self.skipped_count = 0
        self.failed_count = 0
        self.build_gui()
    def center_window(self, width, height):
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        x = int((screen_width - width) / 2)
        y = int((screen_height - height) / 2)
        self.root.geometry(f"{width}x{height}+{x}+{y}")
    def build_gui(self):
        # 输入路径
        Label(self.root, text="输入文件夹:").grid(row=0, column=0, sticky='e')
        self.input_entry = Entry(self.root, width=60)
        self.input_entry.grid(row=0, column=1, padx=5)
        Button(self.root, text="浏览", command=self.select_input).grid(row=0, column=2)
        # 覆盖原图(独立一行)
        self.overwrite_var = IntVar()
        Checkbutton(self.root, text="覆盖原图", variable=self.overwrite_var, command=self.toggle_output).grid(
            row=1, column=0, columnspan=3, sticky='w', padx=20, pady=2)
        # 输出路径(带标签)
        Label(self.root, text="输出文件夹:").grid(row=2, column=0, sticky='e')
        self.output_entry = Entry(self.root, width=60)
        self.output_entry.grid(row=2, column=1, padx=5)
        Button(self.root, text="浏览", command=self.select_output).grid(row=2, column=2)
        # 放大倍数
        Label(self.root, text="放大倍数:").grid(row=3, column=0, sticky='e')
        self.scale_var = StringVar(value="3")
        Entry(self.root, textvariable=self.scale_var, width=10).grid(row=3, column=1, sticky='w')
        # 文件大小限制
        Label(self.root, text="图片体积大于 KB自动跳过:").grid(row=3, column=1, sticky='e')
        self.size_limit_var = StringVar(value="50")
        Entry(self.root, textvariable=self.size_limit_var, width=10).grid(row=3, column=2, sticky='w')
        # 图片格式选择
        Label(self.root, text="图片格式:").grid(row=4, column=0, sticky='ne')
        self.ext_vars = {}
        format_frame = Frame(self.root)
        format_frame.grid(row=4, column=1, sticky='w')
        for ext in self.supported_exts:
            var = IntVar(value=1)
            Checkbutton(format_frame, text=ext, variable=var).pack(side='left')
            self.ext_vars[ext] = var
        # 自定义扩展名
        Label(self.root, text="追加自定义\n图片类型扩展名 (逗号分隔):").grid(row=5, column=0, sticky='e')
        self.custom_ext_entry = Entry(self.root, width=60)
        self.custom_ext_entry.grid(row=5, column=1, padx=5, pady=2)
        # 按钮 + 进度条
        button_frame = Frame(self.root)
        button_frame.grid(row=6, column=0, columnspan=3, pady=10)
        self.start_btn = Button(button_frame, text="开始处理", command=self.start_processing)
        self.start_btn.pack(side='left', padx=5)
        self.stop_btn = Button(button_frame, text="停止", command=self.stop_processing, state=DISABLED)
        self.stop_btn.pack(side='left', padx=5)
        self.progress = ttk.Progressbar(self.root, length=500)
        self.progress.grid(row=7, column=0, columnspan=3, pady=10)
        # 日志区
        Label(self.root, text="日志:").grid(row=8, column=0, sticky='ne')
        self.log_text = Text(self.root, width=95, height=20)
        self.log_text.grid(row=8, column=1, columnspan=2)
    def select_input(self):
        folder = filedialog.askdirectory()
        if folder:
            self.input_entry.delete(0, 'end')
            self.input_entry.insert(0, folder)
    def select_output(self):
        folder = filedialog.askdirectory()
        if folder:
            self.output_entry.delete(0, 'end')
            self.output_entry.insert(0, folder)
    def toggle_output(self):
        state = DISABLED if self.overwrite_var.get() else NORMAL
        self.output_entry.config(state=state)
    def log(self, message):
        self.log_text.insert('end', message + '\n')
        self.log_text.see('end')
    def start_processing(self):
        self.stop_flag = False
        self.start_btn.config(state=DISABLED)
        self.stop_btn.config(state=NORMAL)
        self.log_text.delete('1.0', 'end')
        threading.Thread(target=self.process_images).start()
    def stop_processing(self):
        self.stop_flag = True
        self.log("正在停止...")
    def process_images(self):
        input_dir = self.input_entry.get().strip()
        output_dir = self.output_entry.get().strip()
        scale = int(self.scale_var.get())
        size_limit_kb = int(self.size_limit_var.get())
        self.selected_exts = [ext for ext, var in self.ext_vars.items() if var.get()]
        custom_exts = [e.strip().lower() if e.startswith('.') else f".{e.strip().lower()}"
                       for e in self.custom_ext_entry.get().replace(',', ',').split(',') if e.strip()]
        self.selected_exts.extend(custom_exts)
        if not os.path.isdir(input_dir):
            self.log("❌ 输入文件夹无效!")
            return
        all_files = []
        for foldername, _, filenames in os.walk(input_dir):
            for filename in filenames:
                ext = os.path.splitext(filename)[1].lower()
                if ext in self.selected_exts:
                    all_files.append(os.path.join(foldername, filename))
        self.progress["maximum"] = len(all_files)
        self.progress["value"] = 0
        self.processed_count = self.skipped_count = self.failed_count = 0
        for i, file_path in enumerate(all_files):
            if self.stop_flag:
                self.log("⏹ 已停止处理。")
                break
            try:
                if os.path.getsize(file_path) >= size_limit_kb * 1024:
                    self.log(f"跳过(文件过大): {file_path}")
                    self.skipped_count += 1
                    continue
                with Image.open(file_path) as img:
                    new_size = (img.width * scale, img.height * scale)
                    resized_img = img.resize(new_size, Image.Resampling.LANCZOS)
                    if self.overwrite_var.get():
                        save_path = file_path
                    else:
                        rel_path = os.path.relpath(file_path, input_dir)
                        save_path = os.path.join(output_dir, rel_path)
                        os.makedirs(os.path.dirname(save_path), exist_ok=True)
                    file_ext = os.path.splitext(save_path)[1].lower()
                    temp_path = save_path + ".tmp"
                    save_args = {'format': img.format, 'quality': 95} if file_ext in ('.jpg', '.jpeg') \
                        else {'format': img.format, 'optimize': True} if file_ext == '.png' \
                        else {'format': img.format}
                    resized_img.save(temp_path, **save_args)
                    os.replace(temp_path, save_path)
                    self.log(f"✅ 已处理: {file_path}")
                    self.processed_count += 1
            except Exception as e:
                self.log(f"❌ 失败: {file_path} - 错误: {str(e)}")
                self.failed_count += 1
            self.progress["value"] = i + 1
        self.log(f"🎉 完成!成功处理: {self.processed_count} 张,跳过: {self.skipped_count} 张,失败: {self.failed_count} 张")
        self.start_btn.config(state=NORMAL)
        self.stop_btn.config(state=DISABLED)
if __name__ == "__main__":
    root = Tk()
    app = ImageResizerApp(root)
    root.mainloop()
tomliu   

是放大了一些
ericszy525   


ericszy525 发表于 2025-6-3 17:19
github上有个项目 可以真实放大图片

Upscayl     这个
茶城兄弟   

这个,效果可以吗?
thisbug
OP
  


茶城兄弟 发表于 2025-6-3 11:44
这个,效果可以吗?

我用着还行吧,跟用AI模型跑出来的没啥区别,这个脚本跑完一千张图AI才跑完一张图
chen2020   

不明觉厉,可以试试
dly7202   

谢谢分享哦
skyfxf   

我理解的放大  是把图片上的 每个像素点变成4个,这样图片被放大了4倍,比例不变。这个3倍大小是怎么实现的哪?
您需要登录后才可以回帖 登录 | 立即注册

返回顶部