The purpose of this page is to layout exactly what elements of SIC are being run and where, why, and whyhow, to gain more insight into the design of the framework. It is not to analyze how face detection works.
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 (Parsing out Components)
FaceDetection service is ran in a terminalseparate shell, creating an associated ComponentManager
Code Block | ||
---|---|---|
| ||
run-face-detection |
within a shell
This runs the main() function of face_detection.py, which starts a ComponentManager
enveloping assigned to the FaceDetectionComponent
. As of nowIn this example, this script is ran on the same computer as the rest of the application, although it may be ran on another computer.
...
Code Block | ||
---|---|---|
| ||
# Connect to the services desktop = Desktop(camera_conf=conf) |
within desktop_camera_facedetection.py
Rather than running a ComponentManager
in a separate terminal, the Desktop class (inherits from Device) creates a new thread where its ComponentManager
runs.
...
Assumes that the first image in the faces buffer (contains bounding boxes) corresponds with the first image in the images buffer.
Diagram of this level:
...
Takeaways:
Components like
FaceDetection
do not simply run just by themselves. They consist of aConnector
which is basically a remote control for the actual component, aComponentManager
which runs them, and then the component itself.
Level 2 (Redis Channels)
FaceDetection service is ran in a separate shell, creating an associated ComponentManager
ComponentManager registers a request handler on a channel with the same name as its IP. This means whenever a message is published on this channel, it will process the message according to its function _handle_request
(see ComponentManager script). As of writing this, it only expects two types of requests: it either starts a specific component given a SICStartComponentRequest
, or sets a stop event to stop all of its associated components given a SICStopRequest
.
Desktop device is instantiated
Same as above, except rather than being its own process this ComponentManager is in a thread belonging to the main application process. Moreover, it also manages a different set of components (microphone, camera, speakers, TTS) than the FaceDetection ComponentManager.
Each component is not really a component, but a connector.
FaceDetection is connected to
The Connector
stores the names of the following Redis channels (does not necessarily use them yet)
input_channel: “FaceDetectionComponent:input:{IP}”
_request_reply_channel: “FaceDetectionComponent:reqreply:{IP}”
output_channel: “FaceDetectionComponent:{IP}”
Info |
---|
Note that the IP is the IP that the actual component is running on (passed into the Connector). If no IP is passed in, it will assume it is running on localhost by default. |
Initially tries to ping the actual component. Since the actual component has not been started yet, it sends a message over Redis which is then picked up by its ComponentManager. The associated ComponentManager then starts the actual component.
In this example, there are two ComponentManagers running on the same host. However, they have different sets of components. In the _handle_request
function, each ComponentManager will check to see if the component that’s being requested belongs to it before it starts it. This way, multiple instances of the same component are not started if multiple ComponentManagers are running on the same host.
The connector then subscribes to the input channel so that messages can be manually sent if needed. **not exactly sure why we need this or if it is used.
Desktop camera feed is connected to FaceDetection
In the following line:
Code Block | ||
---|---|---|
| ||
face_rec.connect(desktop.camera) |
A component (desktop.camera) is passed into the connect() method of a Connector
.