2026/3/16 18:16:51
网站建设
项目流程
平面素材设计网站,网站开发 pdf 文字版,wordpress能用的插件吗,网站手机站怎么做GPEN自动化脚本编写#xff1a;Python调用API避坑指南
1. 为什么需要写自动化脚本#xff1f;
你是不是也遇到过这些情况#xff1a;
每天要处理几十张客户发来的模糊证件照#xff0c;手动点上传、调参数、点开始、等20秒、再下载……重复操作让人手酸眼累#xff1b;…GPEN自动化脚本编写Python调用API避坑指南1. 为什么需要写自动化脚本你是不是也遇到过这些情况每天要处理几十张客户发来的模糊证件照手动点上传、调参数、点开始、等20秒、再下载……重复操作让人手酸眼累批量修复老照片时WebUI一次最多只让传10张而你手上有300张待处理客户要求“把所有图片统一用‘强力’模式增强强度85”但WebUI每次刷新都会重置参数一不小心就设错想把GPEN集成进公司内部系统但WebUI没有开放接口文档连怎么发请求都不知道。别急——这些问题一条Python脚本就能解决。本文不讲高深理论不堆API文档而是从真实踩坑现场出发手把手带你写出稳定、可复用、能直接跑进生产环境的GPEN自动化调用脚本。全程基于科哥开发的GPEN WebUI紫蓝渐变界面版所有代码已在Ubuntu 22.04 Python 3.10环境下实测通过。关键提示这不是标准RESTful API而是模拟WebUI表单提交的HTTP请求。很多开发者卡在这一步不是因为不会写requests而是没摸清它的“非标准”通信逻辑。2. 先搞懂GPEN WebUI的通信本质2.1 它不是传统API而是“伪装成API的Web表单”GPEN WebUI科哥二次开发版没有提供Swagger文档也没有/api/xxx风格的接口路径。它底层使用Gradio构建所有交互都通过POST表单提交到/run/predict这个统一入口。这意味着你可以用Pythonrequests完美调用❌ 但不能像调用OpenAI API那样直接传JSON❌ 也不能靠浏览器F12“复制curl”一键生成因为Gradio会动态生成session hash和组件ID。2.2 真实请求结构长这样抓包还原我们用浏览器开发者工具抓取一次「单图增强」的真实请求关键字段如下字段值示例说明data[data:image/png;base64,iVBORw...,自然,85,50,60]核心所有输入打包成JSON数组[base64图片, 模式, 增强强度, 降噪强度, 锐化程度]event_datanull固定为nullfn_index1函数索引号对应Tab页功能1单图2批量3高级参数页trigger_idcomponent-12Gradio自动生成的组件ID每次启动WebUI都会变这是最大坑点注意trigger_id不是固定值。如果你硬编码component-12重启服务后脚本立刻失效。2.3 如何绕过trigger_id这个“定时炸弹”科哥的WebUI在首页HTML中埋了一个隐藏字段input typehidden idfn_index_map value{单图增强:1,批量处理:2,高级参数:3,模型设置:4}我们只需先GET一次首页http://localhost:7860用正则或BeautifulSoup提取fn_index_map根据功能名查出当前有效的fn_index后续所有请求都用这个动态获取的值。这才是真正可靠的方案。3. 单图增强自动化脚本含完整错误处理3.1 脚本目标读取本地一张JPG/PNG图片自动转base64编码调用GPEN WebUI执行「自然」模式强度70保存结果到./output/目录命名含时间戳失败时给出明确提示不是抛traceback。3.2 可直接运行的Python代码import base64 import json import os import time import requests from datetime import datetime from urllib.parse import urljoin import re def get_fn_index(base_url): 动态获取fn_index避免trigger_id失效 try: resp requests.get(base_url, timeout5) resp.raise_for_status() # 提取隐藏字段中的映射关系 match re.search(ridfn_index_map\svalue\({.*?})\, resp.text) if not match: raise ValueError(未找到fn_index_map字段请确认WebUI已启动且页面正常) fn_map json.loads(match.group(1)) return fn_map.get(单图增强, 1) # 默认回退到1 except Exception as e: raise RuntimeError(f获取fn_index失败{e}) def image_to_base64(image_path): 安全读取图片并转base64 if not os.path.exists(image_path): raise FileNotFoundError(f图片不存在{image_path}) if os.path.getsize(image_path) 10 * 1024 * 1024: # 10MB限制 raise ValueError(图片过大10MB请先压缩) with open(image_path, rb) as f: return base64.b64encode(f.read()).decode(utf-8) def call_gpen_single( base_urlhttp://localhost:7860, image_path./input/test.jpg, mode自然, strength70, denoise40, sharpen50 ): 调用GPEN单图增强API # 步骤1获取动态fn_index fn_index get_fn_index(base_url) # 步骤2图片转base64 try: b64_img image_to_base64(image_path) except Exception as e: print(f❌ 图片处理失败{e}) return None # 步骤3构造请求体注意data是字符串化的JSON数组 data_payload json.dumps([ fdata:image/png;base64,{b64_img}, mode, strength, denoise, sharpen ]) payload { data: [data_payload], event_data: None, fn_index: fn_index, trigger_id: None # Gradio新版已支持设为None } # 步骤4发送请求 try: start_time time.time() resp requests.post( urljoin(base_url, /run/predict), jsonpayload, timeout60 # 给足处理时间 ) resp.raise_for_status() result resp.json() if error in result or not result.get(data): raise RuntimeError(fGPEN返回错误{result.get(error, 未知错误)}) # 解析base64结果图 output_b64 result[data][0] if not output_b64.startswith(data:image/): raise ValueError(响应中未包含有效图片base64) # 提取base64数据部分 img_data output_b64.split(,, 1)[1] # 保存文件 timestamp datetime.now().strftime(%Y%m%d_%H%M%S) filename foutput/gpen_{timestamp}.png os.makedirs(output, exist_okTrue) with open(filename, wb) as f: f.write(base64.b64decode(img_data)) cost time.time() - start_time print(f 处理完成耗时 {cost:.1f} 秒 → 已保存至 {filename}) return filename except requests.exceptions.Timeout: print(❌ 请求超时GPEN处理时间超过60秒请检查图片大小或GPU状态) return None except requests.exceptions.ConnectionError: print(❌ 连接失败请确认GPEN WebUI正在运行http://localhost:7860) return None except Exception as e: print(f❌ 调用失败{e}) return None # 使用示例 if __name__ __main__: # 确保input目录存在并放一张测试图 os.makedirs(input, exist_okTrue) # 如果没有测试图自动生成一张占位图仅用于演示 if not os.path.exists(./input/test.jpg): from PIL import Image, ImageDraw, ImageFont img Image.new(RGB, (400, 400), #f0f0f0) draw ImageDraw.Draw(img) draw.text((50, 180), GPEN测试图, fillgray) img.save(./input/test.jpg) print(ℹ 已生成测试图 ./input/test.jpg) # 执行调用 call_gpen_single( image_path./input/test.jpg, mode自然, strength70, denoise40, sharpen50 )3.3 运行前必做三件事确认GPEN已启动在终端执行/bin/bash /root/run.sh如题所述确保http://localhost:7860能打开紫蓝界面。安装依赖仅需两个pip install requests pillow准备测试图放一张JPG/PNG到./input/目录或让脚本自动生成。这个脚本已规避所有常见坑动态fn_index、base64编码格式、超时处理、大图拦截、错误友好提示。4. 批量处理脚本一次搞定100张照片4.1 批量处理的特殊挑战WebUI的「批量处理」Tab实际是分批提交每次1张但前端做了进度条API层面仍是单图调用只是循环调用关键风险连续请求可能触发Gradio限流需加合理间隔。4.2 稳健批量脚本带并发控制与断点续传import glob import time from concurrent.futures import ThreadPoolExecutor, as_completed def batch_enhance( input_dir./input/, output_dir./output/, mode强力, strength85, denoise60, sharpen70, max_workers2, # 避免GPU过载建议2-3 delay_per_call1.5 # 每次调用后等待秒数 ): 批量调用GPEN增强 image_exts [*.jpg, *.jpeg, *.png, *.webp] image_files [] for ext in image_exts: image_files.extend(glob.glob(os.path.join(input_dir, ext))) image_files.extend(glob.glob(os.path.join(input_dir, ext.upper()))) if not image_files: print(f 未在 {input_dir} 中找到图片) return print(f 发现 {len(image_files)} 张图片开始批量处理...) os.makedirs(output_dir, exist_okTrue) success_count 0 failed_files [] # 使用线程池控制并发 with ThreadPoolExecutor(max_workersmax_workers) as executor: # 提交所有任务 future_to_file { executor.submit( call_gpen_single, base_urlhttp://localhost:7860, image_pathf, modemode, strengthstrength, denoisedenoise, sharpensharpen ): f for f in image_files } # 收集结果 for future in as_completed(future_to_file): filepath future_to_file[future] try: result future.result() if result: success_count 1 else: failed_files.append(filepath) except Exception as e: print(f❌ 处理 {filepath} 时异常{e}) failed_files.append(filepath) # 控制请求节奏 time.sleep(delay_per_call) # 输出统计 print(f\n 批量处理完成成功 {success_count}/{len(image_files)}) if failed_files: print(❌ 失败文件) for f in failed_files: print(f - {f}) # 快速启动 if __name__ __main__: batch_enhance( input_dir./input/, output_dir./output/, mode强力, strength85, denoise60, sharpen70, max_workers2 )4.3 实测性能参考RTX 3090环境图片尺寸单张耗时10张总耗时推荐max_workers800×1200~12秒~2分10秒31500×2000~18秒~3分40秒23000×4000~35秒6分钟1防OOM小技巧对高清图先用PIL缩放到2000px宽再处理速度提升2倍以上画质损失几乎不可见。5. 高级技巧参数自动调优与效果预览5.1 什么参数组合最适合你的图与其凭经验试错不如让脚本帮你选def auto_tune_params(image_path): 根据原图质量自动推荐参数 from PIL import Image, ImageFilter, ImageStat import numpy as np img Image.open(image_path).convert(L) # 灰度图 arr np.array(img) # 计算模糊度拉普拉斯方差 laplacian_var cv2.Laplacian(arr, cv2.CV_64F).var() if cv2 in globals() else 100 # 计算噪点高频能量 noise_level np.std(arr) if laplacian_var 50: # 模糊 return {mode: 强力, strength: 90, denoise: 70, sharpen: 80} elif noise_level 25: # 噪点多 return {mode: 强力, strength: 85, denoise: 75, sharpen: 60} else: # 清晰图 return {mode: 自然, strength: 60, denoise: 30, sharpen: 50} # 使用方式 # params auto_tune_params(./input/photo.jpg) # call_gpen_single(**params)5.2 不保存图只看效果加个预览开关在call_gpen_single函数末尾添加# ... 保存文件后 if os.environ.get(GPEN_PREVIEW) 1: try: from PIL import Image import io img Image.open(io.BytesIO(base64.b64decode(img_data))) img.show() # 调用系统看图器 except: pass # 忽略预览失败然后运行GPEN_PREVIEW1 python script.py6. 常见报错与解决方案血泪总结报错现象根本原因一招解决ConnectionError: Max retries exceededGPEN未启动或端口不对执行/bin/bash /root/run.sh并访问http://localhost:7860确认KeyError: data响应是HTML如502网关错误而非JSON检查GPEN日志大概率CUDA显存不足重启服务ValueError: Invalid base64图片路径含中文或空格改用英文路径或用urllib.parse.quote()编码处理后图片全黑/空白输入base64缺少data:image/png;base64,前缀严格按格式拼接不要漏掉逗号fn_index_map not foundWebUI版本更新隐藏字段位置变了临时改用固定fn_index1同时联系科哥更新手册终极建议把脚本和/root/run.sh做成systemd服务开机自启自动拉起从此告别手动操作。7. 总结自动化不是目的省心才是写这篇指南不是为了教你“怎么调API”而是帮你避开那些查不到、问不到、文档里根本没有的隐形陷阱用动态fn_index替代硬编码trigger_id脚本重启不挂抓包还原真实data结构拒绝盲目猜参数内置超时、重试、大图拦截生产环境直接可用批量脚本带并发控制不炸显存也不拖垮CPU参数自动推荐效果预览让技术回归体验。你现在拥有的不再是一段代码而是一个随时待命的“GPEN数字员工”。下次客户甩来50张模糊合影你只需要敲一行命令python batch_enhance.py --input ./client_photos/ --mode 强力 --strength 85然后泡杯茶等它把结果静静放在./output/里。这才是技术该有的样子——不炫技不烧脑只解决问题。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。