Demonstrating a Python project with a user interface has never been so easy. With the Streamlit Framework, you can create a browser user interface using only Python code. In this article, we will create a user interface for the maze program, described in detail in the previous article .


Streamlit is a web framework designed for data researchers to easily deploy models and visualizations using Python. It is fast and minimalistic, as well as beautiful and comfortable. There are built-in widgets for user input, such as loading images, sliders, text input, and other familiar HTML elements such as check boxes and radio buttons. Whenever a user interacts with a streaming application, the python script restarts from top to bottom, which is important to consider when considering the various states of your application.
You can install Streamlit using pip:

pip install streamlit 

And run streamlit in a Python script:

streamlit run 

Use cases

In the previous article , we created a Python program that will go through a maze, given the image file and the start/end location. We would like to turn this program into a one-page web application where the user can download the maze image (or use the default maze image), configure the start and end location of the maze and see the maze passed.

First, let's create a user interface for the image downloader and the ability to use the default image. We can add text output using functions such as st.write () or st.title (). We store a dynamically loaded file using the st.file_uploader () function. Finally, st.checkbox () will return a boolean depending on whether the user has checked the box.

import streamlit as st import cv2 import matplotlib.pyplot as plt import numpy as np import maze st.title('Maze Solver') uploaded_file=st.file_uploader("Choose an image", ["jpg","jpeg","png"]) #image uploader st.write('Or') use_default_image=st.checkbox('Use default maze') 



Then we can display our default image or the loaded image in a usable OpenCV image format.

if use_default_image: opencv_image=cv2.imread('maze5.jpg') elif uploaded_file is not None: file_bytes=np.asarray(bytearray(, dtype=np.uint8) opencv_image=cv2.imdecode(file_bytes, 1) 

As soon as the image is loaded, we want to show the image marked with the start and end points. We will use the sliders to allow the user to move these points. The st.sidebar () function adds a sidebar to the page, and st.slider () accepts numerically within a certain minimum and maximum. We can determine the minimum and maximum values ​​of the slider dynamically depending on the size of our maze image.

if opencv_image is not None: st.subheader('Use the sliders on the left to position the start and end points') start_x=st.sidebar.slider("Start X", value= 24 if use_default_image else 50, min_value=0, max_value=opencv_image.shape[1], key='sx') start_y=st.sidebar.slider("Start Y", value= 332 if use_default_image else 100, min_value=0, max_value=opencv_image.shape[0], key='sy') finish_x=st.sidebar.slider("Finish X", value= 309 if use_default_image else 100, min_value=0, max_value=opencv_image.shape[1], key='fx') finish_y=st.sidebar.slider("Finish Y", value= 330 if use_default_image else 100, min_value=0, max_value=opencv_image.shape[0], key='fy') marked_image=opencv_image.copy() circle_thickness=(marked_image.shape[0]+marked_image.shape[0])//2//100 #circle thickness based on img size, (start_x, start_y), circle_thickness, (0,255,0),-1), (finish_x, finish_y), circle_thickness, (255,0,0),-1) st.image(marked_image, channels="RGB", width=800) 


Whenever the user adjusts the sliders, the image quickly redraws and the points change.

After the user has defined the start and end positions, we want a button to solve the maze and display the solution. The st.spinner () element is only displayed while its child process is running, and the call to st.image () is used to display the image.

if marked_image is not None: if st.button('Solve Maze'): with st.spinner('Solving your maze'): path=maze.find_shortest_path(opencv_image,(start_x, start_y),(finish_x, finish_y)) pathed_image=opencv_image.copy() path_thickness=(pathed_image.shape[0]+pathed_image.shape[0])//200 maze.drawPath(pathed_image, path, path_thickness) st.image(pathed_image, channels="RGB", width=800) 



Solution Solution


In less than 40 lines of code, we created a simple user interface for a Python image processing application. We did not need to write any traditional interface code.In addition to Streamlit's ability to digest simple Python code, Streamlit intelligently restarts the necessary parts of your script from top to bottom every time a user interacts with a page or when a script changes. This provides direct data flow and rapid development.

You can find the full Github code and the first part explaining the algorithm for solving the maze here . Streamlit documentation, including important concepts and additional widgets, can be found here .


Learn the details of how to get a sought-after profession from scratch or Level Up in skills and salary by completing SkillFactory paid online courses:

Read more