如何用Python无重叠拼接Windows应用滚动后的两张截图?
解决Windows应用面板滚动截图无重叠拼接问题
你的核心问题是硬编码了拼接偏移量(273),但PageDown的实际滚动幅度和控件可视高度、系统设置相关,手动数值无法适配所有场景。下面提供两种自动计算偏移量的方案:
方案一:通过UI自动化获取精确滚动偏移
如果使用的是pywinauto这类库,可以直接获取控件的滚动位置变化,计算实际滚动距离:
修改autosetup_summary_scroll函数,记录滚动前后的垂直滚动位置:
import time def autosetup_summary_scroll(): windows = Windows() window_title = f"AutoSetup - PathGroup - {location} - {environment} {version} - {admin} - {search_type}" autosetup = window.find_window(f'name: "{window_title}"') app = autosetup.find_child_window('id: "1129"') app.click() # 获取控件的滚动模式(需根据控件实际支持的模式调整) scroll_pattern = app.ui_automation_control.GetScrollPattern() # 记录滚动前的垂直位置百分比 prev_vertical_pos = scroll_pattern.CurrentVerticalScrollPercent app.screenshot(filename="screenshot_before_scroll.png") desktop.press_keys('page_down') # 等待滚动完成,避免截图过早 time.sleep(0.5) # 记录滚动后的垂直位置百分比 curr_vertical_pos = scroll_pattern.CurrentVerticalScrollPercent app.screenshot(filename="screenshot_after_scroll.png") # 获取控件可视区域高度 client_rect = app.client_rect() visible_height = client_rect.height # 计算实际滚动的像素距离 scroll_pixels = visible_height * (curr_vertical_pos - prev_vertical_pos) / 100 stitch_screenshots_vertically('screenshot_before_scroll.png', 'screenshot_after_scroll.png', 'stitched_screenshot.png', int(scroll_pixels))
然后修改拼接函数,传入自动计算的偏移量:
from PIL import Image def stitch_screenshots_vertically(screenshot_before, screenshot_after, output_path, scroll_offset): image1 = Image.open(screenshot_before) image2 = Image.open(screenshot_after) # 总高度 = 第一张图高度 + 第二张图高度 - 重叠部分(滚动偏移量) total_height = image1.height + image2.height - scroll_offset max_width = max(image1.width, image2.width) new_image = Image.new('RGB', (max_width, total_height)) new_image.paste(image1, (0, 0)) # 第二张图起始位置 = 第一张图高度 - 重叠高度 new_image.paste(image2, (0, image1.height - scroll_offset)) new_image.save(fp=output_path)
方案二:图像对比自动计算重叠区域
如果无法通过UI自动化获取滚动信息,可以对比两张截图的像素,找到最大重叠区域:
from PIL import Image, ImageChops def calculate_overlap(image1, image2): max_overlap = 0 # 最多检查两张图中较小高度的一半,避免无效对比 max_check_height = min(image1.height, image2.height) // 2 # 从大到小遍历可能的重叠高度,找到第一个完全匹配的区域 for overlap in range(max_check_height, 0, -1): crop1 = image1.crop((0, image1.height - overlap, image1.width, image1.height)) crop2 = image2.crop((0, 0, image2.width, overlap)) # 对比两个裁剪区域的差异,无差异则说明完全重叠 diff = ImageChops.difference(crop1, crop2) if diff.getbbox() is None: max_overlap = overlap break return max_overlap def stitch_screenshots_vertically(screenshot_before, screenshot_after, output_path): image1 = Image.open(screenshot_before) image2 = Image.open(screenshot_after) overlap_height = calculate_overlap(image1, image2) total_height = image1.height + image2.height - overlap_height max_width = max(image1.width, image2.width) new_image = Image.new('RGB', (max_width, total_height)) new_image.paste(image1, (0, 0)) new_image.paste(image2, (0, image1.height - overlap_height)) new_image.save(fp=output_path)
额外注意事项
- 滚动后添加短暂延迟,确保控件内容完全滚动到位再截图,避免截图内容未更新。
- 如果控件有固定头部(如标题栏),可以先裁剪掉固定区域再计算重叠,避免头部干扰对比结果。
内容的提问来源于stack exchange,提问作者James Allgood
相关产品推荐
相关产品推荐

