You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于PySimpleGUI实现图片加载及裁剪区域测量功能

PySimpleGUI 图片选区测量与裁剪实现方案
  • 优先用 Graph 元素承载图片,不要用普通的 Image 元素。Graph 原生支持鼠标按下、拖拽、抬起事件监听,还可以直接绘制半透明选区预览框,不需要额外调用底层GUI接口。
  • 坐标记录逻辑
    • 监听MouseDown事件:记录鼠标按下位置为起始坐标点(x1, y1),提前计算好展示图和原图的缩放比例,后续所有展示坐标都要通过比例还原为原图实际像素坐标,避免裁剪错位。
    • 监听MouseMove事件:鼠标按住拖拽时,先删除上一帧的临时选区框,再绘制从起始点到当前鼠标位置的半透明矩形,实时预览选区范围。
    • 监听MouseUp事件:记录鼠标抬起位置为结束坐标点(x2, y2),计算得到选区的标准参数:左上角坐标(min(x1,x2), min(y1,y2))、右下角坐标(max(x1,x2), max(y1,y2))、宽度abs(x2-x1)、高度abs(y2-y1),乘以缩放比例后就是对应原图的实际参数。
  • 裁剪与参数返回逻辑
    • 直接裁剪:把还原后的原图坐标传入PIL的Image.crop()方法即可,该方法的入参格式刚好是(左, 上, 右, 下),和你计算得到的参数完全匹配。
    • 返回参数:可以把计算好的坐标、宽高参数存在变量里,也可以加个确认按钮,用户确认选区后再触发参数输出或者裁剪逻辑,避免误操作。
核心实现示例代码
import PySimpleGUI as sg
from PIL import Image

# 加载原图,此处替换为你自己的图片加载逻辑
original_img = Image.open("test.png")
# 自定义展示缩放比例,根据你的界面尺寸调整
scale = 0.5 
display_width = int(original_img.width * scale)
display_height = int(original_img.height * scale)
display_img = original_img.resize((display_width, display_height))

layout = [
    [sg.Graph(canvas_size=(display_width, display_height), 
              graph_bottom_left=(0, display_height), 
              graph_top_right=(display_width, 0),
              key='-GRAPH-',
              enable_events=True,
              drag_submits=True)],
    [sg.Button('确认裁剪', key='-CROP-'), sg.Text('选区参数:', key='-PARAM-')]
]

window = sg.Window('图片选区工具', layout, finalize=True)
# 将展示图绘制到Graph组件上
window['-GRAPH-'].draw_image(data=display_img.tobytes(), location=(0,0))

start_pt = None
current_rect = None
crop_params = None

while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED:
        break
    # 处理鼠标点击/拖拽事件
    if event == '-GRAPH-':
        x, y = values['-GRAPH-']
        if not start_pt:
            # 首次点击记录起始点
            start_pt = (x, y)
        else:
            # 拖拽中更新选区预览框
            if current_rect:
                window['-GRAPH-'].delete_figure(current_rect)
            current_rect = window['-GRAPH-'].draw_rectangle(start_pt, (x,y), line_color='red', fill_color='yellow', opacity=0.3)
    # 处理鼠标抬起事件
    elif event.endswith('+UP'):
        end_pt = values['-GRAPH-']
        x1, y1 = start_pt
        x2, y2 = end_pt
        # 转换为原图实际像素坐标
        orig_x1 = int(min(x1, x2) / scale)
        orig_y1 = int(min(y1, y2) / scale)
        orig_x2 = int(max(x1, x2) / scale)
        orig_y2 = int(max(y1, y2) / scale)
        crop_params = (orig_x1, orig_y1, orig_x2, orig_y2)
        # 展示选区参数
        window['-PARAM-'].update(f'选区参数:左={orig_x1}, 上={orig_y1}, 右={orig_x2}, 下={orig_y2}, 宽={orig_x2-orig_x1}, 高={orig_y2-orig_y1}')
        start_pt = None
        current_rect = None
    # 处理裁剪请求
    elif event == '-CROP-' and crop_params:
        cropped_img = original_img.crop(crop_params)
        # 此处可添加裁剪后图片的保存、展示逻辑
        cropped_img.save('cropped_result.png')

window.close()

提示:如果你的界面加了滚动条适配大尺寸图片,坐标计算时需要额外加上滚动条的偏移量,否则选区坐标会出现偏移。

内容的提问来源于stack exchange,提问作者katherinekelly2012

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 07:42:01