使用stremalit以及fastapi来处理视频
在steamlit中通过opencv打开视频中的每一帧,再将图片发送到后端进行相关处理,最后返回处理好的图片,将其显示在同一位置连续展示达到视频效果。这样可以实现实时返回结果,关键代码如下。
# 使用opencv读取视频帧并展示 来达到视频的效果
image_placeholder = st.empty() # 创建空白块使得展示原图
result_place = st.empty() # 创建空白块使得展示处理好的结果
import tempfile
f = st.file_uploader("Upload file") # 上传本地视频 数据以二进制写入内存无法直接用opencv打开
if f is not None:
tfile = tempfile.NamedTemporaryFile(delete=False) # 创建临时文件
tfile.write(f.read()) # 视频数据写入临时文件
cap = cv2.VideoCapture(tfile.name) # opencv打开临时文件
if (cap.isOpened() == False):
st.write("Error opening video stream or file")
while (cap.isOpened()):
success, frame = cap.read()
if success:
to_show = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 读取当前帧图片数据
to_show = Image.fromarray(np.uint8(to_show)) # numpy.ndarray 转 PIL.Image.Image
bytes_io = io.BytesIO()
to_show.save(bytes_io, format="PNG") # 将数据以二进制写入内存
estimate = process(bytes_io.getvalue(), backend) # 发送二进制图片数据 返回处理好的图片二进制数据
estimated_image = Image.open(io.BytesIO(estimate.content)).convert("RGB") # 得到处理好的结果图片
image_placeholder.image(to_show, caption='Video') # 原图片 将图片帧展示在同一位置得到视频效果
result_place.image(estimated_image, caption='Video') # 结果图片 将图片帧展示在同一位置得到视频效果
else:
break
cap.release()
将整个视频作为数据发送到后端,在后台将整个视频处理好后,再发送回前端。
streamlit
使用st.file_uploader读取本地视频,再使用st.video展示处理完的视频,代码如下。
f = st.file_uploader("Upload file") # 上传本地视频 数据为二进制存在内存中 可通过f.getvalue读取
if f is not None:
estimate = process(f, backend) # 返回response需要用response.content读取其中内容
estimate = io.BytesIO(estimate.content) # 往内存中写入estimate.content数据
st.video(estimate, format="video/mp4", start_time=0) # 展示视频
fastapi
采用response文件的方式将我们处理好的视频发送至前端,代码如下。
@app.post("/estimation", response_class=FileResponse)
def main(file: bytes = File(...)):
out_video = video_process(file) # 使用response文件方式 video_process返回值为文件名
return out_video
opencv处理前端发送过来的数据
仍然采用创建临时文件的方式打开前端传过来的二进制数据,代码如下。
注意,opencv保存视频时需选择avc1编码方式,streamlit不支持显示MP4V的编码视频。
以及streamlit可能不支持显示avi文件,建议保存文件统一为MP4格式。
def video_process(binary_video):
import tempfile
outfile_name = 'output.mp4' # 输出结果文件名
binary_video = io.BytesIO(binary_video) # 将前端传来binary_video写入内存
tfile = tempfile.NamedTemporaryFile(delete=False) # 创建临时文件
tfile.write(binary_video.read()) # 写入临时文件
cap = cv2.VideoCapture(tfile.name) # 打开文件
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) # 获取视频图像宽
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 获取视频图像高
fps = cap.get(cv2.CAP_PROP_FPS) # 读取图像显示帧率
fourcc = int(cv2.VideoWriter_fourcc(*'avc1')) # 选择编码方式 streamlit不支持显示MPV4编码方式
out = cv2.VideoWriter(outfile_name, fourcc, fps, (width, height)) # 创建输出视频
版权声明:本文为qq_45926473原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。