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)
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;
import sys
sys.setrecursionlimit(10**9)
threading.stack_size(10**8)
Wrap your recursive function in a parent function
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)