环境
- windows 10 64位
- anaconda with python 3.8
- streamlit 0.86.0
- yolov5 v5.0
streamlit是什么
streamlit
是一个开源的 python
库,它能够快速的帮助我们创建定制化的 web
应用,而且还非常便于和他人分享,特别是在机器学习和数据科学领域。整个过程不需要你了解任何前端的知识,包括 html
、css
、javascript
等,对非前端开发人员非常的友好。
streamlit安装
streamlit
要求 python
版本大于等于3.6,可以直接使用 pip
进行安装
pip install streamlit
安装成功后,使用其内置的 hello app
测试,执行命令
streamlit hello
服务启动后,它会自动帮我们打开页面,地址是 http://localhost:8501
可以看到,streamlit
默认使用端口8501
除此之外,streamlit
官方还提供了一个稍复杂的应用,它结合了 yolov3
的目标检测算法,仓库地址:https://github.com/streamlit/demo-self-driving,感兴趣的可以去研究研究,代码简短,但功能完整
那么,针对我们自己的写的源码文件,该怎么运行呢?其实也非常简单,比如源码文件是 app.py
,那么可以执行
streamlit run app.py
这里再说2个常用的命令
streamlit docs
查看文档streamlit cache clear
清缓存
streamlit常用组件
按钮
import streamlit as st
button = st.button('按钮')
文本输入框
import streamlit as st
st.text_input('请输入最喜欢的编程语言', key="name")
文本显示
import streamlit as st
st.write('Hello streamlit.')
streamlit
完美支持 markdown
语法,可以直接使用 write
方法,来看示例
import streamlit as st
st.write("""
# 一级标题
## 二级标题
### 三级标题
**强调**
>这是引用
. python
. java
. c/c++
. rust
""")
除了 write
方法,streamlit
还提供了 text
方法,同样可以显示文本信息
import streamlit as st
st.text('Hello streamlit.')
标题
import streamlit as st
st.title('title')
除了 title
,streamlit
还提供了 header
和 subheader
import streamlit as st
st.header('header')
st.subheader('subheader')
滑动条
import streamlit as st
number = st.slider('Pick a number', 0, 100)
选择框
import streamlit as st
flag = st.checkbox('Yes')
单选按钮
import streamlit as st
languages = ['python', 'c', 'rust', 'c++']
st.radio('Pick a language', languages)
下拉选择框
import streamlit as st
st.selectbox('用过哪几种编程语言?', ('python', 'c', 'java', 'rust'))
日期选择器
import streamlit as st
date = st.date_input('Pick a date')
颜色选择器
import streamlit as st
color = st.color_picker('Pick a color')
文件选择器
import streamlit as st
file = st.file_uploader('Pick a file')
创建web表单
import streamlit as st
with st.form("my_form", clear_on_submit=False):
name = st.text_input("请输入用户名")
passwd = st.text_input("请输入密码", type="password")
passwd_re = st.text_input("请再次输入密码", type="password")
submitted = st.form_submit_button("Submit")
if submitted:
st.write("欢迎用户 {}".format(name))
streamlit的其它功能
显示json
import streamlit as st
st.json({
"code": 0,
"data": {
"sex": "female",
"age": 18,
"score": 100
}
})
显示代码
from numpy.core.arrayprint import _leading_trailing
import streamlit as st
code = """
def func():
print('Hello streamlit.')
"""
st.code(code, language='python')
显示pandas中的dataframe
from numpy.core.arrayprint import _leading_trailing
import streamlit as st
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(50, 5), columns=(
'col %d' % i for i in range(5)))
st.dataframe(df)
最后一句中的 st.dataframe(df)
可以用 st.write(df)
来代替,效果一样
显示表格
import streamlit as st
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(50, 5), columns=(
'col %d' % i for i in range(5)))
st.table(df)
与上边的 dataframe
不同的是,表格会将所有数据都显示出来,而没有了滚动条
指标性数据显示
这里还需要安装另一个库 streamlit-metrics
,执行安装命令 pip install streamlit-metrics
即可
import streamlit as st
from streamlit_metrics import metric_row
st.write("一周数据统计")
metric_row(
{
"关注人数": 100,
"点赞人数": 200,
"在看人数": 300,
"分享人数": 400
}
)
streamlit的会话状态和回调
会话状态session state
在浏览器中打开新的页面,就创建了一个会话(session
)。会话状态是页面 rerun
(并非类似 F5
的页面刷新)时数据交互的一种方式。
看个计数的示例
import streamlit as st
st.title('Hello streamlit.')
counter = 0
increment = st.button('Increment')
if increment:
counter += 1
st.write('Count= ', counter)
可以看到只有第一次点击按钮时,Count
增加了1,后面的点击,counter
都不会改变,这显然跟我们的预期是不一样的。
我们修改下上面的代码
from typing import Counter
import streamlit as st
st.title('Hello streamlit.')
if 'counter' not in st.session_state:
st.session_state.counter = 0
increment = st.button('Increment')
if increment:
st.session_state.counter += 1
st.write('Count= ', st.session_state.counter)
这样功能就正常了,每点击一次按钮,Count
就加1
回调callbacks
回调(callbacks
)是一个 python
函数,它在输入组件更改时被调用,比如按钮被点击、滑动条被拉拽等。
针对上边的示例,使用 callbacks
修改一下
from typing import Counter
import streamlit as st
# callbacks
def increment_counter():
st.session_state.counter += 1
st.title('Callbacks')
if 'counter' not in st.session_state:
st.session_state.counter = 0
st.button('Increment', on_click=increment_counter)
st.write('Count= ', st.session_state.counter)
代码执行的效果是一样的。这是无需传参的示例,如果需要数据交互,可以使用 args
或 kwargs
,看下面的示例
import streamlit as st
st.title('Callbacks with args')
if 'counter' not in st.session_state:
st.session_state.counter = 0
increment_value = st.number_input('Enter a value', value=0, step=1)
def increment_counter(increment_value):
st.session_state.counter += increment_value
increment = st.button('Increment', on_click=increment_counter,
args=(increment_value, ))
st.write('Count = ', st.session_state.counter)
下面看看 kwargs
的用法,它接收的是命名参数
import streamlit as st
st.title('Callbacks with kwargs')
if 'counter' not in st.session_state:
st.session_state.counter = 0
def increment_counter(increment_value=0):
st.session_state.counter += increment_value
def decrement_counter(decrement_value=0):
st.session_state.counter -= decrement_value
st.button('Increment', on_click=increment_counter,
kwargs=dict(increment_value=5))
st.button('Decrement', on_click=decrement_counter,
kwargs=dict(decrement_value=1))
st.write('Count = ', st.session_state.counter)
点击 Increment
按钮,Count
就加5,点击 Decrement
按钮,Count
就减1
会话状态的注意事项
关于会话状态,有两点需要注意,分别是
-
只要页面打开并连接到
streamlit
服务器,会话状态就会一直存在。一旦关闭选项卡,会话状态中存储的所有内容都会丢失 -
会话状态不会持久化。如果
streamlit
服务器崩溃,那么存储在会话状态中的所有内容都会被删除
streamlit部署
streamlit
最重要的一个优势就是分享了
进入站点 https://streamlit.io/sharing ,请求邀请
填写基本信息后,就是等待回复了
streamlit
处理的很快,我是第二天就收到了确认的邮件
电子邮件中,详细给出了部署的步骤,基本上照着操作就可以了
-
将工程保存到
github
中,默认是main
分支,工程下需要有requirements.txt
文件 -
访问 https://share.streamlit.io/, 使用
github
的账号登录 -
创建应用
- 填写项目信息,分支和入口文件不要填错
- 开始部署,后台就开始安装各种依赖
- 项目运行
我这里报了个错
Traceback (most recent call last):
File "/home/appuser/venv/lib/python3.7/site-packages/streamlit/script_runner.py", line 350, in _run_script
exec(code, module.__dict__)
File "/app/yolov5-streamlit/main.py", line 5, in <module>
from detect import detect
File "/app/yolov5-streamlit/detect.py", line 5, in <module>
import cv2
File "/home/appuser/venv/lib/python3.7/site-packages/cv2/__init__.py", line 5, in <module>
from .cv2 import *
ImportError: libGL.so.1: cannot open shared object file: No such file or directory
这里需要将 requirements.txt
文件中的 opencv-python
更改为 opencv-python-headless
点击右上方的 rerun
后,重新安装依赖,就可以运行成功了
最后,来测试下功能是否正常。选择一张本地图片上传,然后点击检测
没有问题,那至此,整个 App
的部署就完成了,可以分享给你的朋友们了
如果想线上体验下,可以访问
https://share.streamlit.io/xugaoxiang/yolov5-streamlit/main/main.py
更换背景图片
import streamlit as st
import base64
def set_bg(main_bg):
st.markdown(
f"""
<style>
.stApp {{
background: url(data:image/png;base64,{base64.b64encode(open(main_bg, "rb").read()).decode()});
background-size: contain
}}
</style>
""",
unsafe_allow_html=True
)
set_bg('bg.png')
更换端口
在启动服务时,使用参数 --server.port
streamlit run main.py --server.port 80
源码下载
github
地址:https://github.com/xugaoxiang/yolov5-streamlit
入口文件是 main.py
,里面跟 streamlit
相关的界面代码,其实非常少,这样看,streamlit
真的是非常适合不懂前端的朋友。yolov5
的代码部分,基本上把原始的项目拷贝过来,只修改了2个地方
detect.py
中的detect
方法,增加了一个参数opt
- 修改视频检测后存储的格式,由原来的
mp4v
改成了avc1
。原因是streamlit
中的video
适合播放h264
编码的mp4
,详细的操作可以参考 https://xugaoxiang.com/2021/08/20/opencv-h264-videowrite/