【问题标题】:python getting Segmentation fault: 11 on OS 10.13python得到分段错误:OS 10.13上的11
【发布时间】:2019-03-30 17:42:28
【问题描述】:

我的 mac 10.13.6 上出现 Segmentation fault: 11 错误

我正在使用 Python 3.6.5 Anaconda 运行 virtualenv

我正在运行像素洪水填充脚本

img = cv2.imread(image,1)
surface = cv2.Canny(img,100,200)

def floodfill(x, y, oldColor, newColor):

    # assume surface is a 2D image and surface[x][y] is the color at x, y.

    if surface[x][y] != oldColor: # the base case

        return

    surface[x][y] = newColor

    floodfill(x + 1, y, oldColor, newColor) # right

    floodfill(x - 1, y, oldColor, newColor) # left

    floodfill(x, y + 1, oldColor, newColor) # down

    floodfill(x, y - 1, oldColor, newColor) # up

floodfill(0, 0, 0, 100)
plt.imshow(edges, cmap='gray')
plt.show()

有什么建议吗?

【问题讨论】:

  • 你能显示你正在运行的代码/命令是什么吗?
  • 是的,使用包含的代码编辑

标签: python-3.x macos segmentation-fault virtualenv


【解决方案1】:

我认为问题在于您的代码在没有前一个函数结束的情况下递归地调用自身,导致您的函数的副本数量不断增加,直到您耗尽内存(这会触发分段错误)。每次 Python 调用一个新函数并将其放入堆栈时,都会创建一个堆栈帧,它会占用一些内存,即使您没有在该函数调用中创建任何新对象。当函数返回时,python 中的垃圾收集器会释放内存,但如果图像中有很多值为0 的值,那么您最终可能会同时运行大量floodfill 的副本.这有点老了,非常深入和技术性,但如果你想了解更多,this is a good discussion

要查看使用活动节点列表解决问题的替代方法,请查看此处:

https://rosettacode.org/wiki/Bitmap/Flood_fill#Python

顺便说一句,您还有另一个问题可能是故意的,因为您的代码将图像视为一个球体,也就是说,当它碰到边框时,它会跳到图像的另一侧并在那里填充.这是因为 python 支持负索引,所以当x=0 跳转到x-1 时,您正在查看索引-1,它是数组中的最后一个索引。为了解决这个问题,您可以添加一些检查:

if x > 0:  # left
    floodfill(x - 1, y, oldColor, newColor)  # left

if y > 0:  # up
    floodfill(x, y - 1, oldColor, newColor)  # up

if x < surface.shape[0] - 1:  # right
    floodfill(x + 1, y, oldColor, newColor)  # right

if y < surface.shape[1] - 1:  # down
    floodfill(x, y + 1, oldColor, newColor)  # down

您的代码通常可以正常工作。如果您用一个小玩具示例进行尝试,您可以看到它的实际效果(这是上面的修复):

surface_array = [[0 for i in range (0,10)] for j in range(0,10)]
surface_array[1][1] = 1
surface_array[0][1] = 1
surface_array[2][0] = 1
surface = np.array(surface_array)
print(surface)
floodfill(0, 0, 0, 100)
print(surface)

【讨论】:

  • 有什么方法可以让我的脚本递归吗?
  • @Cristian 如果您的机器有可用内存,您可以分配更多内存。问题是你的脚本很好地递归,只是python通常不适合使用非常深的递归,因为它创建的堆栈帧与其他一些语言相比相对较大。即使您有更多内存,您也可能会达到 python 中的内置递归限制。请参阅此处以处理该问题:stackoverflow.com/a/3323013/9742036
  • 另一种选择是将图像预处理为较小的尺寸。我没有使用它们,但 CV2 似乎有几种方法:docs.opencv.org/2.4/modules/imgproc/doc/…
  • @AndrewMcDowell 为什么要截取等宽文本,而您可以复制粘贴并单击编辑器中的{} 图标?
【解决方案2】:

对于任何感兴趣的人,这里有一个关于如何在不递归的情况下做同样事情的选项。来自http://inventwithpython.com/blog/2011/08/11/recursion-explained-with-the-flood-fill-algorithm-and-zombies-and-cats/

def floodfill(x, y, oldColor, newColor):

    # assume surface is a 2D image and surface[x][y] is the color at x, y.

    theStack = [ (x, y) ]
    while (len(theStack) > 0):

        x, y = theStack.pop()

        if (x == 224):
            continue
        if (x == -1):
            continue
        if (y == -1):
            continue
        if (y == 224):
            continue


        if edges[x][y] != oldColor:
            continue

        edges[x][y] = newColor


        theStack.append( (x + 1, y) )  # right
        theStack.append( (x - 1, y) )  # left
        theStack.append( (x, y + 1) )  # down
        theStack.append( (x, y - 1) )  # up

【讨论】:

    猜你喜欢
    • 2017-07-30
    • 1970-01-01
    • 2013-09-17
    • 1970-01-01
    • 2021-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多