Search code examples
pythonopencvtornadobokehholoviews

How to make a streaming plot with holoviews and tornado python


Hi I have just started with holoviews and I am trying to prepare a small streaming video app using holoviews, opencv. I have very limited experience with tornado and async programming.

from holoviews.streams import Pipe, Buffer
from tornado.ioloop import IOLoop
from tornado import gen
import cv2
@gen.coroutine
def f():
    pipe = Pipe(data=[])
    #print(pipe)
    vd = cv2.VideoCapture("TestVideo.mp4")
    width = int(vd.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(vd.get(cv2.CAP_PROP_FRAME_HEIGHT))
    frames = int(vd.get(cv2.CAP_PROP_FRAME_COUNT))
    print("Hello")
    for i in range(frames):
        ret, frame = vd.read()
        #print(i)
        try:
            rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            gen.sleep(10000000000)
            pipe.send(rgb[:])
            #print(str(i)+'x')
        except:
            #print(str(i)+'Error')
            print("Error at Frame:"+str(i))
            pass
    vd.release()
    cv2.destroyAllWindows()

IOLoop.current().add_callback(f)
hv.DynamicMap(hv.RGB, streams=[pipe])

I am not getting running/streaming updates. I just get a single image with last frame. Can somebody help me with figuring out my mistake here


Solution

  • Thank you @philippjfr

    In the end I got something workable using streamz python library . However this approach works. This is my working solution based on above approach.

    ```

    import numpy as np
    import pandas as pd
    import holoviews as hv
    hv.extension('bokeh', 'matplotlib')
    from holoviews.streams import Pipe, Buffer
    from tornado.ioloop import IOLoop
    from tornado import gen
    import cv2
    
    @gen.coroutine
    def f():
        width = int(vd.get(cv2.CAP_PROP_FRAME_WIDTH))
        height = int(vd.get(cv2.CAP_PROP_FRAME_HEIGHT))
        frames = int(vd.get(cv2.CAP_PROP_FRAME_COUNT))
        while frames > 0:
            ret, frame = vd.read()
            rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            frames -= 1
            yield pipe.send(rgb)
        vd.release()
        cv2.destroyAllWindows()
    
    vd = cv2.VideoCapture("TestVideo.mp4")    
    ret, frame0 = vd.read()
    rgb = cv2.cvtColor(frame0, cv2.COLOR_BGR2RGBA)
    pipe = Pipe(data=rgb)
    #pipe = Pipe(data=[])
    IOLoop.current().add_callback(f)
    hv.DynamicMap(hv.RGB, streams=[pipe])
    

    ```