flip before
This commit is contained in:
@@ -31,12 +31,12 @@
|
|||||||
# - File output with automatic sequential numbering
|
# - File output with automatic sequential numbering
|
||||||
# - IDS uEye camera source with intervalometer integration
|
# - IDS uEye camera source with intervalometer integration
|
||||||
# - Configurable camera settings (exposure, framerate, gain)
|
# - Configurable camera settings (exposure, framerate, gain)
|
||||||
# - Vertical linescan direction with 1900px output size
|
# - Horizontal linescan direction with 1900px output size, rotated 90° for vertical display
|
||||||
# - 3-pixel bottom crop for sensor cleanup
|
# - 3-pixel bottom crop for sensor cleanup
|
||||||
# - Dual output via tee element (display + file save)
|
# - Dual output via tee element (display + file save)
|
||||||
#
|
#
|
||||||
# Pipeline Architecture:
|
# Pipeline Architecture:
|
||||||
# idsueyesrc -> intervalometer -> videocrop -> queue -> linescan -> videoconvert -> autovideosink
|
# idsueyesrc -> intervalometer -> videocrop -> queue -> linescan -> videoflip -> videoconvert -> autovideosink
|
||||||
#
|
#
|
||||||
# Note: Files are saved via Python in the rollover signal callback, not through the pipeline
|
# Note: Files are saved via Python in the rollover signal callback, not through the pipeline
|
||||||
#
|
#
|
||||||
@@ -186,12 +186,16 @@ def on_rollover(linescan, buffer):
|
|||||||
print(f"[ROL LOVER WARNING] Unsupported format {format_str}, saving as-is")
|
print(f"[ROL LOVER WARNING] Unsupported format {format_str}, saving as-is")
|
||||||
data = data.reshape((height, width, -1))
|
data = data.reshape((height, width, -1))
|
||||||
|
|
||||||
# Create PIL Image and save
|
# Create PIL Image
|
||||||
if channels == 1:
|
if channels == 1:
|
||||||
img = Image.fromarray(data, mode='L')
|
img = Image.fromarray(data, mode='L')
|
||||||
else:
|
else:
|
||||||
img = Image.fromarray(data, mode='RGB')
|
img = Image.fromarray(data, mode='RGB')
|
||||||
|
|
||||||
|
# Rotate 90 degrees clockwise to display horizontally-scanned image vertically
|
||||||
|
img = img.transpose(Image.ROTATE_270)
|
||||||
|
|
||||||
|
# Save rotated image
|
||||||
if file_format == 'png':
|
if file_format == 'png':
|
||||||
img.save(filename, 'PNG')
|
img.save(filename, 'PNG')
|
||||||
else:
|
else:
|
||||||
@@ -317,7 +321,8 @@ Examples:
|
|||||||
queue1 = Gst.ElementFactory.make("queue", "queue1")
|
queue1 = Gst.ElementFactory.make("queue", "queue1")
|
||||||
linescan = Gst.ElementFactory.make("linescan", "linescan")
|
linescan = Gst.ElementFactory.make("linescan", "linescan")
|
||||||
|
|
||||||
# Display output
|
# Display output with rotation
|
||||||
|
videoflip = Gst.ElementFactory.make("videoflip", "flip")
|
||||||
videoconvert = Gst.ElementFactory.make("videoconvert", "convert")
|
videoconvert = Gst.ElementFactory.make("videoconvert", "convert")
|
||||||
videosink = Gst.ElementFactory.make("autovideosink", "videosink")
|
videosink = Gst.ElementFactory.make("autovideosink", "videosink")
|
||||||
|
|
||||||
@@ -329,6 +334,7 @@ Examples:
|
|||||||
'videocrop': videocrop,
|
'videocrop': videocrop,
|
||||||
'queue1': queue1,
|
'queue1': queue1,
|
||||||
'linescan': linescan,
|
'linescan': linescan,
|
||||||
|
'videoflip': videoflip,
|
||||||
'videoconvert': videoconvert,
|
'videoconvert': videoconvert,
|
||||||
'videosink': videosink
|
'videosink': videosink
|
||||||
}
|
}
|
||||||
@@ -364,14 +370,14 @@ Examples:
|
|||||||
|
|
||||||
# Set camera parameters based on mode
|
# Set camera parameters based on mode
|
||||||
if args.mode == 'day':
|
if args.mode == 'day':
|
||||||
exposure = 0.4
|
exposure = 0.02
|
||||||
gain = 0
|
gain = 0
|
||||||
else: # night
|
else: # night
|
||||||
exposure = 5.25
|
exposure = 5.25
|
||||||
gain = 65
|
gain = 65
|
||||||
|
|
||||||
framerate = 200 # Same for both modes
|
framerate = 200 # Same for both modes
|
||||||
device_id = 2
|
device_id = 1
|
||||||
|
|
||||||
source.set_property("exposure", exposure)
|
source.set_property("exposure", exposure)
|
||||||
source.set_property("framerate", framerate)
|
source.set_property("framerate", framerate)
|
||||||
@@ -386,7 +392,7 @@ Examples:
|
|||||||
intervalometer.set_property("enabled", True)
|
intervalometer.set_property("enabled", True)
|
||||||
intervalometer.set_property("camera-element", "source")
|
intervalometer.set_property("camera-element", "source")
|
||||||
intervalometer.set_property("ramp-rate", "slow")
|
intervalometer.set_property("ramp-rate", "slow")
|
||||||
intervalometer.set_property("update-interval", 500)
|
intervalometer.set_property("update-interval", 1000)
|
||||||
intervalometer.set_property("brightness-deadband", 10.0)
|
intervalometer.set_property("brightness-deadband", 10.0)
|
||||||
intervalometer.set_property("gain-max", 82)
|
intervalometer.set_property("gain-max", 82)
|
||||||
intervalometer.set_property("target-brightness", 80.0)
|
intervalometer.set_property("target-brightness", 80.0)
|
||||||
@@ -396,12 +402,15 @@ Examples:
|
|||||||
videocrop.set_property("bottom", 3)
|
videocrop.set_property("bottom", 3)
|
||||||
|
|
||||||
# Configure linescan
|
# Configure linescan
|
||||||
linescan.set_property("direction", 1) # vertical
|
linescan.set_property("direction", 0) # horizontal
|
||||||
linescan.set_property("output-size", 1900)
|
linescan.set_property("output-size", 1900)
|
||||||
|
|
||||||
|
# Configure videoflip to rotate 90 degrees clockwise (method=1 is clockwise)
|
||||||
|
videoflip.set_property("method", 1)
|
||||||
|
|
||||||
if args.debug:
|
if args.debug:
|
||||||
print(f"Linescan: direction=vertical, output-size=1900")
|
print(f"Linescan: direction=horizontal, output-size=1900")
|
||||||
print(f"Files will be saved via rollover callback (not through pipeline)")
|
print(f"Display and files rotated 90° clockwise for vertical presentation")
|
||||||
|
|
||||||
# Connect rollover signal - files are saved in the callback
|
# Connect rollover signal - files are saved in the callback
|
||||||
linescan.connect("rollover", on_rollover)
|
linescan.connect("rollover", on_rollover)
|
||||||
@@ -412,6 +421,7 @@ Examples:
|
|||||||
pipeline.add(videocrop)
|
pipeline.add(videocrop)
|
||||||
pipeline.add(queue1)
|
pipeline.add(queue1)
|
||||||
pipeline.add(linescan)
|
pipeline.add(linescan)
|
||||||
|
pipeline.add(videoflip)
|
||||||
pipeline.add(videoconvert)
|
pipeline.add(videoconvert)
|
||||||
pipeline.add(videosink)
|
pipeline.add(videosink)
|
||||||
|
|
||||||
@@ -428,8 +438,11 @@ Examples:
|
|||||||
if not queue1.link(linescan):
|
if not queue1.link(linescan):
|
||||||
print("ERROR: Could not link queue1 to linescan")
|
print("ERROR: Could not link queue1 to linescan")
|
||||||
return -1
|
return -1
|
||||||
if not linescan.link(videoconvert):
|
if not linescan.link(videoflip):
|
||||||
print("ERROR: Could not link linescan to videoconvert")
|
print("ERROR: Could not link linescan to videoflip")
|
||||||
|
return -1
|
||||||
|
if not videoflip.link(videoconvert):
|
||||||
|
print("ERROR: Could not link videoflip to videoconvert")
|
||||||
return -1
|
return -1
|
||||||
if not videoconvert.link(videosink):
|
if not videoconvert.link(videosink):
|
||||||
print("ERROR: Could not link videoconvert to videosink")
|
print("ERROR: Could not link videoconvert to videosink")
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ Sensor digital gain=0
|
|||||||
|
|
||||||
|
|
||||||
[Image size]
|
[Image size]
|
||||||
Start X=524
|
Start X=0
|
||||||
Start Y=450
|
Start Y=950
|
||||||
Start X absolute=1
|
Start X absolute=1
|
||||||
Start Y absolute=1
|
Start Y absolute=1
|
||||||
Width=256
|
Width=2456
|
||||||
Height=1008
|
Height=100
|
||||||
Binning=0
|
Binning=0
|
||||||
Subsampling=0
|
Subsampling=0
|
||||||
|
|
||||||
@@ -56,8 +56,8 @@ Manual gain=0
|
|||||||
[Timing]
|
[Timing]
|
||||||
Pixelclock=474
|
Pixelclock=474
|
||||||
Extended pixelclock range=0
|
Extended pixelclock range=0
|
||||||
Framerate=169.724771
|
Framerate=1016.483516
|
||||||
Exposure=5.851568
|
Exposure=0.943460
|
||||||
Long exposure=0
|
Long exposure=0
|
||||||
Dual exposure ratio=0
|
Dual exposure ratio=0
|
||||||
|
|
||||||
@@ -152,11 +152,11 @@ Brightness control once=0
|
|||||||
Brightness reference=128
|
Brightness reference=128
|
||||||
Brightness speed=50
|
Brightness speed=50
|
||||||
Brightness max gain=100
|
Brightness max gain=100
|
||||||
Brightness max exposure=5.851568
|
Brightness max exposure=0.943460
|
||||||
Brightness Aoi Left=524
|
Brightness Aoi Left=0
|
||||||
Brightness Aoi Top=450
|
Brightness Aoi Top=950
|
||||||
Brightness Aoi Width=256
|
Brightness Aoi Width=2456
|
||||||
Brightness Aoi Height=1008
|
Brightness Aoi Height=100
|
||||||
Brightness Hysteresis=2
|
Brightness Hysteresis=2
|
||||||
AutoImageControlMode=2
|
AutoImageControlMode=2
|
||||||
AutoImageControlPeakWhiteChannel=0
|
AutoImageControlPeakWhiteChannel=0
|
||||||
@@ -172,10 +172,10 @@ Auto WB offsetB=0
|
|||||||
Auto WB gainMin=0
|
Auto WB gainMin=0
|
||||||
Auto WB gainMax=100
|
Auto WB gainMax=100
|
||||||
Auto WB speed=50
|
Auto WB speed=50
|
||||||
Auto WB Aoi Left=524
|
Auto WB Aoi Left=0
|
||||||
Auto WB Aoi Top=450
|
Auto WB Aoi Top=950
|
||||||
Auto WB Aoi Width=256
|
Auto WB Aoi Width=2456
|
||||||
Auto WB Aoi Height=1008
|
Auto WB Aoi Height=100
|
||||||
Auto WB Once=0
|
Auto WB Once=0
|
||||||
Auto WB Hysteresis=2
|
Auto WB Hysteresis=2
|
||||||
Brightness Skip Frames Trigger Mode=4
|
Brightness Skip Frames Trigger Mode=4
|
||||||
|
|||||||
@@ -46,4 +46,4 @@ Write-Host "Launching linescan pipeline in $Mode mode..."
|
|||||||
Write-Host ""
|
Write-Host ""
|
||||||
|
|
||||||
# All configuration is handled by launch-ids.py defaults
|
# All configuration is handled by launch-ids.py defaults
|
||||||
uv run .\scripts\launch-ids.py --mode $Mode
|
uv run .\scripts\launch-ids.py --mode $Mode --device-id 2
|
||||||
Reference in New Issue
Block a user