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

Python多进程优化带while循环与共享资源的OpenCV图像拼接任务

你遇到的问题的核心原因
  • 多进程全局变量不共享:Windows系统下Python的multiprocessing默认用spawn启动模式,子进程启动时会重新导入你的代码文件,不会执行if __name__ == '__main__'包裹的逻辑,因此子进程内的frames_1、frames_2都是空列表,while循环判断条件不成立直接跳过。
  • 共享变量操作不安全:即使你用了支持跨进程共享的存储结构,直接多进程同时执行pop(0)、append操作也会有数据竞争问题,出现重复处理、丢失数据、结果错乱的情况。
  • 多线程不适配你的场景:图像拼接是CPU密集型任务,Python全局解释器锁(GIL)会导致多线程只能使用单个CPU核心,完全达不到4倍加速的效果,必须用多进程方案。
最优适配方案

直接使用multiprocessing.Pool进程池实现,不需要手动管理进程生命周期,也不需要维护全局共享变量,把待处理的图像对作为参数传入工作函数,处理完成后主进程统一收集结果即可,实现简单且稳定性高。

修改后的可运行代码
import multiprocessing
import time
import cv2

# 单组图像拼接工作函数,不要用全局变量,参数和返回值都单独处理
def stitch_single_pair(img_pair):
    img1, img2 = img_pair
    stitcher = cv2.Stitcher_create(cv2.STITCHER_PANORAMA)
    status, result = stitcher.stitch((img1, img2))
    if status == 0:
        return result
    else:
        print("image stitching failed")
        return None

# converting the video into frames for individual image processing
def convert_video_to_frames():
    frames_1 = []
    frames_2 = []
    cap = cv2.VideoCapture("Sample_video_1.mp4")
    ret = True
    while ret:
        ret, img = cap.read()
        if ret:
            frames_1.append(img)
    cap.release()

    cap = cv2.VideoCapture("Sample_video_2.mp4")
    ret = True
    while ret:
        ret, img = cap.read()
        if ret:
            frames_2.append(img)
    cap.release()

    # 保证两个视频帧数量一致,取最短的长度
    min_len = min(len(frames_1), len(frames_2))
    # 打包成待处理的图像对列表
    return list(zip(frames_1[:min_len], frames_2[:min_len]))

# converting final output images back to video
def convert_frames_to_video(panorama):
    print("now creating stitched image video")
    height, width, layers = panorama[0].shape
    size = (width, height)
    out = cv2.VideoWriter('project.avi', cv2.VideoWriter_fourcc(*'DIVX'), 15, size)
    for img in panorama:
        out.write(img)
    out.release()

if __name__ == '__main__':
    # 先读取所有视频帧,打包成待处理任务列表
    task_list = convert_video_to_frames()
    print(f"总共有{len(task_list)}组待拼接图像")

    start = time.perf_counter()
    # 开启4进程的进程池处理任务
    with multiprocessing.Pool(processes=4) as pool:
        results = pool.map(stitch_single_pair, task_list)
    # 过滤掉拼接失败的None值
    panorama = [res for res in results if res is not None]
    finish = time.perf_counter()
    print(f'finished in {round(finish - start, 2)} seconds(s)')

    print("now converting images to video...")
    convert_frames_to_video(panorama)
额外优化提示
  • 进程数设置不要超过你的CPU物理核心数,否则进程切换开销会抵消多进程加速效果。
  • 如果视频帧数量很大,一次性读取所有帧占内存过高,可以用multiprocessing.Queue做流式任务分发,读一批处理一批,降低内存占用。
  • 可以提前检查两个视频的帧数量是否匹配,避免出现无法配对的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 21:00:00