Sensor Specific Functions
Some of the sensors supported in the qtec C-series platform have some specific functionality which is listed and explained below.
Sony IMX
Refers to the IMX42x/25x series used in the RGB AI Cameras and IMX99x series used in the Hypervision 1700 HSI Camera.
Light Sensitivity
The Sony IMX42x/25x/99x families have 3 available bit modes (8, 10 and 12 bit). The internal Vsat is adjusted to 1/4 when in 8 bit mode compared to the 10/12 bit modes. Therefore the light sensitivity is 4x higher in 8 bit mode when compared to the other modes, which makes the 8 bit mode the recommended mode for applications where the available light intensity is limited. For example fast moving objects or hyperspectral imaging.
Gpixel GSENSE
Refers to the GSENSE2020 used in the Hypervision 1000 HSI Camera.
Shutter modes
The Gpixel GSENSE2020 is a quite unique sensor which offers the possibility of choosing between rolling shutter and global shutter. Each of the shutter modes offers some specific features and advantages: for example it is possible to adjust the exposure time for each individual line when using the rolling shutter mode and to select individually which lines should be captured.
Rolling shutter vs Global shutter
The shutter type refers to the image capture process in the sensor: cameras can either have a rolling shutter or a global shutter.
In a rolling shutter setup each sensor line is exposed and read-out sequentially (in waves), while with a global shutter all pixels are exposed simultaneously. Global shutter sensors require therefore more internal memory (to store all the pixel values until they can be read out). Rolling shutter sensors are normally simpler and therefore cheaper and they also tend to have less noise and bigger sensitivity. But because of the sequential nature of the rolling shutter it is not recommended for fast moving objects since it can result in severe distortions in the image (see below).
Rolling shutter effect (cmglee, CC BY-SA 3.0, via Wikimedia Commons)
Qtec focuses on industrial cameras which normally involve fast moving objects, therefore most of the sensors that qtec works with use global shutter, with the exception of the GSENSE2020 which is a scientific CMOS with the option to select the shutter mode.
Shutter mode selection
The different shutter modes and their specific features can be selected by
choosing the appropriate bitstream
from the qtec-c-paris
series in conjuction with toggling the global shutter
V4L2 control:
-
pisces-paris
: the preferred and default bitstream for the GSENSE2020, supports both rolling and global shutter modes with specific features and limitations- rolling shutter
- allows adjusting the exposure time individually per line
using the
line exposure sequence
V4L2 control - allows selecting individually which lines should be captured
using the
line order
V4L2 control - maximum exposure limited to 68ms for a full frame (higher for smaller frames)
- allows adjusting the exposure time individually per line
using the
- global shutter
- maximum exposure limited to 16ms for a full frame (higher for smaller frames)
- rolling shutter
-
capricorn-paris
: legacy bitstream, supports both rolling and global shutter modes with specific features and limitations- rolling shutter
- not reccommended: no support for
line exposure sequence
orline order
, use pisces-paris instead
- not reccommended: no support for
- global shutter
- no limitation on the maximum exposure, however some combinations of framerate and exposure time can result in artifacts in the image (see the image artifacts section)
- rolling shutter
Note that by default both bitstreams start in Rolling Shutter
mode.
Switching between the two shutter modes can be achieved by toggling the
global shutter
V4L2 control.
pisces-paris
is the default bitstream for the GSENSE2020 and is what is used in the
Hypervision 1000 HSI Camera
because of it's ability to control the exposure individually for each line.
Rolling shutter mode
The rolling shutter on the GSENSE2020 is fully programmable.
This means that the exposure time of lines can be selected individually.
This can be achieved by programming the sensor via the Line Exposure Sequence
V4L2 control, which is effectively an array of values, one for each line.
While global shutter sensors normally allow for a single continuous cropping area (or in some cases up to 8 areas), the fully programmable rolling shutter makes it possible to select individually which lines should be captured (as well in what order). In this way the frame capture process and speed can be greatly optimized (the maximum framerate is directly proportional to the amount of lines captured).
If a single cropping area is desired the standard V4L2 crop/selection interface
can be used, just like for all other sensors supported by qtec.
However if selection of individual lines is desired, then the Line Order
V4L2 control should be used.
The Line Order
control is an array with the same size as the height of the
cropping area (set via the standard V4L2 crop/selection interface).
It's contents reflect the position of the lines to be captured, in the desired
capture order.
Setting the exposure per line
Only available in the pisces-paris bitstream
This is a small example showing how to change the exposure per line in rolling shutter mode, with qamlib.
import qamlib
cam = qamlib.Camera()
# Get the current exposure sequence
exposures = cam.get_ext_control("line exposure sequence").value
# Set the exposure for all lines to 5000
exposures[:] = 5000
# Set a different exposure on the bottom half of the lines
n = int(len(exposures)/2)
exposures[n:] = 2000
# Set the new exposure sequence
try:
cam.set_ext_control("line exposure sequence", qamlib.ArrayControlValue(exposures))
except V4L2Exception as e:
print(e)
quark-ctl can also be used as a quick way to set all lines to the same exposure value:
quark-ctl exposure-sequence --exposure 1000
Because of limited RAM in the FPGA, we have a limit on how complex/long the exposures can be. E.g. for a full frame the maximum exposure time is .
The requested change in the exposure sequence will be rejected if the requested
parameters don't fit within the available memory.
In this case qamlib
will throw an V4L2Exception
and an error will be visible
in dmesg
:
V4L2Exception: Failed to set extended control : (22) Invalid argument
dmesg: gsense-0: Line exposure sequence is too long or complex
Changing Line Exposure Sequence
will adjust the framerate if necessary
(if the current fps is higher than the new maximum fps)
Changing the selected lines
Only available in the pisces-paris bitstream
This is a small example showing how to change the line order in rolling shutter mode, with qamlib.
import qamlib
cam = qamlib.Camera()
# Start by adjusting the crop region to the desired size
cam.set_crop(left=0, top=0, width=2048, height=100)
# Get the current line order array
line_order = cam.get_ext_control("line order").value
# Adjust the desired lines:
# For example use every 5th line starting from 50
line = 50
for i, pos in enumerate(line_order):
line_order[i] = line
line += 5
# Set the new line order
try:
cam.set_ext_control("line order", qamlib.ArrayControlValue(line_order))
except V4L2Exception as e:
print(e)
Changing Line Order
will adjust the framerate if necessary
(if the current fps is higher than the new max fps)
Global Shutter mode
With the GSENSE2020 in global shutter mode, it acts a lot more like all the other supported sensors, except that for each image two frames are generated. The first is a reference frame that needs to be subtracted from the second one in order to generate the actual image.
Note that by default both bitstreams start in Rolling Shutter
mode.
In order to switch to the Global Shutter
mode it is necessary to enable the
global shutter
V4L2 control.
Bitstream differences
Note that both the legacy (capricorn-paris
)
and the default (pisces-paris
)
bitstreams support global shutter mode.
There are however some small differences between their behaviour because of
different implementations.
When using the pisces-paris
bitstream, because of limited RAM in the FPGA,
we have a limit on how complex/long the exposures can be.
For example, for a full frame the maximum exposure time is .
This limit is visible in the max
parameter of the exposure time absolute
V4L2 control, and it is updated when cropping is applied.
Values higher than the maximum get clamped (as happens with all normal V4L2
controls).
This limitation doesn't exist in the capricorn-paris
because it is implemented
in a different way.
However, that bitstream can present some image "artifacts" in some situations
(see below), therefore pisces-paris
is the reccomended (and default) bitstream.
Image "artifacts"
When using the capricorn-paris
legacy bitstream in global shutter mode there is no limitation on the maximum
exposure time, however some combinations of framerate and exposure time can
result in "artifacts" in the image.
An intensity change might occur in the image when changing the framerate while keeping the exposure time fixed (which should normally not occur).
Moreover, a horizontal "line" might be visible separating areas with higher and lower intensities. Changing the exposure time might cause the line to move up and down. The effect seems to happen only in the "real image", and not in the reference frame.
This behavior has been generally seen with framerate values under 40fps and exposure values around 2-5ms.
Framerate values above 40fps do not seem to produce issues.
The global shutter in the
pisces-paris
bitstream does not have the same issue, but as mentioned above, the maximum
exposure time there is limited to 16ms for a full frame.
Frame read-out in global shutter mode
This is a small example (using qamlib) of how to do the frame read-out from the GSENSE2020 in global shutter mode and to combine the 2 frames into the resulting image.
import qamlib
try:
# throw exception on dropped frames
cam = qamlib.Camera(overflow_exception=True)
except Exception as e:
print(e)
exit(-1)
# Set to global shutter (default is rolling shutter)
cam.set_control("global shutter", 1)
# Frame capture
i2 = 0
try:
with cam:
while True:
# Using 'buffered=True' will return the next frame in the queue
# and throw a 'DroppedFrameException' if the queue gets filled up
# set 'overflow_exception=False' in the Camera constructor
# if you want to disable this exception, but then it will be necessary
# to check for dropped frames using the sequence nr from the metadata
ref_meta, ref_frame = cam.get_frame(timeout=1, buffered=True)
meta, frame = cam.get_frame(timeout=1, buffered=True)
# the GSENSE2020 produces 2 frames "per frame" when on global shutter
# the 1st is a reference frame that should be subtracted from the 2nd
# in order to create the resulting image
res_frame = frame - ref_frame
# all this sequence nr checks shouldn't be necessary
# since we will get a 'DroppedFrameException' if frames are dropped
# but are present to illustrate how to check for dropped frames under other circumstances
# reference frames must have even seq nr
if ref_meta.sequence % 2 != 0:
print(f"cam: reference frame out of sequence")
break
# secondary frames must have odd seq nr
if meta.sequence % 2 == 0:
print(f"cam: secondary frame out of sequence")
break
# both frames seq nrs must be sequential
n3 = meta.sequence - ref_meta.sequence
if n3 != 1:
print(f"cam skipped {n3} frames")
break
n2 = ref_meta.sequence - i2
if n2 > 0:
print(f"cam skipped {n2} frames")
break
i2 = meta.sequence + 1
except Exception as e:
template = "An exception of type {0} occurred. Arguments:\n{1!r}"
message = template.format(type(e).__name__, e.args)
print(message)
HG and LG images
The GSENSE2020 sensor has functionality available for creating HDR images,
and therefore produces two images per frame: a high gain (HG) and a low gain (LG).
By default only the 'high gain' image is returned, however, it is possible to
retrieve the 'low gain' image instead by enabling the Rolling Shutter LG Image
V4L2 control.
Using the 'high gain' image with low values (under 1x) in the Gain
control can
result in wrong pixel saturation values (under 255).
In that case enable the 'low gain' image instead.
Invalid frames on stream start
The first X frames received from the GSENSE when it starts streaming are unstable. Some are very dark and some are very bright and some are in between. This is related to the sensor needing time to stabilize.
A delay has been added in the driver in order to address this issue, so that a
certain amount of frames will be discarted (not passed to the user).
Use the start up delay
V4L2 control to adjust the delay if necessary.