python - 将实时视频帧从用户/客户端(Android 应用程序、iPhone 应用程序、python)流式传输到 Flask API(服务器),然后返回到客户端
问题描述
我正在开发 Flask 中的对象检测 API,我想从客户端获取实时视频流,该视频流可能来自 Android 手机、iPhone 或仅来自在 Windows/Linux 上运行的 python 脚本。起初我尝试以下:
def processFrames():
print('[DEBUG] call cv2.VideoCapture(0) from PID', os.getpid())
camera = cv2.VideoCapture(0)
while camera.isOpened():
ret, frame = camera.read()
if not ret:
break
else:
frame = DetectObject(frame)
ret, buffer = cv2.imencode('.jpg', frame)
frame = buffer.tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
@endpoints.route('/RealTime', methods=['GET','POST'])
def RealTime():
return Response(processFrames(), mimetype='multipart/x-mixed-replace; boundary=frame')
但它不断给出错误:
[警告:1]全局/tmp/pip-req-build-13uokl4r/opencv/modules/videoio/src/cap_v4l.cpp(890)打开VIDEOIO(V4L2:/dev/video0):无法按索引打开摄像机
我意识到这是因为 OpenCV 试图打开服务器上的相机。然后我来到了这个解决方案: https ://stackoverflow.com/a/59998983/16396308
但我不知道如何收到来自:
emit('response_back', stringData)
[编辑]
请帮助,因为当我使用上面的解决方案时,通过邮递员发送了一个图像,这是我在服务器上的:
frame = secure_filename(file.filename)
sbuf = StringIO()
sbuf.write(frame)
b = BytesIO(pybase64.b64decode(frame))
pimg = Image.open(b)
将图像作为文件接收(暂时),但对于一张图像,我收到以下错误:
binascii.Error binascii。
错误:不正确的填充
对于不同的图像,我得到以下错误:
PIL.UnidentifiedImageError
PIL.UnidentifiedImageError:无法识别图像文件 <_io.BytesIO object at 0x7f3d9bbcf5e0>
[编辑 2]
我能够将视频从 python 脚本流式传输到远程机器。
客户端.py
def RT_Rec():
camera = cv2.VideoCapture(0)
try:
while True:
ret, frame = camera.read()
content_type = 'image/jpeg'
headers = {'content-type': content_type}
url = "https://[REMOTEMACHINEIP]/RealTime"
_, img_encoded = cv2.imencode('.jpg', frame)
response = requests.post(url, data=img_encoded.tobytes(), headers= headers)
if b"[SUCCESS]" in response.content or b"[ERROR]" in response.content :
print(response.content.decode('utf-8'))
break
else:
nparr = np.frombuffer(response.content,np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
# print(type(img))
cv2.imshow("camera", img)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
except Exception as e:
print(e)
finally:
camera.release()
cv2.destroyAllWindows()
服务器.py
@endpoints.route("/RealTime",methods=["GET","POST"])
def realTime():
if request.method == "POST":
img = request.data
nparr = np.fromstring(img,np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
det,outImg = processFrame(img)
if det:
msg = "[SUCCESS] Processed"
return msg
_, img_encoded = cv2.imencode('.jpg', outImg)
return img_encoded.tobytes()
else:
return "[ERROR] Invalid Request", 500
现在我想知道如何从 Android/iPhone 应用程序发送帧,以便服务器接收它们而不会出现任何错误。?
解决方案
您可以使用 SocketIO 获取用户提要,
from flask import Flask, render_template, request
...
@socketio.on('connect', namespace='/web')
def connect_web():
print('[INFO] Web client connected: {}'.format(request.sid))
@socketio.on('disconnect', namespace='/web')
def disconnect_web():
print('[INFO] Web client disconnected: {}'.format(request.sid))
@socketio.on('connect', namespace='/cv')
def connect_cv():
print('[INFO] CV client connected: {}'.format(request.sid))
@socketio.on('disconnect', namespace='/cv')
def disconnect_cv():
print('[INFO] CV client disconnected: {}'.format(request.sid))
这里有一些链接会派上用场:
推荐阅读
- scala - 功能存储库 - 基于 find()/create() 方法构建 get()
- python - 如何使用 python-docx 向 Word 文档添加超链接?
- python - 如果字符串在列表中,如何用它的字母替换 \u0000
- javascript - 随机播放数组在 Javascript 中给出相同的值
- bert-language-model - 无法执行 BioBERT run_factoid.py 程序
- gcc - 长“来回”gcc库路径背后的原因
- api - Shopware 6 Admin API 的文档。什么是可能的命令?
- javascript - 我无法选择值数据
- r - 如何仅保留R中某些列中具有最高值的行
- c++ - 反映文件中的更改,使用预处理器宏读取