Chore: rename api->camera-management-api and web->management-dashboard-web-app; update compose, ignore, README references

This commit is contained in:
Alireza Vaezi
2025-08-07 22:07:25 -04:00
parent 28dab3a366
commit fc2da16728
281 changed files with 19 additions and 19 deletions

View File

@@ -0,0 +1,4 @@
Log file created at: 2025/07/28 15:32:15
Running on machine: vision
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
E0728 15:32:15.057651 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023

View File

@@ -0,0 +1,4 @@
Log file created at: 2025/07/28 15:32:33
Running on machine: vision
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
E0728 15:32:33.490923 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023

View File

@@ -0,0 +1,4 @@
Log file created at: 2025/07/28 15:32:34
Running on machine: vision
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
E0728 15:32:34.649940 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023

View File

@@ -0,0 +1,4 @@
Log file created at: 2025/07/28 15:32:39
Running on machine: vision
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
E0728 15:32:39.753448 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023

View File

@@ -0,0 +1,4 @@
Log file created at: 2025/07/28 15:32:45
Running on machine: vision
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
E0728 15:32:45.492905 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023

View File

@@ -0,0 +1,4 @@
Log file created at: 2025/07/28 15:33:40
Running on machine: vision
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
E0728 15:33:40.702630 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023

View File

@@ -0,0 +1,4 @@
Log file created at: 2025/07/28 15:34:18
Running on machine: vision
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
E0728 15:34:18.442386 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023

View File

@@ -0,0 +1,4 @@
Log file created at: 2025/07/28 15:34:28
Running on machine: vision
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
E0728 15:34:28.207051 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023

View File

@@ -0,0 +1,4 @@
Log file created at: 2025/07/28 15:34:53
Running on machine: vision
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
E0728 15:34:53.315912 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023

View File

@@ -0,0 +1,4 @@
Log file created at: 2025/07/28 15:35:00
Running on machine: vision
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
E0728 15:35:00.929268 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023

View File

@@ -0,0 +1,4 @@
Log file created at: 2025/07/28 15:35:32
Running on machine: vision
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
E0728 15:35:32.169682 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023

View File

@@ -0,0 +1,4 @@
Log file created at: 2025/07/28 15:35:34
Running on machine: vision
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
E0728 15:35:34.519351 191852 MVCAMAPI.cpp:369] CameraInit Failed, err:32774,Version:2.1.0.49,FriendlyName:Blower-Yield-Cam,SN:054012620023

View File

@@ -0,0 +1,291 @@
# coding=utf-8
"""
Simple GigE Camera Capture Script
Captures 10 images every 200 milliseconds and saves them to the images directory.
"""
import os
import time
import numpy as np
import cv2
import platform
from datetime import datetime
import sys
sys.path.append("./python demo")
import mvsdk
def is_camera_ready_for_capture():
"""
Check if camera is ready for capture.
Returns: (ready: bool, message: str, camera_info: object or None)
"""
try:
# Initialize SDK
mvsdk.CameraSdkInit(1)
# Enumerate cameras
DevList = mvsdk.CameraEnumerateDevice()
if len(DevList) < 1:
return False, "No cameras found", None
DevInfo = DevList[0]
# Check if already opened
try:
if mvsdk.CameraIsOpened(DevInfo):
return False, f"Camera '{DevInfo.GetFriendlyName()}' is already opened by another process", DevInfo
except:
pass # Some cameras might not support this check
# Try to initialize
try:
hCamera = mvsdk.CameraInit(DevInfo, -1, -1)
# Quick capture test
try:
# Basic setup
mvsdk.CameraSetTriggerMode(hCamera, 0)
mvsdk.CameraPlay(hCamera)
# Try to get one frame with short timeout
pRawData, FrameHead = mvsdk.CameraGetImageBuffer(hCamera, 500) # 0.5 second timeout
mvsdk.CameraReleaseImageBuffer(hCamera, pRawData)
# Success - close and return
mvsdk.CameraUnInit(hCamera)
return True, f"Camera '{DevInfo.GetFriendlyName()}' is ready for capture", DevInfo
except mvsdk.CameraException as e:
mvsdk.CameraUnInit(hCamera)
if e.error_code == mvsdk.CAMERA_STATUS_TIME_OUT:
return False, "Camera timeout - may be busy or not streaming properly", DevInfo
else:
return False, f"Camera capture test failed: {e.message}", DevInfo
except mvsdk.CameraException as e:
if e.error_code == mvsdk.CAMERA_STATUS_DEVICE_IS_OPENED:
return False, f"Camera '{DevInfo.GetFriendlyName()}' is already in use", DevInfo
elif e.error_code == mvsdk.CAMERA_STATUS_ACCESS_DENY:
return False, f"Access denied to camera '{DevInfo.GetFriendlyName()}'", DevInfo
else:
return False, f"Camera initialization failed: {e.message}", DevInfo
except Exception as e:
return False, f"Camera check failed: {str(e)}", None
def get_camera_ranges(hCamera):
"""
Get the available ranges for camera settings
"""
try:
# Get exposure time range
exp_min, exp_max, exp_step = mvsdk.CameraGetExposureTimeRange(hCamera)
print(f"Exposure time range: {exp_min:.1f} - {exp_max:.1f} μs (step: {exp_step:.1f})")
# Get analog gain range
gain_min, gain_max, gain_step = mvsdk.CameraGetAnalogGainXRange(hCamera)
print(f"Analog gain range: {gain_min:.2f} - {gain_max:.2f}x (step: {gain_step:.3f})")
return (exp_min, exp_max, exp_step), (gain_min, gain_max, gain_step)
except Exception as e:
print(f"Could not get camera ranges: {e}")
return None, None
def capture_images(exposure_time_us=2000, analog_gain=1.0):
"""
Main function to capture images from GigE camera
Parameters:
- exposure_time_us: Exposure time in microseconds (default: 2000 = 2ms)
- analog_gain: Analog gain multiplier (default: 1.0)
"""
# Check if camera is ready for capture
print("Checking camera availability...")
ready, message, camera_info = is_camera_ready_for_capture()
if not ready:
print(f"❌ Camera not ready: {message}")
print("\nPossible solutions:")
print("- Close any other camera applications (preview software, etc.)")
print("- Check camera connection and power")
print("- Wait a moment and try again")
return False
print(f"{message}")
# Initialize SDK (already done in status check, but ensure it's ready)
try:
mvsdk.CameraSdkInit(1) # Initialize SDK with English language
except Exception as e:
print(f"SDK initialization failed: {e}")
return False
# Enumerate cameras
DevList = mvsdk.CameraEnumerateDevice()
nDev = len(DevList)
if nDev < 1:
print("No camera was found!")
return False
print(f"Found {nDev} camera(s):")
for i, DevInfo in enumerate(DevList):
print(f"{i}: {DevInfo.GetFriendlyName()} {DevInfo.GetPortType()}")
# Select camera (use first one if only one available)
camera_index = 0 if nDev == 1 else int(input("Select camera index: "))
DevInfo = DevList[camera_index]
print(f"Selected camera: {DevInfo.GetFriendlyName()}")
# Initialize camera
hCamera = 0
try:
hCamera = mvsdk.CameraInit(DevInfo, -1, -1)
print("Camera initialized successfully")
except mvsdk.CameraException as e:
print(f"CameraInit Failed({e.error_code}): {e.message}")
return False
try:
# Get camera capabilities
cap = mvsdk.CameraGetCapability(hCamera)
# Check if it's a mono or color camera
monoCamera = cap.sIspCapacity.bMonoSensor != 0
print(f"Camera type: {'Monochrome' if monoCamera else 'Color'}")
# Get camera ranges
exp_range, gain_range = get_camera_ranges(hCamera)
# Set output format
if monoCamera:
mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_MONO8)
else:
mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_BGR8)
# Set camera to continuous capture mode
mvsdk.CameraSetTriggerMode(hCamera, 0)
# Set manual exposure with improved control
mvsdk.CameraSetAeState(hCamera, 0) # Disable auto exposure
# Clamp exposure time to valid range
if exp_range:
exp_min, exp_max, exp_step = exp_range
exposure_time_us = max(exp_min, min(exp_max, exposure_time_us))
mvsdk.CameraSetExposureTime(hCamera, exposure_time_us)
print(f"Set exposure time: {exposure_time_us/1000:.1f}ms")
# Set analog gain
if gain_range:
gain_min, gain_max, gain_step = gain_range
analog_gain = max(gain_min, min(gain_max, analog_gain))
try:
mvsdk.CameraSetAnalogGainX(hCamera, analog_gain)
print(f"Set analog gain: {analog_gain:.2f}x")
except Exception as e:
print(f"Could not set analog gain: {e}")
# Start camera
mvsdk.CameraPlay(hCamera)
print("Camera started")
# Calculate frame buffer size
FrameBufferSize = cap.sResolutionRange.iWidthMax * cap.sResolutionRange.iHeightMax * (1 if monoCamera else 3)
# Allocate frame buffer
pFrameBuffer = mvsdk.CameraAlignMalloc(FrameBufferSize, 16)
# Create images directory if it doesn't exist
if not os.path.exists("images"):
os.makedirs("images")
print("Starting image capture...")
print("Capturing 10 images with 200ms intervals...")
# Capture 10 images
for i in range(10):
try:
# Get image from camera (timeout: 2000ms)
pRawData, FrameHead = mvsdk.CameraGetImageBuffer(hCamera, 2000)
# Process the raw image data
mvsdk.CameraImageProcess(hCamera, pRawData, pFrameBuffer, FrameHead)
# Release the raw data buffer
mvsdk.CameraReleaseImageBuffer(hCamera, pRawData)
# Handle Windows image flip (images are upside down on Windows)
if platform.system() == "Windows":
mvsdk.CameraFlipFrameBuffer(pFrameBuffer, FrameHead, 1)
# Convert to numpy array for OpenCV
frame_data = (mvsdk.c_ubyte * FrameHead.uBytes).from_address(pFrameBuffer)
frame = np.frombuffer(frame_data, dtype=np.uint8)
# Reshape based on camera type
if FrameHead.uiMediaType == mvsdk.CAMERA_MEDIA_TYPE_MONO8:
frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth))
else:
frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth, 3))
# Generate filename with timestamp
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")[:-3] # milliseconds
filename = f"images/image_{i+1:02d}_{timestamp}.jpg"
# Save image using OpenCV
success = cv2.imwrite(filename, frame)
if success:
print(f"Image {i+1}/10 saved: {filename} ({FrameHead.iWidth}x{FrameHead.iHeight})")
else:
print(f"Failed to save image {i+1}/10")
# Wait 200ms before next capture (except for the last image)
if i < 9:
time.sleep(0.2)
except mvsdk.CameraException as e:
print(f"Failed to capture image {i+1}/10 ({e.error_code}): {e.message}")
continue
print("Image capture completed!")
# Cleanup
mvsdk.CameraAlignFree(pFrameBuffer)
finally:
# Close camera
mvsdk.CameraUnInit(hCamera)
print("Camera closed")
return True
if __name__ == "__main__":
print("GigE Camera Image Capture Script")
print("=" * 40)
print("Note: If images are overexposed, you can adjust the exposure settings:")
print("- Lower exposure_time_us for darker images (e.g., 1000-5000)")
print("- Lower analog_gain for less amplification (e.g., 0.5-2.0)")
print()
# for cracker
# You can adjust these values to fix overexposure:
success = capture_images(exposure_time_us=6000, analog_gain=16.0) # 2ms exposure (much lower than default 30ms) # 1x gain (no amplification)
# for blower
success = capture_images(exposure_time_us=1000, analog_gain=3.5) # 2ms exposure (much lower than default 30ms) # 1x gain (no amplification)
if success:
print("\nCapture completed successfully!")
print("Images saved in the 'images' directory")
else:
print("\nCapture failed!")
input("Press Enter to exit...")

View File

@@ -0,0 +1,439 @@
# coding=utf-8
import cv2
import numpy as np
import platform
import time
import threading
from datetime import datetime
import os
import sys
# Add the python demo directory to path to import mvsdk
sys.path.append("python demo")
import mvsdk
class CameraVideoRecorder:
def __init__(self):
self.hCamera = 0
self.pFrameBuffer = 0
self.cap = None
self.monoCamera = False
self.recording = False
self.video_writer = None
self.frame_count = 0
self.start_time = None
def list_cameras(self):
"""List all available cameras"""
try:
# Initialize SDK
mvsdk.CameraSdkInit(1)
except Exception as e:
print(f"SDK initialization failed: {e}")
return []
# Enumerate cameras
DevList = mvsdk.CameraEnumerateDevice()
nDev = len(DevList)
if nDev < 1:
print("No cameras found!")
return []
print(f"\nFound {nDev} camera(s):")
cameras = []
for i, DevInfo in enumerate(DevList):
camera_info = {"index": i, "name": DevInfo.GetFriendlyName(), "port_type": DevInfo.GetPortType(), "serial": DevInfo.GetSn(), "dev_info": DevInfo}
cameras.append(camera_info)
print(f"{i}: {camera_info['name']} ({camera_info['port_type']}) - SN: {camera_info['serial']}")
return cameras
def initialize_camera(self, dev_info, exposure_ms=1.0, gain=3.5, target_fps=3.0):
"""Initialize camera with specified settings"""
self.target_fps = target_fps
try:
# Initialize camera
self.hCamera = mvsdk.CameraInit(dev_info, -1, -1)
print(f"Camera initialized successfully")
# Get camera capabilities
self.cap = mvsdk.CameraGetCapability(self.hCamera)
self.monoCamera = self.cap.sIspCapacity.bMonoSensor != 0
print(f"Camera type: {'Monochrome' if self.monoCamera else 'Color'}")
# Set output format
if self.monoCamera:
mvsdk.CameraSetIspOutFormat(self.hCamera, mvsdk.CAMERA_MEDIA_TYPE_MONO8)
else:
mvsdk.CameraSetIspOutFormat(self.hCamera, mvsdk.CAMERA_MEDIA_TYPE_BGR8)
# Calculate RGB buffer size
FrameBufferSize = self.cap.sResolutionRange.iWidthMax * self.cap.sResolutionRange.iHeightMax * (1 if self.monoCamera else 3)
# Allocate RGB buffer
self.pFrameBuffer = mvsdk.CameraAlignMalloc(FrameBufferSize, 16)
# Set camera to continuous capture mode
mvsdk.CameraSetTriggerMode(self.hCamera, 0)
# Set manual exposure
mvsdk.CameraSetAeState(self.hCamera, 0) # Disable auto exposure
exposure_time_us = exposure_ms * 1000 # Convert ms to microseconds
# Get exposure range and clamp value
try:
exp_min, exp_max, exp_step = mvsdk.CameraGetExposureTimeRange(self.hCamera)
exposure_time_us = max(exp_min, min(exp_max, exposure_time_us))
print(f"Exposure range: {exp_min:.1f} - {exp_max:.1f} μs")
except Exception as e:
print(f"Could not get exposure range: {e}")
mvsdk.CameraSetExposureTime(self.hCamera, exposure_time_us)
print(f"Set exposure time: {exposure_time_us/1000:.1f}ms")
# Set analog gain
try:
gain_min, gain_max, gain_step = mvsdk.CameraGetAnalogGainXRange(self.hCamera)
gain = max(gain_min, min(gain_max, gain))
mvsdk.CameraSetAnalogGainX(self.hCamera, gain)
print(f"Set analog gain: {gain:.2f}x (range: {gain_min:.2f} - {gain_max:.2f})")
except Exception as e:
print(f"Could not set analog gain: {e}")
# Start camera
mvsdk.CameraPlay(self.hCamera)
print("Camera started successfully")
return True
except mvsdk.CameraException as e:
print(f"Camera initialization failed({e.error_code}): {e.message}")
return False
def start_recording(self, output_filename=None):
"""Start video recording"""
if self.recording:
print("Already recording!")
return False
if not output_filename:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
output_filename = f"video_{timestamp}.avi"
# Create output directory if it doesn't exist
os.makedirs(os.path.dirname(output_filename) if os.path.dirname(output_filename) else ".", exist_ok=True)
# Get first frame to determine video properties
try:
pRawData, FrameHead = mvsdk.CameraGetImageBuffer(self.hCamera, 2000)
mvsdk.CameraImageProcess(self.hCamera, pRawData, self.pFrameBuffer, FrameHead)
mvsdk.CameraReleaseImageBuffer(self.hCamera, pRawData)
# Handle Windows frame flipping
if platform.system() == "Windows":
mvsdk.CameraFlipFrameBuffer(self.pFrameBuffer, FrameHead, 1)
# Convert to numpy array
frame_data = (mvsdk.c_ubyte * FrameHead.uBytes).from_address(self.pFrameBuffer)
frame = np.frombuffer(frame_data, dtype=np.uint8)
if self.monoCamera:
frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth))
# Convert mono to BGR for video writer
frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)
else:
frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth, 3))
except mvsdk.CameraException as e:
print(f"Failed to get initial frame: {e.message}")
return False
# Initialize video writer
fourcc = cv2.VideoWriter_fourcc(*"XVID")
fps = getattr(self, "target_fps", 3.0) # Use configured FPS or default to 3.0
frame_size = (FrameHead.iWidth, FrameHead.iHeight)
self.video_writer = cv2.VideoWriter(output_filename, fourcc, fps, frame_size)
if not self.video_writer.isOpened():
print(f"Failed to open video writer for {output_filename}")
return False
self.recording = True
self.frame_count = 0
self.start_time = time.time()
self.output_filename = output_filename
print(f"Started recording to: {output_filename}")
print(f"Frame size: {frame_size}, FPS: {fps}")
print("Press 'q' to stop recording...")
return True
def stop_recording(self):
"""Stop video recording"""
if not self.recording:
print("Not currently recording!")
return False
self.recording = False
if self.video_writer:
self.video_writer.release()
self.video_writer = None
duration = time.time() - self.start_time if self.start_time else 0
avg_fps = self.frame_count / duration if duration > 0 else 0
print(f"\nRecording stopped!")
print(f"Saved: {self.output_filename}")
print(f"Frames recorded: {self.frame_count}")
print(f"Duration: {duration:.1f} seconds")
print(f"Average FPS: {avg_fps:.1f}")
return True
def record_loop(self):
"""Main recording loop"""
if not self.recording:
return
print("Recording... Press 'q' in the preview window to stop")
while self.recording:
try:
# Get frame from camera
pRawData, FrameHead = mvsdk.CameraGetImageBuffer(self.hCamera, 200)
mvsdk.CameraImageProcess(self.hCamera, pRawData, self.pFrameBuffer, FrameHead)
mvsdk.CameraReleaseImageBuffer(self.hCamera, pRawData)
# Handle Windows frame flipping
if platform.system() == "Windows":
mvsdk.CameraFlipFrameBuffer(self.pFrameBuffer, FrameHead, 1)
# Convert to numpy array
frame_data = (mvsdk.c_ubyte * FrameHead.uBytes).from_address(self.pFrameBuffer)
frame = np.frombuffer(frame_data, dtype=np.uint8)
if self.monoCamera:
frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth))
frame_bgr = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)
else:
frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth, 3))
frame_bgr = frame
# Write every frame to video (FPS is controlled by video file playback rate)
if self.video_writer and self.recording:
self.video_writer.write(frame_bgr)
self.frame_count += 1
# Show preview (resized for display)
display_frame = cv2.resize(frame_bgr, (640, 480), interpolation=cv2.INTER_LINEAR)
# Add small delay to control capture rate based on target FPS
target_fps = getattr(self, "target_fps", 3.0)
time.sleep(1.0 / target_fps)
# Add recording indicator
cv2.putText(display_frame, f"REC - Frame: {self.frame_count}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
cv2.imshow("Camera Recording - Press 'q' to stop", display_frame)
# Check for quit key
if cv2.waitKey(1) & 0xFF == ord("q"):
self.stop_recording()
break
except mvsdk.CameraException as e:
if e.error_code != mvsdk.CAMERA_STATUS_TIME_OUT:
print(f"Camera error: {e.message}")
break
def cleanup(self):
"""Clean up resources"""
if self.recording:
self.stop_recording()
if self.video_writer:
self.video_writer.release()
if self.hCamera > 0:
mvsdk.CameraUnInit(self.hCamera)
self.hCamera = 0
if self.pFrameBuffer:
mvsdk.CameraAlignFree(self.pFrameBuffer)
self.pFrameBuffer = 0
cv2.destroyAllWindows()
def interactive_menu():
"""Interactive menu for camera operations"""
recorder = CameraVideoRecorder()
try:
# List available cameras
cameras = recorder.list_cameras()
if not cameras:
return
# Select camera
if len(cameras) == 1:
selected_camera = cameras[0]
print(f"\nUsing camera: {selected_camera['name']}")
else:
while True:
try:
choice = int(input(f"\nSelect camera (0-{len(cameras)-1}): "))
if 0 <= choice < len(cameras):
selected_camera = cameras[choice]
break
else:
print("Invalid selection!")
except ValueError:
print("Please enter a valid number!")
# Get camera settings from user
print(f"\nCamera Settings:")
try:
exposure = float(input("Enter exposure time in ms (default 1.0): ") or "1.0")
gain = float(input("Enter gain value (default 3.5): ") or "3.5")
fps = float(input("Enter target FPS (default 3.0): ") or "3.0")
except ValueError:
print("Using default values: exposure=1.0ms, gain=3.5x, fps=3.0")
exposure, gain, fps = 1.0, 3.5, 3.0
# Initialize camera with specified settings
print(f"\nInitializing camera with:")
print(f"- Exposure: {exposure}ms")
print(f"- Gain: {gain}x")
print(f"- Target FPS: {fps}")
if not recorder.initialize_camera(selected_camera["dev_info"], exposure_ms=exposure, gain=gain, target_fps=fps):
return
# Menu loop
while True:
print(f"\n{'='*50}")
print("Camera Video Recorder Menu")
print(f"{'='*50}")
print("1. Start Recording")
print("2. List Camera Info")
print("3. Test Camera (Live Preview)")
print("4. Exit")
try:
choice = input("\nSelect option (1-4): ").strip()
if choice == "1":
# Start recording
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
output_file = f"videos/camera_recording_{timestamp}.avi"
# Create videos directory
os.makedirs("videos", exist_ok=True)
if recorder.start_recording(output_file):
recorder.record_loop()
elif choice == "2":
# Show camera info
print(f"\nCamera Information:")
print(f"Name: {selected_camera['name']}")
print(f"Port Type: {selected_camera['port_type']}")
print(f"Serial Number: {selected_camera['serial']}")
print(f"Type: {'Monochrome' if recorder.monoCamera else 'Color'}")
elif choice == "3":
# Live preview
print("\nLive Preview - Press 'q' to stop")
preview_loop(recorder)
elif choice == "4":
print("Exiting...")
break
else:
print("Invalid option! Please select 1-4.")
except KeyboardInterrupt:
print("\nReturning to menu...")
continue
except KeyboardInterrupt:
print("\nInterrupted by user")
except Exception as e:
print(f"Error: {e}")
import traceback
traceback.print_exc()
finally:
recorder.cleanup()
print("Cleanup completed")
def preview_loop(recorder):
"""Live preview without recording"""
print("Live preview mode - Press 'q' to return to menu")
while True:
try:
# Get frame from camera
pRawData, FrameHead = mvsdk.CameraGetImageBuffer(recorder.hCamera, 200)
mvsdk.CameraImageProcess(recorder.hCamera, pRawData, recorder.pFrameBuffer, FrameHead)
mvsdk.CameraReleaseImageBuffer(recorder.hCamera, pRawData)
# Handle Windows frame flipping
if platform.system() == "Windows":
mvsdk.CameraFlipFrameBuffer(recorder.pFrameBuffer, FrameHead, 1)
# Convert to numpy array
frame_data = (mvsdk.c_ubyte * FrameHead.uBytes).from_address(recorder.pFrameBuffer)
frame = np.frombuffer(frame_data, dtype=np.uint8)
if recorder.monoCamera:
frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth))
frame_bgr = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)
else:
frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth, 3))
frame_bgr = frame
# Show preview (resized for display)
display_frame = cv2.resize(frame_bgr, (640, 480), interpolation=cv2.INTER_LINEAR)
# Add info overlay
cv2.putText(display_frame, f"PREVIEW - {FrameHead.iWidth}x{FrameHead.iHeight}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
cv2.putText(display_frame, "Press 'q' to return to menu", (10, display_frame.shape[0] - 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
cv2.imshow("Camera Preview", display_frame)
# Check for quit key
if cv2.waitKey(1) & 0xFF == ord("q"):
cv2.destroyWindow("Camera Preview")
break
except mvsdk.CameraException as e:
if e.error_code != mvsdk.CAMERA_STATUS_TIME_OUT:
print(f"Camera error: {e.message}")
break
def main():
print("Camera Video Recorder")
print("====================")
print("This script allows you to:")
print("- List all available cameras")
print("- Record videos with custom exposure (1ms), gain (3.5x), and FPS (3.0) settings")
print("- Save videos with timestamps")
print("- Stop recording anytime with 'q' key")
print()
interactive_menu()
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,6 @@
def main():
print("Hello from usda-vision-cameras!")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,197 @@
#coding=utf-8
"""
Test script to help find optimal exposure settings for your GigE camera.
This script captures a single test image with different exposure settings.
"""
import os
import sys
import mvsdk
import numpy as np
import cv2
import platform
from datetime import datetime
# Add the python demo directory to path
sys.path.append('./python demo')
def test_exposure_settings():
"""
Test different exposure settings to find optimal values
"""
# Initialize SDK
try:
mvsdk.CameraSdkInit(1)
print("SDK initialized successfully")
except Exception as e:
print(f"SDK initialization failed: {e}")
return False
# Enumerate cameras
DevList = mvsdk.CameraEnumerateDevice()
nDev = len(DevList)
if nDev < 1:
print("No camera was found!")
return False
print(f"Found {nDev} camera(s):")
for i, DevInfo in enumerate(DevList):
print(f" {i}: {DevInfo.GetFriendlyName()} ({DevInfo.GetPortType()})")
# Use first camera
DevInfo = DevList[0]
print(f"\nSelected camera: {DevInfo.GetFriendlyName()}")
# Initialize camera
try:
hCamera = mvsdk.CameraInit(DevInfo, -1, -1)
print("Camera initialized successfully")
except mvsdk.CameraException as e:
print(f"CameraInit Failed({e.error_code}): {e.message}")
return False
try:
# Get camera capabilities
cap = mvsdk.CameraGetCapability(hCamera)
monoCamera = (cap.sIspCapacity.bMonoSensor != 0)
print(f"Camera type: {'Monochrome' if monoCamera else 'Color'}")
# Get camera ranges
try:
exp_min, exp_max, exp_step = mvsdk.CameraGetExposureTimeRange(hCamera)
print(f"Exposure time range: {exp_min:.1f} - {exp_max:.1f} μs")
gain_min, gain_max, gain_step = mvsdk.CameraGetAnalogGainXRange(hCamera)
print(f"Analog gain range: {gain_min:.2f} - {gain_max:.2f}x")
except Exception as e:
print(f"Could not get camera ranges: {e}")
exp_min, exp_max = 100, 100000
gain_min, gain_max = 1.0, 4.0
# Set output format
if monoCamera:
mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_MONO8)
else:
mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_BGR8)
# Set camera to continuous capture mode
mvsdk.CameraSetTriggerMode(hCamera, 0)
mvsdk.CameraSetAeState(hCamera, 0) # Disable auto exposure
# Start camera
mvsdk.CameraPlay(hCamera)
# Allocate frame buffer
FrameBufferSize = cap.sResolutionRange.iWidthMax * cap.sResolutionRange.iHeightMax * (1 if monoCamera else 3)
pFrameBuffer = mvsdk.CameraAlignMalloc(FrameBufferSize, 16)
# Create test directory
if not os.path.exists("exposure_tests"):
os.makedirs("exposure_tests")
print("\nTesting different exposure settings...")
print("=" * 50)
# Test different exposure times (in microseconds)
exposure_times = [500, 1000, 2000, 5000, 10000, 20000] # 0.5ms to 20ms
analog_gains = [1.0] # Start with 1x gain
test_count = 0
for exp_time in exposure_times:
for gain in analog_gains:
# Clamp values to valid ranges
exp_time = max(exp_min, min(exp_max, exp_time))
gain = max(gain_min, min(gain_max, gain))
print(f"\nTest {test_count + 1}: Exposure={exp_time/1000:.1f}ms, Gain={gain:.1f}x")
# Set camera parameters
mvsdk.CameraSetExposureTime(hCamera, exp_time)
try:
mvsdk.CameraSetAnalogGainX(hCamera, gain)
except:
pass # Some cameras might not support this
# Wait a moment for settings to take effect
import time
time.sleep(0.1)
# Capture image
try:
pRawData, FrameHead = mvsdk.CameraGetImageBuffer(hCamera, 2000)
mvsdk.CameraImageProcess(hCamera, pRawData, pFrameBuffer, FrameHead)
mvsdk.CameraReleaseImageBuffer(hCamera, pRawData)
# Handle Windows image flip
if platform.system() == "Windows":
mvsdk.CameraFlipFrameBuffer(pFrameBuffer, FrameHead, 1)
# Convert to numpy array
frame_data = (mvsdk.c_ubyte * FrameHead.uBytes).from_address(pFrameBuffer)
frame = np.frombuffer(frame_data, dtype=np.uint8)
if FrameHead.uiMediaType == mvsdk.CAMERA_MEDIA_TYPE_MONO8:
frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth))
else:
frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth, 3))
# Calculate image statistics
mean_brightness = np.mean(frame)
max_brightness = np.max(frame)
# Save image
filename = f"exposure_tests/test_{test_count+1:02d}_exp{exp_time/1000:.1f}ms_gain{gain:.1f}x.jpg"
cv2.imwrite(filename, frame)
# Provide feedback
status = ""
if mean_brightness < 50:
status = "TOO DARK"
elif mean_brightness > 200:
status = "TOO BRIGHT"
elif max_brightness >= 255:
status = "OVEREXPOSED"
else:
status = "GOOD"
print(f" → Saved: {filename}")
print(f" → Brightness: mean={mean_brightness:.1f}, max={max_brightness:.1f} [{status}]")
test_count += 1
except mvsdk.CameraException as e:
print(f" → Failed to capture: {e.message}")
print(f"\nCompleted {test_count} test captures!")
print("Check the 'exposure_tests' directory to see the results.")
print("\nRecommendations:")
print("- Look for images marked as 'GOOD' - these have optimal exposure")
print("- If all images are 'TOO BRIGHT', try lower exposure times or gains")
print("- If all images are 'TOO DARK', try higher exposure times or gains")
print("- Avoid 'OVEREXPOSED' images as they have clipped highlights")
# Cleanup
mvsdk.CameraAlignFree(pFrameBuffer)
finally:
# Close camera
mvsdk.CameraUnInit(hCamera)
print("\nCamera closed")
return True
if __name__ == "__main__":
print("GigE Camera Exposure Test Script")
print("=" * 40)
print("This script will test different exposure settings and save sample images.")
print("Use this to find the optimal settings for your lighting conditions.")
print()
success = test_exposure_settings()
if success:
print("\nTesting completed successfully!")
else:
print("\nTesting failed!")
input("Press Enter to exit...")