Camera parameters update

Hi,

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 in advance!

Best,
Dario

Hello @dariojavo ,

This should be possible through the Oak client, assuming you want to change something in the CameraSettings proto definition (e.g. exposure time).

There are some parameters that have to be set when the camera is connected to, so can you be more specific on what it is exactly you want to do?

Also, can you please provide what version of the brainOS you have or a picture of the home screen?

Thank you.

– Kyle

Hi Kyle,

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?

I’m currently on Amiga OS 1.2.

Thanks,
Dario

Thank you for the clarification @dariojavo ,

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.

See:

And:

– Kyle

Hi Kyle,

Thanks for the fast response.

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)

Thanks in advance.

Best,
Dario.

@dariojavo that looks good.

For what you want to do, you can:

  1. Make client a class arg (e.g., self.client).
  2. Create a separate asyncio task that only does the parameter changes and does NOT call stream_frames. (see example below based on your code)
  3. 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.

– Kyle

Thanks Kyle, I will take a look on this during the week and let you know how it goes.

Best,
Dario

Looking forward to hearing about it.

– Kyle

Hi Kyle,

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:

    camera_subscription = SubscribeRequest(
        uri=uri_pb2.Uri(
            # path=f"/{service_name}/{stream_name}",
            path=f"/calibration",
            query=f"service_name={service_name}",
        ),
        every_n=1,
    )        

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?

Thanks in advance Kyle!

Best,
Dario

Hello @dariojavo ,

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)

Check out the full examples here:

Camera calibration example:

Camera settings example:

Good luck!
Kyle