Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

I will break it down into different levels of increasing detail as to not be too overwhelming at once. In this simple example, a desktop computer uses its camera to detect and display bounding boxes around faces.

Level 1

  1. FaceDetection service is ran in a terminal, creating an associated ComponentManager

Code Block
languagebash
run-face-detection

This runs the main() function of face_detection.py, which starts a ComponentManager enveloping the FaceDetectionComponent. As of now, this script is ran on the same computer as the rest of the application, although it may be ran on another computer.

  1. Desktop device is instantiated

Code Block
languagepy
# Connect to the services
desktop = Desktop(camera_conf=conf)

Rather than running a ComponentManager in a separate terminal, the Desktop class (inherits from Device) creates a new thread where its ComponentManager runs.

  1. FaceDetection is connected to

Code Block
languagepy
face_rec = FaceDetection(ip="")

This instantiates a Connector which tries to connect to the actual FaceDetection component running on the specified IP.

  1. Desktop camera feed is connected to FaceDetection

Code Block
languagepy
face_rec.connect(desktop.camera)

This connects the output channel of the camera to the input channel of the FaceDetection component. desktop.camera is also a Connector.

  1. Callback functions are registered for Desktop camera and FaceDetection component

Code Block
languagepy
imgs_buffer = queue.Queue(maxsize=1)
faces_buffer = queue.Queue(maxsize=1)


def on_image(image_message: CompressedImageMessage):
    imgs_buffer.put(image_message.image)


def on_faces(message: BoundingBoxesMessage):
    faces_buffer.put(message.bboxes)
    
    
desktop.camera.register_callback(on_image)
face_rec.register_callback(on_faces)

For every message the DesktopCamera or FaceDetection components publish on their output channels, they also will put in their respective buffers.

  1. Buffers are continuously read from, bounding boxes are drawn on and displayed

Code Block
languagepy
while True:
    img = imgs_buffer.get()
    faces = faces_buffer.get()

    for face in faces:
        utils_cv2.draw_bbox_on_image(face, img)

    cv2.imshow("", img)
    cv2.waitKey(1)

Assumes that the first image in the faces buffer (contains bounding boxes) corresponds with the first image in the images buffer.

...

Takeaways:

  • Components like FaceDetection do not simply run by themselves. They consist of a Connectorwhich is basically a remote control for the actual component, a ComponentManager which runs them, and then the component itself.

Level 2

Level 3