Cristian
Cristian

Reputation: 495

python getting Segmentation fault: 11 on OS 10.13

Im getting Segmentation fault: 11 error on my mac 10.13.6

I'm running a virtualenv with Python 3.6.5 Anaconda

I'm running a pixel flood filling script

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()

any suggestions?

Upvotes: 2

Views: 2288

Answers (2)

Cristian
Cristian

Reputation: 495

Here is an option on how to do the same thing without recursion for anyone interested. from 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

Upvotes: 2

Andrew McDowell
Andrew McDowell

Reputation: 2980

I think the problem is that your code is recursively calling itself without the previous function ending, resulting in increasing numbers of copies of your function resting on the stack until you run out of memory (which triggers the segmentation fault). Each time Python calls a new function and places it on the stack, a stack frame is created which uses up some memory, even if you aren't creating any new objects within that function call. When the function returns, the garbage collector within python frees up the memory, but if there are a lot of values in your image with value 0, then then you can end up with a lot of copies of floodfill running at once. This is a little old and very in-depth and technical but if you want to know more, this is a good discussion.

To see an alternative approach to tackling the problem using lists of active nodes, have a look here:

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

As an aside, you have another issue that may be deliberate, in that your code treats the image as a sphere, in the sense that when it hits a border it will jump to the other side of the image and fill there too. This is because python supports negative indices, so when x=0 and you jump to x-1, you are looking at index -1 which is the last index in the array. To address this you could add some checks:

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

Your code works fine in general though. If you try it with a small toy example, you can see it in action (this is with the fix above):

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)

enter image description here

Upvotes: 2

Related Questions