Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stream realtime video between 2 computers using Python

I am trying to send my macbook air webcam video in realtime and receive it using python on another computer. The motivation for this is to be able to offload realtime image recognition tasks to a server. The server requires having access to the realtime video frames in python so that I can then pass the frames to my image recognition algorithm (a deep neural net).

I was able to do this successfully using https://github.com/atuldo/videoStream which uses the socket library to send the video frames in string format. However, this method results is a very low frame rate (see below for code snippet).

Attempt 1:

from flask import Flask, render_template, Response
from camera import VideoCamera

app = Flask(__name__)

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

def gen(camera):
    while True:
        frame = camera.get_frame()
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')

@app.route('/video_feed')
def video_feed():
    return Response(gen(VideoCamera()),
                    mimetype='multipart/x-mixed-replace; boundary=frame')

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

I also used this https://github.com/log0/video_streaming_with_flask_example which uses flask to stream the video to a web page. Looking at the webpage in chrome it has a much better frame rate than my first solution. However, this solution does not receive the video in python and would require me to read the video from the webpage, which I am not exactly sure how to go about.

Attempt 2 (I replaced pygame from original github code with cv2 to be able to access my mac webcam) :

### Server
import socket
from threading import *
import socket
import pygame
import pygame.camera
from pygame.locals import *

import cv2

def server():
    #host_name = socket.gethostname()
    host_name = 'localhost'
    print "\nServer started at " + str(socket.gethostbyname(host_name)) + " at port " + str(90) 
    #port = 90
    port = 1024
    serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    serversocket.bind(("",port))
    serversocket.listen(10)
    #pygame.camera.init()
    #cam = pygame.camera.Camera(0,(640,480),"RGB")
    #cam.start()
    #img = pygame.Surface((640,480))
    video = cv2.VideoCapture(0)

    while True:
        connection, address = serversocket.accept()
        print "GOT_CONNECTION"
        #cam.get_image(img)
        #data = pygame.image.tostring(img,"RGB")
        success, image = video.read()
        data = cv2.imencode('.jpg', image)[1].tostring()
        connection.sendall(data)
        connection.close()

server()

###Reciever (snippet, for full code please refer to the github link above)

        clientsocket=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        clientsocket.connect((self.ipAddress, self.port))
        received = []
        while True:
            recvd_data = clientsocket.recv(230400)
            if not recvd_data:
                break
            else:
                received.append(recvd_data)
        dataset = ''.join(received)
        #image = pygame.image.fromstring(dataset,(640, 480),"RGB") # convert received image from string
        nparr = np.fromstring(dataset, np.uint8)
        image = cv2.imdecode(nparr, cv2.CV_LOAD_IMAGE_COLOR)
        cv2.imwrite('foo.jpg', image)
        #pygame.image.save(image, "foo.jpg")
        self.ids.image_source.reload()

The video stream is displayed on the webpage like so:

<html>
  <head>
    <title>Video Streaming Demonstration</title>
  </head>
  <body>
    <h1>Video Streaming Demonstration</h1>
    <img id="bg" src="{{ url_for('video_feed') }}">
  </body>
</html>

How can I get a high frame rate with either one of the two approaches or is there a better way to go about this?

like image 682
alexbhandari Avatar asked Jun 18 '17 05:06

alexbhandari


1 Answers

The reason may be that you VideoCapture device is not configured for higher framerate or it does not support higher framerate at all.

You specified very low frame rate, I don't know what this means to you, but I tested it with my 2 cameras. With slightly modified code, I can max out the first camera to 15fps, but the second one is running at 25fps without problems. These are expected numbers for me.

like image 175
Jiri Avatar answered Sep 19 '22 14:09

Jiri