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 is restarted 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 app.py
In a previous article, we created a program in Python that will go through a maze, given the image file and the start / end locations. 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(uploaded_file.read()), 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, 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, 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, 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, key='fy') marked_image = opencv_image.copy() circle_thickness=(marked_image.shape+marked_image.shape)//2//100 #circle thickness based on img size cv2.circle(marked_image, (start_x, start_y), circle_thickness, (0,255,0),-1) cv2.circle(marked_image, (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 is quickly redrawn 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+pathed_image.shape)//200 maze.drawPath(pathed_image, path, path_thickness) st.image(pathed_image, channels="RGB", width=800)
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. Besides Streamlit’s ability to digest simple Python code, Streamlit intelligently restarts the necessary parts of your script from top to bottom each time a user interacts with a page or when a script changes. This provides direct data flow and rapid development.
Learn the details of how to get a sought-after profession from scratch or Level Up in skills and salary by taking paid SkillFactory online courses:
- Machine Learning Course (12 weeks)
- Learning Data Science from scratch (12 months)
- Analyst profession with any starting level (9 months)
- Python for Web Development Course (9 months)
- Trends in Data Scenсe 2020
- Data Science is dead. Long live Business Science
- The coolest Data Scientist does not waste time on statistics
- How to Become a Data Scientist Without Online Courses
- Sorting cheat sheet for Data Science
- Data Science for the Humanities: What is Data
- Steroid Data Scenario: Introducing Decision Intelligence