<jupyter_start><jupyter_text>Python solve Maze!!!* Solving maze without machine learning, in-fact no learning :P* A simple image processing approach to solve maze using morphological operationsreference: [Guide to Signals and Patterns in Image Processing](https://link.springer.com/book/10.1007/978-3-319-14172-5)<jupyter_code># download and install all the requirements
# set autoreload 2 to reload .py script changes
%load_ext autoreload
%autoreload 2
!git clone https://github.com/vishnu89chand/python_solve_maze.git
import cv2
import numpy as np
from glob import glob
import matplotlib.pyplot as plt
from ipywidgets import interact
# conver the image to binary
# crop maze from image
# get the thickness of maze path in pixel
def preProcessMaze(oimg):
    img = cv2.cvtColor(oimg, cv2.COLOR_BGR2GRAY)
    # create binary image using otsu adaptive thresholding
    img = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
    # trim the image border
    r,c = np.where(img==255)
    x0,x1, y0, y1 = r[0], r[-1], c[0], c[-1]
    img = img[y0:y1, x0:x1] # crop roi
    # on four sides search no of zero pixel on border
    mazePathSize = max([(img[0] == 0).sum(),(img[:,0] == 0).sum(),
                            (img[1] == 0).sum(), (img[:, 1] == 0).sum()])
    return img, mazePathSize<jupyter_output><empty_output><jupyter_text>Hints:*   A maze consists of walls (255) and paths (0)*   Where the correct path split the maze into two parts.* Dead ends are basically paths (0) surrounded by wall (255) can be detected using closing operationsAlgorithm:1. Select any one contour and choose a ksize (for good result choose kernel size == pathSize).2. Dilate the contour. This will generate a mask with all possible paths3. Perform closing operation on the image. This mask shows all the dead ends4. Now find the final path by removing dead ends from the all possible paths.<jupyter_code>def solveMaze(img, kSize, contourIx):
    contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contourImg = cv2.drawContours(np.zeros_like(img), contours, contourIx, 255, 5)
    kernel = np.ones((kSize, kSize), 'u1')
    # to solve maze subtract dilation with close
    dilation = cv2.morphologyEx(contourImg, cv2.MORPH_DILATE, kernel)
    close = cv2.morphologyEx(dilation, cv2.MORPH_ERODE, kernel) # perform closing
    diff = cv2.bitwise_xor(dilation, close) # bitwise subraction
    return diff, contourImg, dilation, close
def main(imPath, contourIx, enablePathSize, pathSize, figsize):
    fig, axs = plt.subplots(nrows=2, ncols=3, figsize=(figsize, figsize))
    oimg = cv2.imread(imPath)
    dispImgs = []
    img, mazePathSize = preProcessMaze(oimg)
    if enablePathSize:
        mazePathSize = pathSize 
    path, contourImg, dilation , close = solveMaze(img, mazePathSize, contourIx)
    dispImgs.append(["Contour Image", contourImg.copy()])
    dispImgs.append(["Dilated Image", dilation.copy()])
    dispImgs.append(["Close Image", close.copy()])
    dispImgs.append(["Input", oimg])
    dispImgs.append(["Path", path.copy()])
    img[path == 255] = 196
    dispImgs.append(["Solution [size: %s]" % mazePathSize, img.copy()])
    for ax, (title, img) in zip(axs.flat, dispImgs):
        ax.imshow(img, interpolation='bilinear')
        ax.set_title(title)
        ax.axis('off')
    plt.show()
print("Before using track bar please enablePathSize")
a = interact(main, imPath=glob('python_solve_maze/maze*.*'),contourIx=[0,1], enablePathSize=False, pathSize=(1,100), figsize=(10, 26))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11922753988245172, 'fraction_numerical': 0.028827315980968375, 'mean_word_length': 4.374436090225564, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '498983', 'license': 'MIT', 'n_tokens_mistral': 1273, 'n_tokens_neox': 1187, 'n_words': 354, 'path': 'python_solve_maze.ipynb', 'repo_name': 'vishnu89chand/python_solve_maze', 'size': '3573'}