Видеоканал OpenCV подается через Python Flask очередей, введенных пользователем на веб-странице - PullRequest
0 голосов
/ 27 апреля 2020

Я работаю над проектом, который транслирует видео с пи (который будет установлен на машине r c) на веб-сервер в облаке, и позволяет кому-то управлять автомобилем, используя потоковое видео и нажатия клавиш используя флягу / javascript.

Хотя я натолкнулся на довольно большую стену. Видеопоток, кажется, ставит в очередь любые нажатия клавиш, собранные javascript. Я посмотрел варианты потоков; однако, я не думаю, что это возможно, так как возвращение из функции video_feed является объектом Response, который я не уверен, как бы я мог использовать, если бы он был многопоточным. Другая идея заключалась в том, чтобы каким-то образом иметь другое приложение только для потоковой передачи видео в / video_feed, но я не уверен, возможно ли получить к нему доступ через основное приложение. У меня заканчиваются идеи ...

app.py

@app.route('/video_feed/<car_id>')
@login_required
def video_feed(car_id):
    car_video_port = int(car_data['car'+str(car_id)]['video_port'])
    stream_viewer = StreamViewer(port=car_video_port)
    return Response(stream_viewer.gen_frame(),
                    mimetype='multipart/x-mixed-replace; boundary=frame')

car_movement = []
@app.route('/command_car/<string:car_id>', methods=['GET', 'POST'])
@login_required
def command_car(car_id):
    new_direction = request.get_json(force=True)['direction']
    up_or_down = request.get_json(force=True)['up_or_down']

    if new_direction == 'stop':
        format_movement('stop',car_id)
    elif new_direction in car_movement and up_or_down == 'up':
        car_movement.remove(new_direction)
        format_movement(car_movement,car_id)
    elif new_direction in car_movement and up_or_down == 'down':
        pass    
    elif new_direction not in car_movement and up_or_down == 'up':
        pass
    elif new_direction not in car_movement and up_or_down == 'down':
        car_movement.append(new_direction)
        format_movement(car_movement,car_id)

stream_viewer.gen_frame

def gen_frame(self):
    self.keep_running = True
    while self.footage_socket and self.keep_running:
        try:
            frame = self.footage_socket.recv_string()
            img = string_to_image(frame)
            encodedImage = cv2.imencode(".jpg", img)[1].tostring()
            yield (b'--frame\r\n'
                  b'Content-Type: image/jpeg\r\n\r\n' + encodedImage + b'\r\n\r\n')
        except KeyboardInterrupt:
            cv2.destroyAllWindows()
            break
    print("Streaming Stopped!")

html file

{% extends "bootstrap/base.html" %}

{% block title %}
Drive Car
{% endblock %}

{% block styles %}
{{super()}}
<link rel="stylesheet" href="{{url_for('.static', filename='drive_car.css')}}">
{% endblock %}

{% block content %}

<iframe src="/video_feed/{{ car }}" width="400" height="400"></iframe>

Use the arror keys to drive the car!
<script type=text/javascript>

var forward = false;
var reverse = false;
var left = false;
var right = false;

document.onkeydown = checkKeyDown;
function checkKeyDown(e) {
    e = e || window.event;

    if (e.keyCode == '38') {
        direction = 'forward'
        if (!forward) {
            forward = true;
            movement = true;
        }
    }
    else if (e.keyCode == '40') {
        direction = 'reverse'
        if (!reverse) {
            reverse = true;
            movement = true;
        }
    }
    else if (e.keyCode == '37') {
        direction = 'left'
        if (!left) {
            left = true;
            movement = true;
        }
    }
    else if (e.keyCode == '39') {
        direction = 'right'
        if (!right) {
            right = true;
            movement = true;
        }
    }
    else {
        movement = false;
    }

    if (movement) {
        var xhr = new XMLHttpRequest();
        xhr.open("POST", "/command_car/{{car}}", true);
        xhr.setRequestHeader('Content-Type', 'application/json');
        xhr.send(JSON.stringify({"direction": direction,"up_or_down": "down"}));
    }
    movement = false;
}

document.onkeyup = checkKeyUp;
function checkKeyUp(e) {
    e = e || window.event;

    if (e.keyCode == '38') {
        direction = 'forward'
        forward = false;
        change = true;
    }
    else if (e.keyCode == '40') {
        direction = 'reverse'
        reverse = false;
        change = true;
    }
    else if (e.keyCode == '37') {
        direction = 'left'
        left = false;
        change = true;
    }
    else if (e.keyCode == '39') {
        direction = 'right'
        right = false;
        change = true;
    }
    else {
        change = false;
    }

    if (change) {
        var xhr = new XMLHttpRequest();
        xhr.open("POST", "/command_car/{{car}}", true);
        xhr.setRequestHeader('Content-Type', 'application/json');
        xhr.send(JSON.stringify({"direction": direction,"up_or_down": "up"}));
    }
    change = false;
}

window.onbeforeunload = function() {
        var xhr = new XMLHttpRequest();
        xhr.open("POST", "/command_car/{{car}}", true);
        xhr.setRequestHeader('Content-Type', 'application/json');
        xhr.send(JSON.stringify({"direction": "stop","up_or_down": "up"}));    
}
    </script>

{% endblock %}
...