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

Python实现DFS图像动画脚本无报错中途停止执行问题

问题根因分析

  • done数组未初始化
    你用np.ndarray([height, width], img.dtype)创建的数组是未初始化状态,内存中的残留值会导致大量像素被误判为已访问,countDone永远累积不到height*width,看起来就像循环提前停止。
  • 递归深度溢出触发系统强制杀进程
    即使你修改了Python的递归上限,操作系统对进程栈空间的限制是固定的(通常只有几MB),如果你的图像里存在大面积连通的前景区域,DFS递归深度会达到几万甚至几十万,直接超过系统栈上限,进程被系统强制终止,所以不会触发atexit的回调,也不会抛出Python层面的错误。
  • 随机坐标取值范围错误
    你写的random.randrange(0, width - 1)和random.randrange(0, height - 1)会永远取不到最右侧列和最下侧行的像素,这部分像素永远不会被访问,循环永远不会满足退出条件。

修复方案

1. 修复数组初始化问题

把done数组的初始化代码替换为:

done = np.zeros([height, width], dtype=np.uint8)

直接初始化为全0,确保所有像素初始状态都是未访问。

2. 把递归DFS改为迭代DFS,规避栈溢出问题

递归的深度受系统栈限制,换成手动用栈结构实现的迭代版DFS即可解决该问题,修改searchNeighbour函数如下:

def searchNeighbour(start_x, start_y):
    global done, countDone
    # 用列表作为栈存储待访问的坐标
    stack = [(start_x, start_y)]
    while stack:
        x, y = stack.pop()
        # 跳过已访问的坐标
        if done[y, x]:
            continue
        # 标记为已访问
        done[y, x] = 1
        countDone += 1
        # 非前景像素不处理邻居
        if list(img[y, x]) != foreground:
            continue
        # 渲染当前像素
        blank_image[y, x] = foreground
        cv2.imshow("o", blank_image)
        cv2.waitKey(1)
        # 把未访问的邻居压入栈,调整压栈顺序可以和原递归的遍历顺序保持一致
        if y + 1 <= height - 1 and not done[y + 1, x]:
            stack.append((x, y + 1))
        if y - 1 >= 0 and not done[y - 1, x]:
            stack.append((x, y - 1))
        if x + 1 <= width - 1 and not done[y, x + 1]:
            stack.append((x + 1, y))
        if x - 1 >= 0 and not done[y, x - 1]:
            stack.append((x - 1, y))

3. 修复随机坐标的取值范围

把while循环里的随机坐标生成代码替换为:

x = random.randrange(0, width)
y = random.randrange(0, height)

randrange的上界为开区间,直接传入width和height即可覆盖所有像素坐标。

可选优化

所有处理完成后可以添加cv2.waitKey(0),避免处理完程序直接闪退,看不到最终渲染结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 22:36:02