Let a tower choose its camera's auto-exposure target: --target
The Alvium recipe sets no IntensityControllerTarget, so a camera kept its default of 50 %, which burns out the sky over a dark forest; staeffelsberg's colour camera runs at 20 (set by hand in the Viewer), rietschen's Manta at 30. export_camera_profile.py --target <percent> now sets it for either family (IntensityControllerTarget, or ExposureAutoTarget on a Manta). Without the option nothing changes. For podrosche, whose migration plans 20 %. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
2faa4508d9
commit
fff437c13c
|
|
@ -696,6 +696,11 @@ property the Viewer workflow exists to provide: GenICam validity is stateful, so
|
|||
a hand-written XML can be individually plausible and collectively wrong. Here
|
||||
the camera is the judge, and anything it refused is printed rather than assumed.
|
||||
|
||||
`--target <percent>` sets the auto-exposure target, a tower's own choice: the
|
||||
Alvium recipe sets none, so the camera keeps its default of 50, which burns out
|
||||
the sky over a dark forest. Staeffelsberg runs at 20, rietschen at 30. The keep
|
||||
rule reads the target back from the camera, so nothing else has to change.
|
||||
|
||||
Read the summary line it prints - it is the number that decides whether the
|
||||
profile can be delivered at all:
|
||||
|
||||
|
|
|
|||
|
|
@ -193,6 +193,20 @@ def has_feature(cam, name):
|
|||
return False
|
||||
|
||||
|
||||
def with_target(recipe, family, target):
|
||||
"""The recipe with its auto-exposure target set to `target` percent.
|
||||
|
||||
A tower's own choice, not a recipe's: staeffelsberg's colour camera runs at
|
||||
20 %, rietschen's at 30, where the Alvium's default of 50 burnt out the sky.
|
||||
The keep rule reads the target back from the camera, so nothing else needs
|
||||
to know. An existing target entry is replaced; otherwise it goes last."""
|
||||
if target is None:
|
||||
return recipe
|
||||
name = "ExposureAutoTarget" if family == "gige" else "IntensityControllerTarget"
|
||||
out = [(n, v) for n, v in recipe if n != name]
|
||||
return out + [(name, float(target))]
|
||||
|
||||
|
||||
def recipe_family(cam):
|
||||
"""'gige' for a camera that only knows the older names, else 'alvium'."""
|
||||
if not has_feature(cam, "ExposureTime") and has_feature(cam, "ExposureTimeAbs"):
|
||||
|
|
@ -270,6 +284,9 @@ def main():
|
|||
ap.add_argument("--camera", default=None, help="camera id (default: the first real one)")
|
||||
ap.add_argument("--family", default="auto", choices=("auto", "alvium", "gige"),
|
||||
help="which recipe set (default: from the features the camera has)")
|
||||
ap.add_argument("--target", type=float, default=None,
|
||||
help="auto-exposure target in percent (default: the recipe's, or the "
|
||||
"camera's own where the recipe sets none)")
|
||||
ap.add_argument("--dry-run", action="store_true")
|
||||
args = ap.parse_args()
|
||||
|
||||
|
|
@ -294,7 +311,8 @@ def main():
|
|||
|
||||
with cam:
|
||||
family = recipe_family(cam) if args.family == "auto" else args.family
|
||||
recipe = (GIGE_RECIPES if family == "gige" else RECIPES)[args.profile]
|
||||
recipe = with_target((GIGE_RECIPES if family == "gige" else RECIPES)[args.profile],
|
||||
family, args.target)
|
||||
print(f"camera : {cam.get_id()} {cam.get_model()}")
|
||||
print(f"profile : {args.profile} ({family} recipe){' (dry run)' if args.dry_run else ''}")
|
||||
refused = []
|
||||
|
|
|
|||
Loading…
Reference in New Issue