Python получает ошибку сегментации: 11 в ос 10.13

Я получаю ошибку Segmentation fault: 11 на моем Mac 10.13.6

Я запускаю virtualenv с Python 3.6.5 Anaconda

Я запускаю скрипт заливки пикселей

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

какие-либо предложения?

Можете ли вы показать, какой код / ​​команду вы выполняете?

Karl 26.10.2018 04:44

да, отредактировано с включенным кодом

Cristian 26.10.2018 04:57
2
2
2 009
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я думаю, проблема в том, что ваш код рекурсивно вызывает сам себя без завершения предыдущей функции, что приводит к увеличению числа копий вашей функции, лежащих в стеке, до тех пор, пока у вас не закончится память (что вызывает ошибку сегментации). Каждый раз, когда Python вызывает новую функцию и помещает ее в стек, создается кадр стека, который использует некоторую память, даже если вы не создаете никаких новых объектов в этом вызове функции. Когда функция возвращается, сборщик мусора в python освобождает память, но если в вашем изображении много значений со значением 0, тогда вы можете получить сразу несколько копий floodfill. Это немного старый и очень подробный и технический, но если вы хотите узнать больше, это хорошее обсуждение.

Чтобы увидеть альтернативный подход к решению проблемы с использованием списков активных узлов, посмотрите здесь:

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)

enter image description here

Есть ли способ разрешить рекурсию в моем скрипте?

Cristian 27.10.2018 23:37

@Cristian Вы можете выделить больше памяти, если она доступна на вашем компьютере. Проблема в том, что ваш скрипт отлично справляется с рекурсией, просто python обычно не подходит для использования очень глубокой рекурсии, потому что фреймы стека, которые он создает, относительно велики по сравнению с некоторыми другими языками. Даже если у вас больше памяти, вы можете достичь предела встроенной рекурсии в python. См. Здесь, чтобы справиться с этим: stackoverflow.com/a/3323013/9742036

Andrew McDowell 29.10.2018 10:55

Другой вариант - предварительно обработать изображение до меньшего размера. Я не использовал их, но у CV2, похоже, есть несколько способов сделать это: docs.opencv.org/2.4/modules/imgproc/doc/…

Andrew McDowell 29.10.2018 10:55

@AndrewMcDowell, зачем делать снимок экрана с моноширинным текстом, если его можно было просто скопировать, вставить и щелкнуть значок {} в редакторе?

Boris 12.12.2019 11:37

Вот вариант того, как сделать то же самое без рекурсии для всех, кого это интересует. от 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

Другие вопросы по теме