
完整代码保存为 image_warp.py 并运行pythonimport gradio as grimport cv2import numpy as npfrom PIL import Image, ImageDraw, ImageFont# 核心处理函数def warp_image(image,tl_x, tl_y, # 左上角偏移tr_x, tr_y, # 右上角偏移br_x, br_y, # 右下角偏移bl_x, bl_y, # 左下角偏移text, # 要添加的文字text_x, text_y, # 文字位置font_size,font_color,bg_color):h, w image.shape[:2]# 原始四个角点pts_src np.float32([[0, 0], [w, 0], [w, h], [0, h]])# 目标四个角点用户通过滑块控制偏移pts_dst np.float32([[0 tl_x, 0 tl_y],[w tr_x, 0 tr_y],[w br_x, h br_y],[0 bl_x, h bl_y]])# 计算透视变换矩阵M cv2.getPerspectiveTransform(pts_src, pts_dst)# 计算变换后完整图像的边界框避免裁剪all_pts pts_dst.copy()min_x min(all_pts[:, 0])max_x max(all_pts[:, 0])min_y min(all_pts[:, 1])max_y max(all_pts[:, 1])# 保证最小尺寸防止矩阵报错out_w int(max_x - min_x) 20out_h int(max_y - min_y) 20if out_w 10 or out_h 10:out_w, out_h w, h# 平移矩阵让整个变形后的画面显示在画布中央T np.array([[1, 0, -min_x 10], [0, 1, -min_y 10], [0, 0, 1]], dtypenp.float32)M T M# 执行透视变形warped cv2.warpPerspective(image, M, (out_w, out_h))# ----- 添加文字PIL支持中文若系统无中文字体则回退默认-----pil_img Image.fromarray(cv2.cvtColor(warped, cv2.COLOR_BGR2RGB))draw ImageDraw.Draw(pil_img)try:# 尝试加载系统字体Windows用simheiMac用PingFangLinux用arialfont ImageFont.truetype(simhei.ttf, int(font_size))except:try:font ImageFont.truetype(PingFang.ttc, int(font_size))except:font ImageFont.load_default()# 解析颜色 (#RRGGBB格式)def hex_to_rgb(hex_str):hex_str hex_str.lstrip(#)return tuple(int(hex_str[i:i2], 16) for i in (0, 2, 4))f_color hex_to_rgb(font_color)b_color hex_to_rgb(bg_color) if bg_color else None# 若设置了背景色先绘制文字背景框if b_color:bbox draw.textbbox((text_x, text_y), text, fontfont)draw.rectangle(bbox, fillb_color)# 绘制文字draw.text((text_x, text_y), text, fontfont, fillf_color)# 转回OpenCV格式返回result cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)return result# ----- 构建 Gradio 界面 -----with gr.Blocks(title图片任意角度拉伸压缩添加文字, themegr.themes.Soft()) as demo:gr.Markdown(## 上传图片拖拽滑块控制四个角实现任意角度拉伸/压缩并添加文字)with gr.Row():with gr.Column(scale1):input_img gr.Image(label 上传图片, typenumpy, height300)gr.Markdown(### 顶点偏移控制正负值均可)with gr.Row():tl_x gr.Slider(-300, 300, value0, label左上 X)tl_y gr.Slider(-300, 300, value0, label左上 Y)with gr.Row():tr_x gr.Slider(-300, 300, value0, label右上 X)tr_y gr.Slider(-300, 300, value0, label右上 Y)with gr.Row():br_x gr.Slider(-300, 300, value0, label右下 X)br_y gr.Slider(-300, 300, value0, label右下 Y)with gr.Row():bl_x gr.Slider(-300, 300, value0, label左下 X)bl_y gr.Slider(-300, 300, value0, label左下 Y)gr.Markdown(### 文字设置)text_input gr.Textbox(value你好世界, label文字内容)with gr.Row():text_x gr.Slider(0, 800, value50, label文字 X 位置)text_y gr.Slider(0, 600, value50, label文字 Y 位置)with gr.Row():font_size gr.Slider(10, 100, value40, label字号)font_color gr.Textbox(value#FF0000, label字体颜色 (如 #FF0000))bg_color gr.Textbox(value#000000, label背景颜色 (留空则透明))btn gr.Button( 执行变形并添加文字, variantprimary)with gr.Column(scale1):output_img gr.Image(label 处理结果, typenumpy, height500)# 绑定按钮事件btn.click(fnwarp_image,inputs[input_img, tl_x, tl_y, tr_x, tr_y, br_x, br_y, bl_x, bl_y,text_input, text_x, text_y, font_size, font_color, bg_color],outputsoutput_img)# 示例提示gr.Markdown(### 使用技巧- 拖动四个角的 **X/Y 偏移滑块**画面会像纸张一样被拉伸或压缩实现透视变形。- 支持 **负值**向内收缩和 **正值**向外扩张。- 文字颜色和背景色请使用 **#RRGGBB** 格式例如 #FF0000 为红色。)if __name__ __main__:demo.launch()---运行方法1. 安装依赖打开终端或命令提示符bashpip install gradio opencv-python pillow numpy2. 运行程序bashpython image_warp.py3. 使用· 终端会显示本地访问地址通常是 http://127.0.0.1:7860用浏览器打开。· 上传图片 → 拖动8个滑块控制4个顶点 → 填写文字 → 点击按钮即可实时看到变形文字效果。功能说明· 任意角度拉伸/压缩通过独立控制四个顶点的偏移量可实现透视、扭曲、缩放等所有变形效果。· 添加文字支持中英文可调字号、颜色并可设置文字背景色或透明。· 画面自适应变形后画面自动扩展画布不会裁剪超出部分。如果调整滑块的取值范围当前为 -300 ~ 300修改代码中 Slider 的 minimum 和 maximum 参数即可如改为 -500 ~ 500。