流openCV视频捕获到烧瓶服务器

发布于 2025-02-05 03:03:24 字数 1825 浏览 2 评论 0原文

问候, 我当时正在从事一个无人机项目,我想从笔记本电脑上的无人机流程中进行流,并根据处理提供命令,我使用的是从同一框架中使用烧瓶框架。

目前,作为第一步,我想从无人机中获取流并将其放到烧瓶服务器上并在烧瓶网站上查看,而不是立即进行处理部分。

将视频压缩到JPG之后,将视频放在服务器上,然后使用基本64对其进行编码,然后最终使用json.dumps(),然后 requests.puts.put() IT。

在Blask Server程序中的服务器端,我使用request.json,使用json.loads(),但我不清楚下一步该怎么做。

我在烧瓶,网络开发以及有限的经验和知识方面没有足够的经验,但是它在烧瓶程序中返回错误405

这是程序

服务器

import base64
import json

from flask import Flask, make_response, render_template, request

app = Flask(__name__)


def getFrames(img):
    pass


@app.route('/video', methods=['POST', 'GET'])
def video():
    if request.method == 'PUT':
        load = json.loads(request.json)
        imdata = base64.b64decode(load['image'])
        respose = make_response(imdata.tobytes())
        return respose


@app.route('/')
def index():
    return render_template('index.html')


@app.route('/cmd')
def cmd():
    pass


if __name__ == "__main__":
    app.run(debug=True)

索引

<!DOCTYPE html>
<html>

<head>
    <title>Video Stream</title>
</head>
<body>
    <h1>
        Live Stream
    </h1>
    <div>
        <img src="{{ url_for('video') }}" width="50%">
    </div>
</body>
</html>

烧瓶

import base64
import json
import requests
import cv2

cap = cv2.VideoCapture(1)

ip = ''                   #url returned by the flask program

while True:
    success, img = cap.read()
    cv2.imshow("OUTPUT", img)
    _, imdata = cv2.imencode('.JPG', img)
    jStr = json.dumps({"image": base64.b64encode(imdata).decode('ascii')})
    requests.put(url=(ip + '/video'), data=jStr)
    if cv2.waitKey(1) == 27:
        break

Greeting,
I was working on a drone project, I wanted to take stream from my drone process it on my laptop and give a command based on processing, I was using the flask framework from the same.

Currently, as the first step I want to take the stream from drone and PUT it to the flask server and view it on the flask website, not doing the processing part right now.

I PUT the video to server after compressing it into jpg and using base 64 to encode it and then finally use json.dumps() and then requests.put() it.

On the server side in flask server program I get its using request.json, use json.loads(), but I am not clear what to do next.

I am not experienced enough with flask, web development and with limited experience and knowledge made the programs, but it returns error 405 on the flask program.

Here are the programs

flask server

import base64
import json

from flask import Flask, make_response, render_template, request

app = Flask(__name__)


def getFrames(img):
    pass


@app.route('/video', methods=['POST', 'GET'])
def video():
    if request.method == 'PUT':
        load = json.loads(request.json)
        imdata = base64.b64decode(load['image'])
        respose = make_response(imdata.tobytes())
        return respose


@app.route('/')
def index():
    return render_template('index.html')


@app.route('/cmd')
def cmd():
    pass


if __name__ == "__main__":
    app.run(debug=True)

index.html

<!DOCTYPE html>
<html>

<head>
    <title>Video Stream</title>
</head>
<body>
    <h1>
        Live Stream
    </h1>
    <div>
        <img src="{{ url_for('video') }}" width="50%">
    </div>
</body>
</html>

drone program

import base64
import json
import requests
import cv2

cap = cv2.VideoCapture(1)

ip = ''                   #url returned by the flask program

while True:
    success, img = cap.read()
    cv2.imshow("OUTPUT", img)
    _, imdata = cv2.imencode('.JPG', img)
    jStr = json.dumps({"image": base64.b64encode(imdata).decode('ascii')})
    requests.put(url=(ip + '/video'), data=jStr)
    if cv2.waitKey(1) == 27:
        break

Any help is highly appreciated!!!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

凡间太子 2025-02-12 03:03:24

您不必转换为base64并使用JSON。直接以原始字节发送JPG可能更简单,更快,

并且使其更简单,我将使用/upload将图像从无人机发送到服务器,/video>/video向用户图像。

import requests
import cv2

cap = cv2.VideoCapture(0)

while True:
    success, img = cap.read()

    if success:    
        cv2.imshow("OUTPUT", img)
        
         _, imdata = cv2.imencode('.JPG', img)

        print('.', end='', flush=True)

        requests.put('http://127.0.0.1:5000/upload', data=imdata.tobytes())
    
    # 40ms = 25 frames per second (1000ms/40ms), 
    # 1000ms = 1 frame per second (1000ms/1000ms)
    # but this will work only when `imshow()` is used.
    # Without `imshow()` it will need `time.sleep(0.04)` or `time.sleep(1)`

    if cv2.waitKey(40) == 27:  # 40ms = 25 frames per second (1000ms/40ms) 
        break

cv2.destroyAllWindows()
cap.release()

现在烧瓶。这部分还不完整。

它从无人机中获取图像并保存在全球变量中。当用户打开页面时,它将从/video加载单个图像

from flask import Flask, make_response, render_template, request

app = Flask(__name__)

frame = None   # global variable to keep single JPG

@app.route('/upload', methods=['PUT'])
def upload():
    global frame
    
    # keep jpg data in global variable
    frame = request.data
    
    return "OK"

@app.route('/video')
def video():
    if frame:
        return make_response(frame)
    else:
        return ""

@app.route('/')
def index():
    return 'image:<br><img src="/video">'

if __name__ == "__main__":
    app.run(debug=True)

,此刻它只能显示一个静态图像。它需要以Motion-jpeg


编辑:

版本发送Motion> Motion-jpeg,因此您可以看到视频。

它可以与ChromeMicrosoft EdgeBrave(全部使用Chrome Engine)一起工作。

问题使Firefox。它悬挂并试图一直加载图像。我不知道真正的问题是什么,但是如果我添加time.sleep(),那么它可以解决问题。

from flask import Flask, Response, render_template_string, request
import time

app = Flask(__name__)

frame = None   # global variable to keep single JPG, 
               # at start you could assign bytes from empty JPG

@app.route('/upload', methods=['PUT'])
def upload():
    global frame
    
    # keep jpg data in global variable
    frame = request.data
    
    return "OK"

def gen():
    while True:
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n'
               b'\r\n' + frame + b'\r\n')
        time.sleep(0.04) # my Firefox needs some time to display image / Chrome displays image without it 
                         # 0.04s = 40ms = 25 frames per second 

        
@app.route('/video')
def video():
    if frame:
        # if you use `boundary=other_name` then you have to yield `b--other_name\r\n`
        return Response(gen(), mimetype='multipart/x-mixed-replace; boundary=frame')
    else:
        return ""

@app.route('/')
def index():
    return 'image:<br><img src="/video">'
    #return render_template_string('image:<br><img src="{{ url_for("video") }}">')

if __name__ == "__main__":
    app.run(debug=True)#, use_reloader=False)

服务器可以在进程上的分开线程中运行用户,有时它可能不会在用户之间共享frame。如果我使用use_reloader = false,那么我可以停止发送到/upload,然后在浏览器中停止视频,然后我可以再次开始发送到/upload 和浏览器再次显示流(无需重新加载页面)。没有use_reloader = false浏览器不会重新启动视频,因此需要重新加载页面。也许它需要使用flask.g来保持框架。或/upload必须在文件或数据库中保存帧,/video必须从文件或数据库中读取帧。

You don't have to convert to base64 and use JSON. it can be simpler and faster to send JPG directly as raw bytes

And to make it simpler I would use /upload to send image from drone to server, and /video to send image to users.

import requests
import cv2

cap = cv2.VideoCapture(0)

while True:
    success, img = cap.read()

    if success:    
        cv2.imshow("OUTPUT", img)
        
         _, imdata = cv2.imencode('.JPG', img)

        print('.', end='', flush=True)

        requests.put('http://127.0.0.1:5000/upload', data=imdata.tobytes())
    
    # 40ms = 25 frames per second (1000ms/40ms), 
    # 1000ms = 1 frame per second (1000ms/1000ms)
    # but this will work only when `imshow()` is used.
    # Without `imshow()` it will need `time.sleep(0.04)` or `time.sleep(1)`

    if cv2.waitKey(40) == 27:  # 40ms = 25 frames per second (1000ms/40ms) 
        break

cv2.destroyAllWindows()
cap.release()

Now flask. This part is not complete.

It gets image from drone and keep in global variable. And when user open page then it loads single image from /video

from flask import Flask, make_response, render_template, request

app = Flask(__name__)

frame = None   # global variable to keep single JPG

@app.route('/upload', methods=['PUT'])
def upload():
    global frame
    
    # keep jpg data in global variable
    frame = request.data
    
    return "OK"

@app.route('/video')
def video():
    if frame:
        return make_response(frame)
    else:
        return ""

@app.route('/')
def index():
    return 'image:<br><img src="/video">'

if __name__ == "__main__":
    app.run(debug=True)

At this moment it can display only one static image. It needs to send it as motion-jpeg


EDIT:

Version which sends motion-jpeg so you see video.

It works correctly with Chrome, Microsoft Edge and Brave (all use chrome engine).

Problem makes Firefox. It hangs and tries to load image all time. I don't know what is the real problem but if I add time.sleep() then it can solve problem.

from flask import Flask, Response, render_template_string, request
import time

app = Flask(__name__)

frame = None   # global variable to keep single JPG, 
               # at start you could assign bytes from empty JPG

@app.route('/upload', methods=['PUT'])
def upload():
    global frame
    
    # keep jpg data in global variable
    frame = request.data
    
    return "OK"

def gen():
    while True:
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n'
               b'\r\n' + frame + b'\r\n')
        time.sleep(0.04) # my Firefox needs some time to display image / Chrome displays image without it 
                         # 0.04s = 40ms = 25 frames per second 

        
@app.route('/video')
def video():
    if frame:
        # if you use `boundary=other_name` then you have to yield `b--other_name\r\n`
        return Response(gen(), mimetype='multipart/x-mixed-replace; boundary=frame')
    else:
        return ""

@app.route('/')
def index():
    return 'image:<br><img src="/video">'
    #return render_template_string('image:<br><img src="{{ url_for("video") }}">')

if __name__ == "__main__":
    app.run(debug=True)#, use_reloader=False)

Server may runs users in separated threads on processes and sometimes it may not share frame between users. If I use use_reloader=False then I can stop sending to /upload and this stops video in browser, and later I can start again sending to /upload and browser again displays stream (without reloading page). Without use_reloader=False browser doesn't restart video and it needs to reload page. Maybe it will need to use flask.g to keep frame. Or /upload will have to save frame in file or database and /video will have to read frame from file or database.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文