Home > OS >  Stream OpenCV Video Capture to flask server
Stream OpenCV Video Capture to flask server

Time:06-07

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!!!

CodePudding user response:

It is not full solution.


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

  • Related