Jetson Nano B01 - setting exposure times for two raspberry pi cameras

I checked the samples, but they’re writtein in C++ (that I don’t know unfortunately).
I’m using Python for my work.

Thanks for the reply!

You would set the pipeline such as:

"nvarguscamerasrc sensor_id=0 wbmode=0 awblock=true gainrange=\"8 8\" ispdigitalgainrange=\"4 4\" exposuretimerange=\"5000000 5000000\" aelock=true ! video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080,format=(string)NV12, framerate=(fraction)30/1 ! nvvidconv ! video/x-raw, format=(string)BGRx ! videoconvert ! video/x-raw, format=(string)BGR ! appsink"
1 Like

Thank you very much, I had some problems with the string formatting.

If I use sensor-mode=3 (which is 60fps, 1280x720) I can avoid to set the framerate parameter if I use exposuretimerange values less than 16ms, am I right?

I would advise to set the framerate so that another framerate wouldn’t be used.
The maximum exposure time for a given framerate depends on your sensor, you would check further or keep a small margin wrt to period.

1 Like

So, this is what I did so far.
As I said before, I’m using the code given by JetsonHacksNano.

I set the pipeline in the following way:

def gstreamer_pipeline(
sensor_id=0,
capture_width=1280,
capture_height=720,
display_width=1280,
display_height=720,
framerate=30,
flip_method=0,
exposuretime_low = 5000000,
exposuretime_high = 5000000,
):
return (
"nvarguscamerasrc sensor-id=%d, "
"video/x-raw(memory:NVMM), "
"width=(int)%d, height=(int)%d, "
"wbmode=0, awblock=true, gainrange="8 8", ispdigitalgainrange="4 4", "
"exposuretimerange="(int)%d (int)%d", aeLock=true, "
"format=(string)NV12, framerate=(fraction)%d/1 ! "
"nvvidconv flip-method=%d ! "
"video/x-raw, width=(int)%d, height=(int)%d, format=(string)BGRx ! "
"videoconvert ! "
“video/x-raw, format=(string)BGR ! appsink”

    % (
        sensor_id,
        capture_width,
        capture_height,
        exposuretime_low,
        exposuretime_high,
        framerate,
        flip_method,
        display_width,
        display_height,
    )
)

Then I start the two cameras. For example, this is how I initialize the first one:

def start_cameras():
left_camera = CSI_Camera()
left_camera.open(
gstreamer_pipeline(
sensor_id=0,
exposuretime_low=1000000,
exposuretime_high=1000000,
framerate=30,
flip_method=0,
display_height=540,
display_width=960,
)
)
left_camera.start()

These are the only changes I did to the original code.
Unfortunately, I get this error when I run the code:

(python:7330): GStreamer-CRITICAL **: 13:06:07.953: gst_element_make_from_uri: assertion ‘gst_uri_is_valid (uri)’ failed
[ WARN:0] global /home/nvidia/host/build_opencv/nv_opencv/modules/videoio/src/cap_gstreamer.cpp (711) open OpenCV | GStreamer warning: Error opening bin: could not set property “sensor-id” in element “nvarguscamerasrc0” to “0,”
[ WARN:0] global /home/nvidia/host/build_opencv/nv_opencv/modules/videoio/src/cap_gstreamer.cpp (480) isPipelinePlaying OpenCV | GStreamer warning: GStreamer: pipeline have not been created

(python:7330): GStreamer-CRITICAL **: 13:06:07.965: gst_element_make_from_uri: assertion ‘gst_uri_is_valid (uri)’ failed
[ WARN:0] global /home/nvidia/host/build_opencv/nv_opencv/modules/videoio/src/cap_gstreamer.cpp (711) open OpenCV | GStreamer warning: Error opening bin: could not set property “sensor-id” in element “nvarguscamerasrc1” to “1,”
[ WARN:0] global /home/nvidia/host/build_opencv/nv_opencv/modules/videoio/src/cap_gstreamer.cpp (480) isPipelinePlaying OpenCV | GStreamer warning: GStreamer: pipeline have not been created
Unable to open any cameras
Traceback (most recent call last):
File “dual_exp.py”, line 202, in
start_cameras()
File “dual_exp.py”, line 184, in start_cameras
_ , right_image=right_camera.read()
File “dual_exp.py”, line 88, in read
frame = self.frame.copy()
AttributeError: ‘NoneType’ object has no attribute ‘copy’

Can’t really figure out where the problem is, being the code exactly the same as before.
Maybe there is an error in the new pipeline?

You may try to remove the ‘(int)’ here.
Also, I don’t see the ‘\’ before ‘"’ in the pipeline string.

Additional note: not faced that, but in some cases aeantibanding may also have to be set off.

1 Like

I’ll try later and I’ll let you know about the int and the aeantubanding parameter (I don’t think this one was listed in the parameter list.

Regarding the ‘\’ before ‘"’ in the pipeline, there is no such thing even in the original pipeline, which is the following:

"nvarguscamerasrc sensor-id=%d sensor-mode=%d ! "
"video/x-raw(memory:NVMM), "
"width=(int)%d, height=(int)%d, "
"format=(string)NV12, framerate=(fraction)%d/1 ! "
"nvvidconv flip-method=%d ! "
"video/x-raw, width=(int)%d, height=(int)%d, format=(string)BGRx ! "
"videoconvert ! "
“video/x-raw, format=(string)BGR ! appsink”

In the original pipeline, these were only quotes enclosing strings that will be concatenated.

But for the exposuretimerange argument, the string itself should contain quotes. In order to avoid these to be taken as end of string but rather to be chars in the string, you have to use a backslash before:

"nvarguscamerasrc sensor-id=%d, "
"video/x-raw(memory:NVMM), "
"width=(int)%d, height=(int)%d, "
"wbmode=0, awblock=true, gainrange=\"8 8\", ispdigitalgainrange=\"4 4\", "
"exposuretimerange=\"%d %d\", aeLock=true, "
"format=(string)NV12, framerate=(fraction)%d/1 ! "
"nvvidconv flip-method=%d ! "
"video/x-raw, width=(int)%d, height=(int)%d, format=(string)BGRx ! "
"videoconvert ! "
"video/x-raw, format=(string)BGR ! appsink"
1 Like

Infact I put them in the code, I don’t know they weren’t displayed in the previous comment. I’ll try the changes you suggested,

So, I copied your pipeline but still got the same error as before.
My previous pipeline was:

"exposuretimerange= \"(int)%d (int)%d \", aeLock=true, "

so I don’t think this is the problem.
Maybe the pipeline is not being created correctly because of the parameter’s order? But this should not be a problem either.
I know that sounds dumb, could it be the position of , and ! in the pipeline that’s causing the problem?

You would just print the pipeline string as returned from you function and post it here in code block:

pipeline_str = gstreamer_pipeline()
print(pipeline_str)
1 Like

Sorry I didn’t understand what you mean

Your python code defines a function gstreamer_pipeline() that return the pipeline string. Printing it would allow you to copy it from terminal and post it here so that someone would be able to check.

I think I got it…You added these options to the output caps of nvarguscamerasrc, while these are nvarguscamerasrc options. Try:

def gstreamer_pipeline(
sensor_id=0,
capture_width=1280,
capture_height=720,
display_width=1280,
display_height=720,
framerate=30,
flip_method=0,
exposuretime_low = 5000000,
exposuretime_high = 5000000,
):
return (
"nvarguscamerasrc sensor-id=%d, wbmode=0, awblock=true, gainrange=\"8 8\", ispdigitalgainrange=\"4 4\", exposuretimerange=\"%d %d\", aeLock=true ! "
"video/x-raw(memory:NVMM), width=(int)%d, height=(int)%d, format=(string)NV12, framerate=(fraction)%d/1 ! "
"nvvidconv flip-method=%d ! "
"video/x-raw, width=(int)%d, height=(int)%d, format=(string)BGRx ! "
"videoconvert ! "
"video/x-raw, format=(string)BGR ! appsink"
% (
        sensor_id,
        exposuretime_low,
        exposuretime_high,
        capture_width,
        capture_height,
        framerate,
        flip_method,
        display_width,
        display_height,
    )
)

Okay I understood, infact I was posting the pipeline output, which is:

nvarguscamerasrc sensor-id=0 video/x-raw(memory:NVMM), width=(int)1280, height=(int)720, wbmode=0, awblock=true, gainrange="8 8", ispdigitalgainrange="4 4", exposuretimerange="5000000 5000000", aeLock=true, format=(string)NV12, framerate=(fraction)30/1 ! nvvidconv flip-method=0 ! video/x-raw, width=(int)1280, height=(int)720, format=(string)BGRx ! videoconvert ! video/x-raw, format=(string)BGR ! appsink

This time I got this error:

(python:7955): GStreamer-CRITICAL **: 16:32:41.347: gst_element_make_from_uri: assertion 'gst_uri_is_valid (uri)' failed
[ WARN:0] global /home/nvidia/host/build_opencv/nv_opencv/modules/videoio/src/cap_gstreamer.cpp (711) open OpenCV | **GStreamer warning: Error opening bin: no element "video"**
[ WARN:0] global /home/nvidia/host/build_opencv/nv_opencv/modules/videoio/src/cap_gstreamer.cpp (480) isPipelinePlaying OpenCV | GStreamer warning: GStreamer: pipeline have not been created

(python:7955): GStreamer-CRITICAL **: 16:32:41.359: gst_element_make_from_uri: assertion 'gst_uri_is_valid (uri)' failed
[ WARN:0] global /home/nvidia/host/build_opencv/nv_opencv/modules/videoio/src/cap_gstreamer.cpp (711) open OpenCV | **GStreamer warning: Error opening bin: no element "video"**
[ WARN:0] global /home/nvidia/host/build_opencv/nv_opencv/modules/videoio/src/cap_gstreamer.cpp (480) isPipelinePlaying OpenCV | GStreamer warning: GStreamer: pipeline have not been created
Unable to open any cameras

I also understood your point, the order of the parameter is really important then. I used your part of code, but I’m still getting different errors, I could punch my monitor sooner or later :DDD
This time I’m getting these errors:

  1. Something similar to:
GStreamer warning: Error opening bin: could not set property "sensor-id" in element "nvarguscamerasrc0" to "0"
  1. This one is pretty awkward
Traceback (most recent call last):
  File "dual_exp.py", line 197, in <module>
    start_cameras()
  File "dual_exp.py", line 145, in start_cameras
    display_width=960,
  File "dual_exp.py", line 130, in gstreamer_pipeline
    display_height,
TypeError: not enough arguments for format string

This is the part of code I use to initialize the first camera (same code for the second one):

 left_camera = CSI_Camera()
    left_camera.open(
        gstreamer_pipeline(
            sensor_id=0,
            exposuretime_low=1000000,
            exposuretime_high=1000000,
            framerate=30,
            flip_method=0,
            display_height=540,
            display_width=960,
        )
    )
    left_camera.start()

I see some errors I did when modifying your code (I have not tested).
Plugin options are only separated by spaces, while caps properties are comma-separated.
You would modify the nvarguscamera options and remove the commas:

def gstreamer_pipeline(
sensor_id=0,
exposuretime_low = 5000000,
exposuretime_high = 5000000,
capture_width=1280,
capture_height=720,
display_width=1280,
display_height=720,
framerate=30,
flip_method=0,
):
return (
"nvarguscamerasrc sensor-id=%d wbmode=0 awblock=true gainrange=\"8 8\" ispdigitalgainrange=\"4 4\" exposuretimerange=\"%d %d\" aeLock=true ! "
"video/x-raw(memory:NVMM), width=(int)%d, height=(int)%d, format=(string)NV12, framerate=(fraction)%d/1 ! "
"nvvidconv flip-method=%d ! "
"video/x-raw, width=(int)%d, height=(int)%d, format=(string)BGRx ! "
"videoconvert ! "
"video/x-raw, format=(string)BGR ! appsink"
% (
        sensor_id,
        exposuretime_low,
        exposuretime_high,
        capture_width,
        capture_height,
        framerate,
        flip_method,
        display_width,
        display_height,
    )
)
1 Like

hello tooricco,

please note that, the exposure time range settings were based-on nanoseconds,
your setting, exposuretimerange="5000000 5000000" seems a quite small exposure values.
please also check your sensor capability for the supported exposure-time values.
you may look into device tree for the min_exp_time and max_exp_time properties.
while you enable camera steam, there’ll also report the available ranges for each sensor modes.
for example,

GST_ARGUS: Available Sensor modes :
GST_ARGUS: 1280 x 1080 FR = 29.999999 fps Duration = 33333334 ; Analog Gain range min 1.000000, max 8.000000; Exposure Range min 17000, max 28220000;
1 Like

I know they’re small exposure values, but they worked pretty well.
I choose those values just to test the cameras, but I also got solid results!

Thank you Honey, that solved my problem.
Just had a bit of difficulty setting the pipeline.
There is a documentation about it?

You may find some doc from NVIDIA here.

As general rule, for gstreamer some description is supposed to be embedded into plugins. Use:

# This would list all available plugins and more
gst-inspect-1.0

# This would show details about a given plugin. 
# Tells which library provides it
# SINK caps are for input, SRC caps for output
# Will list available options, default values...and more
gst-inspect-1.0 given_plugin