I’m trying to change the camera parameters of multiple cameras from a kivy app. Unfortunately, for now I have only been able to change the parameters when the code starts since I am not able to re-write the configuration while streaming. How can I change the parameters while streaming, or how can I stop the camera stream, in order to modify the parameters and start the stream again?
Thanks for your response. Yes, that is in fact what I have used to modify the settings. I have been able to do it before the stream is created. Following you camera streaming template that would be in here:
# Create the stream
if response_stream is None:
#Change camera settings (Change exposure, iso, ....)
response_stream = client.stream_frames(every_n=self.stream_every_n)
However, I have been able to do this only before streaming, once the camera start streaming I can not change the camera settings without getting the camera going down. Is there a way to change the camera settings in live or either stop the camera service in order to change the parameters and start the service again?
Have you tried using the update_rgb_settings or update_mono_settings methods of the OakCameraClient , followed by send_settings?
update_rgb_settings and update_mono_settings take a CameraSettings proto as an argument. You should be able to do this while the cameras are streaming and the stream will continue on with the new settings. If you want to change the rate with the every_n argument, you should cancel the stream and restart it.
Yes, I have used update_rgb_settings, update_mono_settings, and send_settings, and they worked, that is how I was able to change the parameters before streaming. Please see below how I am currently changing the parameters.
# Create the stream
if response_stream is None:
# Update camera parameters
# Create a new instance of CameraSettings with desired parameters
new_rgb_settings = new_mono_settings = oak_pb2.CameraSettings(
auto_exposure = self.auto_exposure, # Set auto exposure
exposure_time = self.exposure_time, # Assume this is in us
iso_value = self.iso # ISO value
)
# Assuming new_rgb_settings is a protobuf object of CameraSettings type
client.update_rgb_settings(new_rgb_settings)
# Similarly for mono camera
client.update_mono_settings(new_mono_settings)
await asyncio.sleep(1)
# Send modified settings to the camera
response = await client.send_settings()
if response:
print(f"Ok, parameters have been updated for {port}")
response_stream = client.stream_frames(every_n=self.stream_every_n)
Create a separate asyncio task that only does the parameter changes and does NOT call stream_frames. (see example below based on your code)
Call this function when a button is pressed, or make this a forever running loop that checks for settings changes and sends the update when they’re changed. Something along those lines.
async def update_settings(self):
new_rgb_settings = oak_pb2.CameraSettings(
auto_exposure = self.auto_exposure, # Set auto exposure
exposure_time = self.exposure_time, # Assume this is in us
iso_value = self.iso # ISO value
)
new_mono_settings = new_rgb_settings
# Assuming new_rgb_settings is a protobuf object of CameraSettings type
self.client.update_rgb_settings(new_rgb_settings)
# Similarly for mono camera
self.client.update_mono_settings(new_mono_settings)
# Send modified settings to the camera
response = await self.client.send_settings()
print(response)
What is important is that you let the while loop with stream_frames keep running and do this settings change in a separate function.
I have been working now with the OS 2.0, and the recorder_v2 app. Considering this, it has been difficult for me to understand how to change the parameters of the camera in the stream_camera function. I have tried for example to see the camera calibration:
async for _, message in camera_client.subscribe(
camera_subscription, decode=True
):
print(message)
and it works! However, when I tried to access in the same way the /camera_settings/rgb to see them and modifying if keeps forever in a loop. How can I access and modify the camera parameters, similar to what I was doing before, with this new pipeline?
I apologize for the delayed response, we were very busy with preparations for and attending the FIRA conference.
We have a good example for exactly what you want to do! It’s not yet merged into GitHub - farm-ng/farm-ng-amiga at main-v2 (the farm-ng-amiga branch that corresponds to AmigaOS v2.x), so it would’ve been hard for you to find this.
The takeaway is that you want to use the request_reply method of the EventClient for single message queries like calibration & /camera_settings/rgb. There is no need to create a full “subscribe” loop for these single requests.
For calibration, you can do something like:
# get the calibration message
reply = await camera_client.request_reply("/calibration", Empty())
# parse the reply
calibration: oak_pb2.OakCalibration = payload_to_protobuf(reply.event, reply.payload)
print(calibration)
For camera settings, you can do something like:
camera_settings_request = oak_pb2.CameraSettings(
# Enter your parameters here
)
reply = await camera_client.request_reply(f"/camera_settings/{stream_name}", camera_settings_request)
# parse the reply
camera_settings: oak_pb2.CameraSettings = payload_to_protobuf(reply.event, reply.payload)
print(camera_settings)