Saturday, 15 October 2022

Camera stream using Asyncio and holoviews

I am trying to adapt this answer to my needs. I am trying to write a small program to operate some lab equipment, and instead of a prerecorded video, I want to show the output of a camera. That part works well using the following code:

import numpy as np
import pandas as pd
import holoviews as hv
hv.extension('bokeh')
from holoviews.streams import Pipe, Buffer
from tornado.ioloop import IOLoop
from tornado import gen
import cv2
from instrumental.drivers.cameras import uc480
instruments = uc480.list_instruments()

@gen.coroutine
def f():
#async def f():
    while cam.is_open:
        frame = cam.grab_image(timeout='10s', copy=True, exposure_time='10ms')
        rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        yield pipe.send(rgb)
        #await pipe.send(rgb)       
    cv2.destroyAllWindows()

cam = uc480.UC480_Camera(instruments[0],reopen_policy='reuse')
cam.start_live_video(framerate = "10Hz")
frame0 = cam.grab_image(timeout='10s', copy=True, exposure_time='10ms') 
rgb = cv2.cvtColor(frame0, cv2.COLOR_BGR2RGBA)
pipe = Pipe(data=rgb)
#camera_task = asyncio.gather(f())#doesn't work?
camera_loop = IOLoop.current().add_callback(f)
hv.DynamicMap(hv.RGB, streams=[pipe])

I have little experience outside of writing small scripts, so I chose to use Panel for my simple UI, and asyncio to make everything running smoothly. I started to modify the code some more in order to better understand it, yet so far I failed. My questions are the following:

  • From what I could gather, tornado may not be required, since asyncio provides similar/identical funcionality. I would very much like to use only asyncio if possible, or does tornado add anything substantial in this case?
  • According to the documentation, I should be able to replace the @gen.coroutine decorator and the yield keyword with async and await, which I already know from asyncio, but when doing that, the loop never starts. How do I start the loop then in the correct way?
  • Finally, if tornado is required, how would one stop the loop from running in this example?. In asyncio I would just .cancel() the task, but in this case that didn't work.

edit: a little more information:

  • Right now, while developing, I am running the code in a Jupyter notebook.
  • Once it is finished (or when testing), I run the code using panel serve (which shows everything in a browser tab, running a tornado server in the background if I understand correctly)
  • My idea is to use the camera to image a laser spot on a sample surface.
  • I would like to use the camera in real-time, to be able to check by eye if the laser is in focus. --- My questions and doubts are about this step, since I have no experience with asynchronous(?) programming (as in more complex than a simple script without UI) . What would be the standard way to do this?
  • I will then also use one-shot images to extract and process data (e.g cross-sections of the laser profile, etc. using holoviews.) --- This already works.


from Camera stream using Asyncio and holoviews

No comments:

Post a Comment