Camera Thing, CameraProtocol, and specific cameras create a confusing dependency loop.
The current system for cameras is really impeding development.
We have:
- A
CameraProtocol - A
BaseCameraclass -
StreamingPiCamera2- that is in a different repo and doesn't inherit fromBaseCamera. - Other Cameras "Things" that inherit from from
BaseCamera
Some issues include:
-
The
BaseCameraclass claims to be implementingCameraProtocol, but isn't based on the methods missing. - As we use specific cameras to test (PiCamera on a microscope, simulation in tests) nothing errors. -
labthings-picamera2is effectively a circular dependency -labthings-picamera2cannot depend onopenflexure-microscope-serverto inherit fromBaseCameraasopenflexure-microscope-serverhas an optional dependency onlabthings-picamera2. This means to develop, edits that affect the protocol need to simultaneously be added into two repositories as the PiCamera is our default camera in for real world use and testing. - It is not possible to add functionality to the BaseClass as it is not inherited, this makes abstraction far less good.
What to do
As the PiCamera is the standard camera for the microscope I think it is best to move the StreamingPiCamera2 and all labthings-picamera2 functionality into this repo.
We had previously talked about moving all the camera code into a repo called labthings-cameras. However, it is becoming clearer that the way we are implementing the camera protocol is pretty specific to the server needs.
Once StreamingPiCamera2 is in the Repo we can make StreamingPiCamera2 inherit from BaseCamera. We should also consider merging BaseCamera and CameraProtocol. Note the PEP 544 is quite clear that it is possible to implement methods in a protocol, and that inheriting from a protocol does not make the inheriting class a protocol, but does allow them to get methods "for free".
This way we can make the Base/Protocol class implement certain functionality. For example. Currently we can collect images in lots of ways (Blob, array, PIL image). The Base class could have base functions to convert between types, so if a collection method is not directly implemented by the camera, the correct data can be created by conversion.
The cameras also needs to be able to report things like its imaging modes and resolutions so that code are not assuming a PiCamera v2 board and asking all other cameras to act like this. For example a method like cam.get_available_capture_modes() could exist. For the PiCamera V2 board it should probably return something like:
{
"rapid": {
"name": "Rapid (0.5MP)",
"description": "The fastest capture, but only 0.5MP",
"capture_resolution": (820, 616),
"stream_resolution": (820, 616)
},
"fast": {
"name": "Fast (2MP)",
"description": "A fast way to capture a 2MP image, quality is diminished",
"capture_resolution": (1640, 1232),
"stream_resolution": (1640, 1232)
},
"standard": {
"name": "Standard (2MP)",
"description": "Recommended. The most robust way to capture high quality a 2MP image.",
"capture_resolution": (1640, 1232),
"stream_resolution": (3280, 2464)
},
full: {
"name": "Full (8MP)",
"description": "Full 8MP capture, this is slowest and may not have any more useful data than Standard.",
"capture_resolution": (3280, 2464),
"stream_resolution": (3280, 2464)
}
}
This way we use have a list names to expose to the GUI. We can tell the camera simply to enter that capture mode, this way the camera can correctly set up its streams at a lower level depending on how the camera works behind the scenes.
Possible issues
-
Importing - This can be solved by Picamera2 being an optional dependency in the same way
labthings-picamera2is. -
Testing - Currently
labthings-picamera2has tests but they can only be run on a Pi. The easiest thing to do is to exclude the picamera specific code from the base coverage statistics. We can then move the PiCamera tests to a directory calledhardware-specific-tests/picamera. This way it is easy to run the tests from a Pi when developing the server. - Untested Cameras - Currently no testing is done with the OpenCV camera. It would be good to have a documented way to test this camera too.