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
相关产品推荐
相关产品推荐

