python script stops in the middle of execution without errors

Viewed 497

i have a simple script showing dfs using python, and it stops without executing completely

the script just inputs an image, turns it into an image with just 2 colors(something like islands and water problem of dfs).

it starts with a blank image(background) and then shows an animation with islands(foreground color) becoming visible one by one.

it works upto some point and then stops completely. i have checked the condition of while loop is not met when it stops.

even the atexit message is not printed.

here's the script

import imageFilters as imf
import imutils
import cv2
import numpy as np
import random
import sys
import atexit

sys.setrecursionlimit(1000000000)

atexit.register(print, "exited ")


background = [255, 255, 255] #white
foreground = [0,0,0] #black

img_path = input("ENTER IMAGE PATH:")

img = cv2.imread(img_path)

 #imf.createLineDrawing: resizes with height = 600 and creates an image with only two colors;
img = imf.createLineDrawing(img, foreground, background)
(height, width, channel) = img.shape

blank_image = np.ndarray([height, width, channel], img.dtype)
blank_image.fill(255)

done = np.ndarray([height, width], img.dtype)
countDone = 0

def searchNeighbour(x, y):

    global done,countDone

    done[y, x] = 1
    countDone += 1
    if list(img[y, x]) == foreground:
        blank_image[y, x] = foreground
    else:
        return

    cv2.imshow("o", blank_image)
    cv2.waitKey(1)

    if x - 1 >= 0 and not(done[y, x - 1]):
        searchNeighbour(x - 1, y)
    if x + 1 <= width - 1 and not(done[y, x + 1]):
        searchNeighbour(x + 1, y)
    if y - 1 >= 0 and not(done[y - 1, x]):
        searchNeighbour(x, y - 1)
    if y + 1 <= height - 1 and not(done[y + 1, x]):
        searchNeighbour(x, y + 1)


while countDone < height*width:
    x = random.randrange(0, width - 1)
    y = random.randrange(0, height - 1)
    if not(done[y, x]):
        searchNeighbour(x, y)

2 Answers

stick this in somewhere:

import pdb; pdb.set_trace()

and then type h when it stops for instructions. you can step through line by line and find out the values each step


also, after it finishes, maybe try typing echo $? to see if it exited with an error. (if you are using something unixy) (0 means it things it is done, and any other number means something broke generally)


Or maybe just put a line at the bottom of the project that says

print("DONE PROGRAM %s" % countDone)

to be 100% that it doesn't just finish the loop

I got the solution. This is a major drawback of python. Python is not a functional language and so it is unable to hold large recursions.

actually the default recursion limit(10000) is not arbitrary, but is set because of small stack size. so even if you increase recursion limit, it will cause a stack overflow.

however i got the soution using multithreading;

i just wrapped it in a function and ran it in a different thread with increased stack limit;

STEPS TO RUN LARGE RECURSION IN PYTHON

  1. Add below lines at starting of code
import sys

sys.setrecursionlimit(10**9)
threading.stack_size(10**8)
  1. Wrap your recursive function in a parent function

  2. add below line at end of code -

threading.Thread(target=<your_parent_function>).start()

where <your_parent_function> is the name of your parent function

my final code-

import imageFilters as imf
import cv2
import numpy as np
from random import randrange
import threading
import sys

sys.setrecursionlimit(10**9)
threading.stack_size(10**8)


background = [255, 255, 255]
foreground = [56, 50, 36]

img_path = input("ENTER IMAGE PATH:")

img = cv2.imread(img_path)
img = imf.createLineDrawing(img, foreground, background)
(height, width, channel) = img.shape

blank_image = np.ndarray([height, width, channel], img.dtype)
blank_image.fill(255)

done = np.ndarray([height, width], img.dtype)
countDone = 0


def searchNeighbour(x, y):

    global done, countDone
    print(countDone)
    countDone += 1
    done[y, x] = 1

    if list(img[y, x]) == foreground:
        blank_image[y, x] = foreground
    else:
        print("returning")
        return 0

    cv2.imshow("O", blank_image)
    cv2.waitKey(1)

    if x - 1 >= 0 and not(done[y, x - 1]):
        searchNeighbour(x - 1, y)
    if x + 1 <= width - 1 and not(done[y, x + 1]):
        searchNeighbour(x + 1, y)
    if y - 1 >= 0 and not(done[y - 1, x]):
        searchNeighbour(x, y - 1)
    if y + 1 <= height - 1 and not(done[y + 1, x]):
        searchNeighbour(x, y + 1)


def showAllForegrounds():
    while countDone < height*width:
        x = randrange(0, width - 1)
        y = randrange(0, height - 1)
        if not(done[y, x]):
            searchNeighbour(x, y)


threading.Thread(target=showAllForegrounds).start()

print("DONE PROGRAM %s" % countDone)
Related