diff --git a/.gitignore b/.gitignore index 9a5aced..fcc266f 100644 --- a/.gitignore +++ b/.gitignore @@ -137,3 +137,5 @@ dist # Vite logs files vite.config.js.timestamp-* vite.config.ts.timestamp-* + +/videos/* \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..7fa27ff --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "python.analysis.extraPaths": [ + "./python demo" + ] +} \ No newline at end of file diff --git a/01README.md b/01README.md new file mode 100644 index 0000000..8a3059d --- /dev/null +++ b/01README.md @@ -0,0 +1,146 @@ +# GigE Camera Image Capture + +This project provides simple Python scripts to connect to a GigE camera and capture images using the provided SDK. + +## Files Overview + +### Demo Files (provided with camera) +- `python demo/mvsdk.py` - Main SDK wrapper library +- `python demo/grab.py` - Basic image capture example +- `python demo/cv_grab.py` - OpenCV-based continuous capture +- `python demo/cv_grab_callback.py` - Callback-based capture +- `python demo/readme.txt` - Original demo documentation + +### Custom Scripts +- `camera_capture.py` - Standalone script to capture 10 images with 200ms intervals +- `test.ipynb` - Jupyter notebook with the same functionality +- `images/` - Directory where captured images are saved + +## Features + +- **Automatic camera detection** - Finds and connects to available GigE cameras +- **Configurable capture** - Currently set to capture 10 images with 200ms intervals +- **Both mono and color support** - Automatically detects camera type +- **Timestamped filenames** - Images saved with date/time stamps +- **Error handling** - Robust error handling for camera operations +- **Cross-platform** - Works on Windows and Linux (with appropriate image flipping) + +## Requirements + +- Python 3.x +- OpenCV (`cv2`) +- NumPy +- Matplotlib (for Jupyter notebook display) +- GigE camera SDK (MVSDK) - included in `python demo/` directory + +## Usage + +### Option 1: Standalone Script + +Run the standalone Python script: + +```bash +python camera_capture.py +``` + +This will: +1. Initialize the camera SDK +2. Detect available cameras +3. Connect to the first camera found +4. Configure camera settings (manual exposure, continuous mode) +5. Capture 10 images with 200ms intervals +6. Save images to the `images/` directory +7. Clean up and close the camera + +### Option 2: Jupyter Notebook + +Open and run the `test.ipynb` notebook: + +```bash +jupyter notebook test.ipynb +``` + +The notebook provides the same functionality but with: +- Step-by-step execution +- Detailed explanations +- Visual display of the last captured image +- Better error reporting + +## Camera Configuration + +The scripts are configured with the following default settings: + +- **Trigger Mode**: Continuous capture (mode 0) +- **Exposure**: Manual, 30ms +- **Output Format**: + - Monochrome cameras: MONO8 + - Color cameras: BGR8 +- **Image Processing**: Automatic ISP processing from RAW to RGB/MONO + +## Output + +Images are saved in the `images/` directory with the following naming convention: +``` +image_XX_YYYYMMDD_HHMMSS_mmm.jpg +``` + +Where: +- `XX` = Image number (01-10) +- `YYYYMMDD_HHMMSS_mmm` = Timestamp with milliseconds + +Example: `image_01_20250722_140530_123.jpg` + +## Troubleshooting + +### Common Issues + +1. **"No camera was found!"** + - Check camera connection (Ethernet cable) + - Verify camera power + - Check network settings (camera and PC should be on same subnet) + - Ensure camera drivers are installed + +2. **"CameraInit Failed"** + - Camera might be in use by another application + - Check camera permissions + - Try restarting the camera or PC + +3. **"Failed to capture image"** + - Check camera settings + - Verify sufficient lighting + - Check exposure settings + +4. **Images appear upside down** + - This is handled automatically on Windows + - Linux users may need to adjust the flip settings + +### Network Configuration + +For GigE cameras, ensure: +- Camera and PC are on the same network segment +- PC network adapter supports Jumbo frames (recommended) +- Firewall allows camera communication +- Sufficient network bandwidth + +## Customization + +You can modify the scripts to: + +- **Change capture count**: Modify the range in the capture loop +- **Adjust timing**: Change the `time.sleep(0.2)` value +- **Modify exposure**: Change the exposure time parameter +- **Change output format**: Modify file format and quality settings +- **Add image processing**: Insert processing steps before saving + +## SDK Reference + +The camera SDK (`mvsdk.py`) provides extensive functionality: + +- Camera enumeration and initialization +- Image capture and processing +- Parameter configuration (exposure, gain, etc.) +- Trigger modes and timing +- Image format conversion +- Error handling + +Refer to the original SDK documentation for advanced features. diff --git a/VIDEO_RECORDER_README.md b/VIDEO_RECORDER_README.md new file mode 100644 index 0000000..d1daba3 --- /dev/null +++ b/VIDEO_RECORDER_README.md @@ -0,0 +1,191 @@ +# Camera Video Recorder + +A Python script for recording videos from GigE cameras using the provided SDK with custom exposure and gain settings. + +## Features + +- **List all available cameras** - Automatically detects and displays all connected cameras +- **Custom camera settings** - Set exposure time to 1ms and gain to 3.5x (or custom values) +- **Video recording** - Record videos in AVI format with timestamp filenames +- **Live preview** - Test camera functionality with live preview mode +- **Interactive menu** - User-friendly menu system for all operations +- **Automatic cleanup** - Proper resource management and cleanup + +## Requirements + +- Python 3.x +- OpenCV (`cv2`) +- NumPy +- Camera SDK (mvsdk) - included in `python demo` directory +- GigE camera connected to the system + +## Installation + +1. Ensure your GigE camera is connected and properly configured +2. Make sure the `python demo` directory with `mvsdk.py` is present +3. Install required Python packages: + ```bash + pip install opencv-python numpy + ``` + +## Usage + +### Basic Usage + +Run the script: +```bash +python camera_video_recorder.py +``` + +The script will: +1. Display a welcome message and feature overview +2. List all available cameras +3. Let you select a camera (if multiple are available) +4. Allow you to set custom exposure and gain values +5. Present an interactive menu with options + +### Menu Options + +1. **Start Recording** - Begin video recording with timestamp filename +2. **List Camera Info** - Display detailed camera information +3. **Test Camera (Live Preview)** - View live camera feed without recording +4. **Exit** - Clean up and exit the program + +### Default Settings + +- **Exposure Time**: 1.0ms (1000 microseconds) +- **Gain**: 3.5x +- **Video Format**: AVI with XVID codec +- **Frame Rate**: 30 FPS +- **Output Directory**: `videos/` (created automatically) + +### Recording Controls + +- **Start Recording**: Select option 1 from the menu +- **Stop Recording**: Press 'q' in the preview window +- **Video Files**: Saved as `videos/camera_recording_YYYYMMDD_HHMMSS.avi` + +## File Structure + +``` +camera_video_recorder.py # Main script +python demo/ + mvsdk.py # Camera SDK wrapper + (other demo files) +videos/ # Output directory (created automatically) + camera_recording_*.avi # Recorded video files +``` + +## Script Features + +### CameraVideoRecorder Class + +- `list_cameras()` - Enumerate and display available cameras +- `initialize_camera()` - Set up camera with custom exposure and gain +- `start_recording()` - Initialize video writer and begin recording +- `stop_recording()` - Stop recording and save video file +- `record_loop()` - Main recording loop with live preview +- `cleanup()` - Proper resource cleanup + +### Key Functions + +- **Camera Detection**: Automatically finds all connected GigE cameras +- **Settings Validation**: Checks and clamps exposure/gain values to camera limits +- **Frame Processing**: Handles both monochrome and color cameras +- **Windows Compatibility**: Handles frame flipping for Windows systems +- **Error Handling**: Comprehensive error handling and user feedback + +## Example Output + +``` +Camera Video Recorder +==================== +This script allows you to: +- List all available cameras +- Record videos with custom exposure (1ms) and gain (3.5x) settings +- Save videos with timestamps +- Stop recording anytime with 'q' key + +Found 1 camera(s): +0: GigE Camera Model (GigE) - SN: 12345678 + +Using camera: GigE Camera Model + +Camera Settings: +Enter exposure time in ms (default 1.0): 1.0 +Enter gain value (default 3.5): 3.5 + +Initializing camera with: +- Exposure: 1.0ms +- Gain: 3.5x + +Camera type: Color +Set exposure time: 1000.0μs +Set analog gain: 3.50x (range: 1.00 - 16.00) +Camera started successfully + +================================================== +Camera Video Recorder Menu +================================================== +1. Start Recording +2. List Camera Info +3. Test Camera (Live Preview) +4. Exit + +Select option (1-4): 1 + +Started recording to: videos/camera_recording_20241223_143022.avi +Frame size: (1920, 1080), FPS: 30.0 +Press 'q' to stop recording... +Recording... Press 'q' in the preview window to stop + +Recording stopped! +Saved: videos/camera_recording_20241223_143022.avi +Frames recorded: 450 +Duration: 15.2 seconds +Average FPS: 29.6 +``` + +## Troubleshooting + +### Common Issues + +1. **"No cameras found!"** + - Check camera connection + - Verify camera power + - Ensure network configuration for GigE cameras + +2. **"SDK initialization failed"** + - Verify `python demo/mvsdk.py` exists + - Check camera drivers are installed + +3. **"Camera initialization failed"** + - Camera may be in use by another application + - Try disconnecting and reconnecting the camera + +4. **Recording issues** + - Ensure sufficient disk space + - Check write permissions in the output directory + +### Performance Tips + +- Close other applications using the camera +- Ensure adequate system resources (CPU, RAM) +- Use SSD storage for better write performance +- Adjust frame rate if experiencing dropped frames + +## Customization + +You can modify the script to: +- Change video codec (currently XVID) +- Adjust target frame rate +- Modify output filename format +- Add additional camera settings +- Change preview window size + +## Notes + +- Videos are saved in the `videos/` directory with timestamp filenames +- The script handles both monochrome and color cameras automatically +- Frame flipping is handled automatically for Windows systems +- All resources are properly cleaned up on exit diff --git a/camera_capture.py b/camera_capture.py new file mode 100644 index 0000000..a585883 --- /dev/null +++ b/camera_capture.py @@ -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...") diff --git a/camera_status_test.ipynb b/camera_status_test.ipynb new file mode 100644 index 0000000..ffd0f85 --- /dev/null +++ b/camera_status_test.ipynb @@ -0,0 +1,607 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "intro", + "metadata": {}, + "source": [ + "# Camera Status and Availability Testing\n", + "\n", + "This notebook tests various methods to check camera status and availability before attempting to capture images.\n", + "\n", + "## Key Functions to Test:\n", + "- `CameraIsOpened()` - Check if camera is already opened by another process\n", + "- `CameraInit()` - Try to initialize and catch specific error codes\n", + "- `CameraGetImageBuffer()` - Test actual image capture with timeout\n", + "- Error code analysis for different failure scenarios" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "imports", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Libraries imported successfully!\n", + "Platform: Windows\n" + ] + } + ], + "source": [ + "# Import required libraries\n", + "import os\n", + "import sys\n", + "import time\n", + "import numpy as np\n", + "import cv2\n", + "import platform\n", + "from datetime import datetime\n", + "\n", + "# Add the python demo directory to path to import mvsdk\n", + "sys.path.append('./python demo')\n", + "import mvsdk\n", + "\n", + "print(\"Libraries imported successfully!\")\n", + "print(f\"Platform: {platform.system()}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "error-codes", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Relevant Camera Status Error Codes:\n", + "========================================\n", + "CAMERA_STATUS_SUCCESS: 0\n", + "CAMERA_STATUS_DEVICE_IS_OPENED: -18\n", + "CAMERA_STATUS_DEVICE_IS_CLOSED: -19\n", + "CAMERA_STATUS_ACCESS_DENY: -45\n", + "CAMERA_STATUS_DEVICE_LOST: -38\n", + "CAMERA_STATUS_TIME_OUT: -12\n", + "CAMERA_STATUS_BUSY: -28\n", + "CAMERA_STATUS_NO_DEVICE_FOUND: -16\n" + ] + } + ], + "source": [ + "# Let's examine the relevant error codes from the SDK\n", + "print(\"Relevant Camera Status Error Codes:\")\n", + "print(\"=\" * 40)\n", + "print(f\"CAMERA_STATUS_SUCCESS: {mvsdk.CAMERA_STATUS_SUCCESS}\")\n", + "print(f\"CAMERA_STATUS_DEVICE_IS_OPENED: {mvsdk.CAMERA_STATUS_DEVICE_IS_OPENED}\")\n", + "print(f\"CAMERA_STATUS_DEVICE_IS_CLOSED: {mvsdk.CAMERA_STATUS_DEVICE_IS_CLOSED}\")\n", + "print(f\"CAMERA_STATUS_ACCESS_DENY: {mvsdk.CAMERA_STATUS_ACCESS_DENY}\")\n", + "print(f\"CAMERA_STATUS_DEVICE_LOST: {mvsdk.CAMERA_STATUS_DEVICE_LOST}\")\n", + "print(f\"CAMERA_STATUS_TIME_OUT: {mvsdk.CAMERA_STATUS_TIME_OUT}\")\n", + "print(f\"CAMERA_STATUS_BUSY: {mvsdk.CAMERA_STATUS_BUSY}\")\n", + "print(f\"CAMERA_STATUS_NO_DEVICE_FOUND: {mvsdk.CAMERA_STATUS_NO_DEVICE_FOUND}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "id": "status-functions", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Camera Availability Check\n", + "==============================\n", + "✓ SDK initialized successfully\n", + "✓ Found 2 camera(s)\n", + " 0: Blower-Yield-Cam (NET-1000M-192.168.1.165)\n", + " 1: Cracker-Cam (NET-1000M-192.168.1.167)\n", + "\n", + "Testing camera 0: Blower-Yield-Cam\n", + "✓ Camera is available (not opened by another process)\n", + "✓ Camera initialized successfully\n", + "✓ Camera closed after testing\n", + "\n", + "Testing camera 1: Cracker-Cam\n", + "✓ Camera is available (not opened by another process)\n", + "✓ Camera initialized successfully\n", + "✓ Camera closed after testing\n", + "\n", + "Results for 2 cameras:\n", + " Camera 0: AVAILABLE\n", + " Camera 1: AVAILABLE\n" + ] + } + ], + "source": [ + "def check_camera_availability():\n", + " \"\"\"\n", + " Comprehensive camera availability check\n", + " \"\"\"\n", + " print(\"Camera Availability Check\")\n", + " print(\"=\" * 30)\n", + " \n", + " # Step 1: Initialize SDK\n", + " try:\n", + " mvsdk.CameraSdkInit(1)\n", + " print(\"✓ SDK initialized successfully\")\n", + " except Exception as e:\n", + " print(f\"✗ SDK initialization failed: {e}\")\n", + " return None, \"SDK_INIT_FAILED\"\n", + " \n", + " # Step 2: Enumerate cameras\n", + " try:\n", + " DevList = mvsdk.CameraEnumerateDevice()\n", + " nDev = len(DevList)\n", + " print(f\"✓ Found {nDev} camera(s)\")\n", + " \n", + " if nDev < 1:\n", + " print(\"✗ No cameras detected\")\n", + " return None, \"NO_CAMERAS\"\n", + " \n", + " for i, DevInfo in enumerate(DevList):\n", + " print(f\" {i}: {DevInfo.GetFriendlyName()} ({DevInfo.GetPortType()})\")\n", + " \n", + " except Exception as e:\n", + " print(f\"✗ Camera enumeration failed: {e}\")\n", + " return None, \"ENUM_FAILED\"\n", + " \n", + " # Step 3: Check all cameras\n", + " camera_results = []\n", + " \n", + " for i, DevInfo in enumerate(DevList):\n", + " print(f\"\\nTesting camera {i}: {DevInfo.GetFriendlyName()}\")\n", + " \n", + " # Check if camera is already opened\n", + " try:\n", + " is_opened = mvsdk.CameraIsOpened(DevInfo)\n", + " if is_opened:\n", + " print(\"✗ Camera is already opened by another process\")\n", + " camera_results.append((DevInfo, \"ALREADY_OPENED\"))\n", + " continue\n", + " else:\n", + " print(\"✓ Camera is available (not opened by another process)\")\n", + " except Exception as e:\n", + " print(f\"⚠ Could not check if camera is opened: {e}\")\n", + " \n", + " # Try to initialize camera\n", + " try:\n", + " hCamera = mvsdk.CameraInit(DevInfo, -1, -1)\n", + " print(\"✓ Camera initialized successfully\")\n", + " camera_results.append((hCamera, \"AVAILABLE\"))\n", + " \n", + " # Close the camera after testing\n", + " try:\n", + " mvsdk.CameraUnInit(hCamera)\n", + " print(\"✓ Camera closed after testing\")\n", + " except Exception as e:\n", + " print(f\"⚠ Warning: Could not close camera: {e}\")\n", + " \n", + " except mvsdk.CameraException as e:\n", + " print(f\"✗ Camera initialization failed: {e.error_code} - {e.message}\")\n", + " \n", + " # Analyze specific error codes\n", + " if e.error_code == mvsdk.CAMERA_STATUS_DEVICE_IS_OPENED:\n", + " camera_results.append((DevInfo, \"DEVICE_OPENED\"))\n", + " elif e.error_code == mvsdk.CAMERA_STATUS_ACCESS_DENY:\n", + " camera_results.append((DevInfo, \"ACCESS_DENIED\"))\n", + " elif e.error_code == mvsdk.CAMERA_STATUS_DEVICE_LOST:\n", + " camera_results.append((DevInfo, \"DEVICE_LOST\"))\n", + " else:\n", + " camera_results.append((DevInfo, f\"INIT_ERROR_{e.error_code}\"))\n", + " \n", + " except Exception as e:\n", + " print(f\"✗ Unexpected error during initialization: {e}\")\n", + " camera_results.append((DevInfo, \"UNEXPECTED_ERROR\"))\n", + " \n", + " return camera_results\n", + "\n", + "# Test the function\n", + "camera_results = check_camera_availability()\n", + "print(f\"\\nResults for {len(camera_results)} cameras:\")\n", + "for i, (camera_info, status) in enumerate(camera_results):\n", + " if hasattr(camera_info, 'GetFriendlyName'):\n", + " name = camera_info.GetFriendlyName()\n", + " else:\n", + " name = f\"Camera {i}\"\n", + " print(f\" {name}: {status}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "test-capture-availability", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Testing capture readiness for 2 available camera(s):\n", + "\n", + "Testing camera 0 capture readiness...\n", + "\n", + "Testing Camera Capture Readiness\n", + "===================================\n", + "✓ Camera capabilities retrieved\n", + "✓ Camera type: Color\n", + "✓ Basic camera configuration set\n", + "✓ Camera started\n", + "✓ Frame buffer allocated\n", + "\n", + "Testing image capture...\n", + "✓ Image captured successfully: 1280x1024\n", + "✓ Image processed and buffer released\n", + "✓ Cleanup completed\n", + "Capture Ready for Blower-Yield-Cam: True\n", + "\n", + "Testing camera 1 capture readiness...\n", + "\n", + "Testing Camera Capture Readiness\n", + "===================================\n", + "✓ Camera capabilities retrieved\n", + "✓ Camera type: Color\n", + "✓ Basic camera configuration set\n", + "✓ Camera started\n", + "✓ Frame buffer allocated\n", + "\n", + "Testing image capture...\n", + "✓ Image captured successfully: 1280x1024\n", + "✓ Image processed and buffer released\n", + "✓ Cleanup completed\n", + "Capture Ready for Cracker-Cam: True\n" + ] + } + ], + "source": [ + "def test_camera_capture_readiness(hCamera):\n", + " \"\"\"\n", + " Test if camera is ready for image capture\n", + " \"\"\"\n", + " if not isinstance(hCamera, int):\n", + " print(\"Camera not properly initialized, skipping capture test\")\n", + " return False\n", + " \n", + " print(\"\\nTesting Camera Capture Readiness\")\n", + " print(\"=\" * 35)\n", + " \n", + " try:\n", + " # Get camera capabilities\n", + " cap = mvsdk.CameraGetCapability(hCamera)\n", + " print(\"✓ Camera capabilities retrieved\")\n", + " \n", + " # Check camera type\n", + " monoCamera = (cap.sIspCapacity.bMonoSensor != 0)\n", + " print(f\"✓ Camera type: {'Monochrome' if monoCamera else 'Color'}\")\n", + " \n", + " # Set basic configuration\n", + " if monoCamera:\n", + " mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_MONO8)\n", + " else:\n", + " mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_BGR8)\n", + " \n", + " mvsdk.CameraSetTriggerMode(hCamera, 0) # Continuous mode\n", + " mvsdk.CameraSetAeState(hCamera, 0) # Manual exposure\n", + " mvsdk.CameraSetExposureTime(hCamera, 5000) # 5ms exposure\n", + " print(\"✓ Basic camera configuration set\")\n", + " \n", + " # Start camera\n", + " mvsdk.CameraPlay(hCamera)\n", + " print(\"✓ Camera started\")\n", + " \n", + " # Allocate buffer\n", + " FrameBufferSize = cap.sResolutionRange.iWidthMax * cap.sResolutionRange.iHeightMax * (1 if monoCamera else 3)\n", + " pFrameBuffer = mvsdk.CameraAlignMalloc(FrameBufferSize, 16)\n", + " print(\"✓ Frame buffer allocated\")\n", + " \n", + " # Test image capture with short timeout\n", + " print(\"\\nTesting image capture...\")\n", + " try:\n", + " pRawData, FrameHead = mvsdk.CameraGetImageBuffer(hCamera, 1000) # 1 second timeout\n", + " print(f\"✓ Image captured successfully: {FrameHead.iWidth}x{FrameHead.iHeight}\")\n", + " \n", + " # Process and release\n", + " mvsdk.CameraImageProcess(hCamera, pRawData, pFrameBuffer, FrameHead)\n", + " mvsdk.CameraReleaseImageBuffer(hCamera, pRawData)\n", + " print(\"✓ Image processed and buffer released\")\n", + " \n", + " capture_success = True\n", + " \n", + " except mvsdk.CameraException as e:\n", + " print(f\"✗ Image capture failed: {e.error_code} - {e.message}\")\n", + " \n", + " if e.error_code == mvsdk.CAMERA_STATUS_TIME_OUT:\n", + " print(\" → Camera timeout - may be busy or not streaming\")\n", + " elif e.error_code == mvsdk.CAMERA_STATUS_DEVICE_LOST:\n", + " print(\" → Device lost - camera disconnected\")\n", + " elif e.error_code == mvsdk.CAMERA_STATUS_BUSY:\n", + " print(\" → Camera busy - may be used by another process\")\n", + " \n", + " capture_success = False\n", + " \n", + " # Cleanup\n", + " mvsdk.CameraAlignFree(pFrameBuffer)\n", + " print(\"✓ Cleanup completed\")\n", + " \n", + " return capture_success\n", + " \n", + " except Exception as e:\n", + " print(f\"✗ Capture readiness test failed: {e}\")\n", + " return False\n", + "\n", + "# Test capture readiness for available cameras\n", + "available_cameras = [(cam, stat) for cam, stat in camera_results if stat == \"AVAILABLE\"]\n", + "\n", + "if available_cameras:\n", + " print(f\"\\nTesting capture readiness for {len(available_cameras)} available camera(s):\")\n", + " for i, (camera_handle, status) in enumerate(available_cameras):\n", + " if hasattr(camera_handle, 'GetFriendlyName'):\n", + " # This shouldn't happen for AVAILABLE cameras, but just in case\n", + " print(f\"\\nCamera {i}: Invalid handle\")\n", + " continue\n", + " \n", + " print(f\"\\nTesting camera {i} capture readiness...\")\n", + " # Re-initialize the camera for testing since we closed it earlier\n", + " try:\n", + " # Find the camera info from the original results\n", + " DevList = mvsdk.CameraEnumerateDevice()\n", + " if i < len(DevList):\n", + " DevInfo = DevList[i]\n", + " hCamera = mvsdk.CameraInit(DevInfo, -1, -1)\n", + " capture_ready = test_camera_capture_readiness(hCamera)\n", + " print(f\"Capture Ready for {DevInfo.GetFriendlyName()}: {capture_ready}\")\n", + " mvsdk.CameraUnInit(hCamera)\n", + " else:\n", + " print(f\"Could not re-initialize camera {i}\")\n", + " except Exception as e:\n", + " print(f\"Error testing camera {i}: {e}\")\n", + "else:\n", + " print(\"\\nNo cameras are available for capture testing\")\n", + " print(\"Camera statuses:\")\n", + " for i, (cam_info, status) in enumerate(camera_results):\n", + " if hasattr(cam_info, 'GetFriendlyName'):\n", + " name = cam_info.GetFriendlyName()\n", + " else:\n", + " name = f\"Camera {i}\"\n", + " print(f\" {name}: {status}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "id": "comprehensive-check", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "==================================================\n", + "COMPREHENSIVE CAMERA CHECK\n", + "==================================================\n", + "Camera Availability Check\n", + "==============================\n", + "✓ SDK initialized successfully\n", + "✓ Found 2 camera(s)\n", + " 0: Blower-Yield-Cam (NET-1000M-192.168.1.165)\n", + " 1: Cracker-Cam (NET-1000M-192.168.1.167)\n", + "\n", + "Testing camera 0: Blower-Yield-Cam\n", + "✓ Camera is available (not opened by another process)\n", + "✓ Camera initialized successfully\n", + "✓ Camera closed after testing\n", + "\n", + "Testing camera 1: Cracker-Cam\n", + "✓ Camera is available (not opened by another process)\n", + "✓ Camera initialized successfully\n", + "✓ Camera closed after testing\n", + "\n", + "==================================================\n", + "FINAL RESULTS:\n", + "Camera Available: False\n", + "Capture Ready: False\n", + "Status: (34, 'AVAILABLE')\n", + "==================================================\n" + ] + } + ], + "source": [ + "def comprehensive_camera_check():\n", + " \"\"\"\n", + " Complete camera availability and readiness check\n", + " Returns: (available, ready, handle_or_info, status_message)\n", + " \"\"\"\n", + " # Check availability\n", + " handle_or_info, status = check_camera_availability()\n", + " \n", + " available = status == \"AVAILABLE\"\n", + " ready = False\n", + " \n", + " if available:\n", + " # Test capture readiness\n", + " ready = test_camera_capture_readiness(handle_or_info)\n", + " \n", + " # Close camera after testing\n", + " try:\n", + " mvsdk.CameraUnInit(handle_or_info)\n", + " print(\"✓ Camera closed after testing\")\n", + " except:\n", + " pass\n", + " \n", + " return available, ready, handle_or_info, status\n", + "\n", + "# Run comprehensive check\n", + "print(\"\\n\" + \"=\" * 50)\n", + "print(\"COMPREHENSIVE CAMERA CHECK\")\n", + "print(\"=\" * 50)\n", + "\n", + "available, ready, info, status_msg = comprehensive_camera_check()\n", + "\n", + "print(\"\\n\" + \"=\" * 50)\n", + "print(\"FINAL RESULTS:\")\n", + "print(f\"Camera Available: {available}\")\n", + "print(f\"Capture Ready: {ready}\")\n", + "print(f\"Status: {status_msg}\")\n", + "print(\"=\" * 50)" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "id": "status-check-function", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Testing Simple Camera Ready Check:\n", + "========================================\n", + "Ready: True\n", + "Message: Camera 'Blower-Yield-Cam' is ready for capture\n", + "Camera: Blower-Yield-Cam\n" + ] + } + ], + "source": [ + "def is_camera_ready_for_capture():\n", + " \"\"\"\n", + " Simple function to check if camera is ready for capture.\n", + " Returns: (ready: bool, message: str, camera_info: object or None)\n", + " \n", + " This is the function you can use in your main capture script.\n", + " \"\"\"\n", + " try:\n", + " # Initialize SDK\n", + " mvsdk.CameraSdkInit(1)\n", + " \n", + " # Enumerate cameras\n", + " DevList = mvsdk.CameraEnumerateDevice()\n", + " if len(DevList) < 1:\n", + " return False, \"No cameras found\", None\n", + " \n", + " DevInfo = DevList[0]\n", + " \n", + " # Check if already opened\n", + " try:\n", + " if mvsdk.CameraIsOpened(DevInfo):\n", + " return False, f\"Camera '{DevInfo.GetFriendlyName()}' is already opened by another process\", DevInfo\n", + " except:\n", + " pass # Some cameras might not support this check\n", + " \n", + " # Try to initialize\n", + " try:\n", + " hCamera = mvsdk.CameraInit(DevInfo, -1, -1)\n", + " \n", + " # Quick capture test\n", + " try:\n", + " # Basic setup\n", + " mvsdk.CameraSetTriggerMode(hCamera, 0)\n", + " mvsdk.CameraPlay(hCamera)\n", + " \n", + " # Try to get one frame with short timeout\n", + " pRawData, FrameHead = mvsdk.CameraGetImageBuffer(hCamera, 500) # 0.5 second timeout\n", + " mvsdk.CameraReleaseImageBuffer(hCamera, pRawData)\n", + " \n", + " # Success - close and return\n", + " mvsdk.CameraUnInit(hCamera)\n", + " return True, f\"Camera '{DevInfo.GetFriendlyName()}' is ready for capture\", DevInfo\n", + " \n", + " except mvsdk.CameraException as e:\n", + " mvsdk.CameraUnInit(hCamera)\n", + " if e.error_code == mvsdk.CAMERA_STATUS_TIME_OUT:\n", + " return False, \"Camera timeout - may be busy or not streaming properly\", DevInfo\n", + " else:\n", + " return False, f\"Camera capture test failed: {e.message}\", DevInfo\n", + " \n", + " except mvsdk.CameraException as e:\n", + " if e.error_code == mvsdk.CAMERA_STATUS_DEVICE_IS_OPENED:\n", + " return False, f\"Camera '{DevInfo.GetFriendlyName()}' is already in use\", DevInfo\n", + " elif e.error_code == mvsdk.CAMERA_STATUS_ACCESS_DENY:\n", + " return False, f\"Access denied to camera '{DevInfo.GetFriendlyName()}'\", DevInfo\n", + " else:\n", + " return False, f\"Camera initialization failed: {e.message}\", DevInfo\n", + " \n", + " except Exception as e:\n", + " return False, f\"Camera check failed: {str(e)}\", None\n", + "\n", + "# Test the simple function\n", + "print(\"\\nTesting Simple Camera Ready Check:\")\n", + "print(\"=\" * 40)\n", + "\n", + "ready, message, camera_info = is_camera_ready_for_capture()\n", + "print(f\"Ready: {ready}\")\n", + "print(f\"Message: {message}\")\n", + "if camera_info:\n", + " print(f\"Camera: {camera_info.GetFriendlyName()}\")" + ] + }, + { + "cell_type": "markdown", + "id": "usage-example", + "metadata": {}, + "source": [ + "## Usage Example\n", + "\n", + "Here's how you can integrate the camera status check into your capture script:\n", + "\n", + "```python\n", + "# Before attempting to capture images\n", + "ready, message, camera_info = is_camera_ready_for_capture()\n", + "\n", + "if not ready:\n", + " print(f\"Camera not ready: {message}\")\n", + " # Handle the error appropriately\n", + " return False\n", + "\n", + "print(f\"Camera ready: {message}\")\n", + "# Proceed with normal capture logic\n", + "```\n", + "\n", + "## Key Findings\n", + "\n", + "1. **`CameraIsOpened()`** - Checks if camera is opened by another process\n", + "2. **`CameraInit()` error codes** - Provide specific failure reasons\n", + "3. **Quick capture test** - Verifies camera is actually streaming\n", + "4. **Timeout handling** - Detects if camera is busy/unresponsive\n", + "\n", + "The most reliable approach is to:\n", + "1. Check if camera exists\n", + "2. Check if it's already opened\n", + "3. Try to initialize it\n", + "4. Test actual image capture with short timeout\n", + "5. Clean up properly" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "cc_pecan", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/camera_video_recorder.py b/camera_video_recorder.py new file mode 100644 index 0000000..7efd72b --- /dev/null +++ b/camera_video_recorder.py @@ -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() diff --git a/exposure test.ipynb b/exposure test.ipynb new file mode 100644 index 0000000..467802d --- /dev/null +++ b/exposure test.ipynb @@ -0,0 +1,426 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 25, + "id": "ba958c88", + "metadata": {}, + "outputs": [], + "source": [ + "# coding=utf-8\n", + "\"\"\"\n", + "Test script to help find optimal exposure settings for your GigE camera.\n", + "This script captures a single test image with different exposure settings.\n", + "\"\"\"\n", + "import sys\n", + "\n", + "sys.path.append(\"./python demo\")\n", + "import os\n", + "import mvsdk\n", + "import numpy as np\n", + "import cv2\n", + "import platform\n", + "from datetime import datetime\n", + "\n", + "# Add the python demo directory to path\n" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "23f1dc49", + "metadata": {}, + "outputs": [], + "source": [ + "def test_exposure_settings():\n", + " \"\"\"\n", + " Test different exposure settings to find optimal values\n", + " \"\"\"\n", + " # Initialize SDK\n", + " try:\n", + " mvsdk.CameraSdkInit(1)\n", + " print(\"SDK initialized successfully\")\n", + " except Exception as e:\n", + " print(f\"SDK initialization failed: {e}\")\n", + " return False\n", + "\n", + " # Enumerate cameras\n", + " DevList = mvsdk.CameraEnumerateDevice()\n", + " nDev = len(DevList)\n", + "\n", + " if nDev < 1:\n", + " print(\"No camera was found!\")\n", + " return False\n", + "\n", + " print(f\"Found {nDev} camera(s):\")\n", + " for i, DevInfo in enumerate(DevList):\n", + " print(f\" {i}: {DevInfo.GetFriendlyName()} ({DevInfo.GetPortType()})\")\n", + "\n", + " # Use first camera\n", + " DevInfo = DevList[0]\n", + " print(f\"\\nSelected camera: {DevInfo.GetFriendlyName()}\")\n", + "\n", + " # Initialize camera\n", + " try:\n", + " hCamera = mvsdk.CameraInit(DevInfo, -1, -1)\n", + " print(\"Camera initialized successfully\")\n", + " except mvsdk.CameraException as e:\n", + " print(f\"CameraInit Failed({e.error_code}): {e.message}\")\n", + " return False\n", + "\n", + " try:\n", + " # Get camera capabilities\n", + " cap = mvsdk.CameraGetCapability(hCamera)\n", + " monoCamera = cap.sIspCapacity.bMonoSensor != 0\n", + " print(f\"Camera type: {'Monochrome' if monoCamera else 'Color'}\")\n", + "\n", + " # Get camera ranges\n", + " try:\n", + " exp_min, exp_max, exp_step = mvsdk.CameraGetExposureTimeRange(hCamera)\n", + " print(f\"Exposure time range: {exp_min:.1f} - {exp_max:.1f} μs\")\n", + "\n", + " gain_min, gain_max, gain_step = mvsdk.CameraGetAnalogGainXRange(hCamera)\n", + " print(f\"Analog gain range: {gain_min:.2f} - {gain_max:.2f}x\")\n", + "\n", + " print(\"whatever this is: \", mvsdk.CameraGetAnalogGainXRange(hCamera))\n", + " except Exception as e:\n", + " print(f\"Could not get camera ranges: {e}\")\n", + " exp_min, exp_max = 100, 100000\n", + " gain_min, gain_max = 1.0, 4.0\n", + "\n", + " # Set output format\n", + " if monoCamera:\n", + " mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_MONO8)\n", + " else:\n", + " mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_BGR8)\n", + "\n", + " # Set camera to continuous capture mode\n", + " mvsdk.CameraSetTriggerMode(hCamera, 0)\n", + " mvsdk.CameraSetAeState(hCamera, 0) # Disable auto exposure\n", + "\n", + " # Start camera\n", + " mvsdk.CameraPlay(hCamera)\n", + "\n", + " # Allocate frame buffer\n", + " FrameBufferSize = cap.sResolutionRange.iWidthMax * cap.sResolutionRange.iHeightMax * (1 if monoCamera else 3)\n", + " pFrameBuffer = mvsdk.CameraAlignMalloc(FrameBufferSize, 16)\n", + "\n", + " # Create test directory\n", + " if not os.path.exists(\"exposure_tests\"):\n", + " os.makedirs(\"exposure_tests\")\n", + "\n", + " print(\"\\nTesting different exposure settings...\")\n", + " print(\"=\" * 50)\n", + "\n", + " # Test different exposure times (in microseconds)\n", + " exposure_times = [100, 200, 500, 1000, 2000, 5000, 10000, 20000] # 0.5ms to 20ms\n", + " analog_gains = [2.5, 5.0, 10.0, 16.0] # Start with 1x gain\n", + "\n", + " test_count = 0\n", + " for exp_time in exposure_times:\n", + " for gain in analog_gains:\n", + " # Clamp values to valid ranges\n", + " exp_time = max(exp_min, min(exp_max, exp_time))\n", + " gain = max(gain_min, min(gain_max, gain))\n", + "\n", + " print(f\"\\nTest {test_count + 1}: Exposure={exp_time/1000:.1f}ms, Gain={gain:.1f}x\")\n", + "\n", + " # Set camera parameters\n", + " mvsdk.CameraSetExposureTime(hCamera, exp_time)\n", + " try:\n", + " mvsdk.CameraSetAnalogGainX(hCamera, gain)\n", + " except:\n", + " pass # Some cameras might not support this\n", + "\n", + " # Wait a moment for settings to take effect\n", + " import time\n", + "\n", + " time.sleep(0.1)\n", + "\n", + " # Capture image\n", + " try:\n", + " pRawData, FrameHead = mvsdk.CameraGetImageBuffer(hCamera, 2000)\n", + " mvsdk.CameraImageProcess(hCamera, pRawData, pFrameBuffer, FrameHead)\n", + " mvsdk.CameraReleaseImageBuffer(hCamera, pRawData)\n", + "\n", + " # Handle Windows image flip\n", + " if platform.system() == \"Windows\":\n", + " mvsdk.CameraFlipFrameBuffer(pFrameBuffer, FrameHead, 1)\n", + "\n", + " # Convert to numpy array\n", + " frame_data = (mvsdk.c_ubyte * FrameHead.uBytes).from_address(pFrameBuffer)\n", + " frame = np.frombuffer(frame_data, dtype=np.uint8)\n", + "\n", + " if FrameHead.uiMediaType == mvsdk.CAMERA_MEDIA_TYPE_MONO8:\n", + " frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth))\n", + " else:\n", + " frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth, 3))\n", + "\n", + " # Calculate image statistics\n", + " mean_brightness = np.mean(frame)\n", + " max_brightness = np.max(frame)\n", + "\n", + " # Save image\n", + " filename = f\"exposure_tests/test_{test_count+1:02d}_exp{exp_time/1000:.1f}ms_gain{gain:.1f}x.jpg\"\n", + " cv2.imwrite(filename, frame)\n", + "\n", + " # Provide feedback\n", + " status = \"\"\n", + " if mean_brightness < 50:\n", + " status = \"TOO DARK\"\n", + " elif mean_brightness > 200:\n", + " status = \"TOO BRIGHT\"\n", + " elif max_brightness >= 255:\n", + " status = \"OVEREXPOSED\"\n", + " else:\n", + " status = \"GOOD\"\n", + "\n", + " print(f\" → Saved: {filename}\")\n", + " print(f\" → Brightness: mean={mean_brightness:.1f}, max={max_brightness:.1f} [{status}]\")\n", + "\n", + " test_count += 1\n", + "\n", + " except mvsdk.CameraException as e:\n", + " print(f\" → Failed to capture: {e.message}\")\n", + "\n", + " print(f\"\\nCompleted {test_count} test captures!\")\n", + " print(\"Check the 'exposure_tests' directory to see the results.\")\n", + " print(\"\\nRecommendations:\")\n", + " print(\"- Look for images marked as 'GOOD' - these have optimal exposure\")\n", + " print(\"- If all images are 'TOO BRIGHT', try lower exposure times or gains\")\n", + " print(\"- If all images are 'TOO DARK', try higher exposure times or gains\")\n", + " print(\"- Avoid 'OVEREXPOSED' images as they have clipped highlights\")\n", + "\n", + " # Cleanup\n", + " mvsdk.CameraAlignFree(pFrameBuffer)\n", + "\n", + " finally:\n", + " # Close camera\n", + " mvsdk.CameraUnInit(hCamera)\n", + " print(\"\\nCamera closed\")\n", + "\n", + " return True" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "2891b5bf", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "GigE Camera Exposure Test Script\n", + "========================================\n", + "This script will test different exposure settings and save sample images.\n", + "Use this to find the optimal settings for your lighting conditions.\n", + "\n", + "SDK initialized successfully\n", + "Found 2 camera(s):\n", + " 0: Blower-Yield-Cam (NET-100M-192.168.1.204)\n", + " 1: Cracker-Cam (NET-1000M-192.168.1.246)\n", + "\n", + "Selected camera: Blower-Yield-Cam\n", + "Camera initialized successfully\n", + "Camera type: Color\n", + "Exposure time range: 8.0 - 1048568.0 μs\n", + "Analog gain range: 2.50 - 16.50x\n", + "whatever this is: (2.5, 16.5, 0.5)\n", + "\n", + "Testing different exposure settings...\n", + "==================================================\n", + "\n", + "Test 1: Exposure=0.1ms, Gain=2.5x\n", + " → Saved: exposure_tests/test_01_exp0.1ms_gain2.5x.jpg\n", + " → Brightness: mean=94.1, max=255.0 [OVEREXPOSED]\n", + "\n", + "Test 2: Exposure=0.1ms, Gain=5.0x\n", + " → Saved: exposure_tests/test_02_exp0.1ms_gain5.0x.jpg\n", + " → Brightness: mean=13.7, max=173.0 [TOO DARK]\n", + "\n", + "Test 3: Exposure=0.1ms, Gain=10.0x\n", + " → Saved: exposure_tests/test_03_exp0.1ms_gain10.0x.jpg\n", + " → Brightness: mean=14.1, max=255.0 [TOO DARK]\n", + "\n", + "Test 4: Exposure=0.1ms, Gain=16.0x\n", + " → Saved: exposure_tests/test_04_exp0.1ms_gain16.0x.jpg\n", + " → Brightness: mean=18.2, max=255.0 [TOO DARK]\n", + "\n", + "Test 5: Exposure=0.2ms, Gain=2.5x\n", + " → Saved: exposure_tests/test_05_exp0.2ms_gain2.5x.jpg\n", + " → Brightness: mean=22.1, max=255.0 [TOO DARK]\n", + "\n", + "Test 6: Exposure=0.2ms, Gain=5.0x\n", + " → Saved: exposure_tests/test_06_exp0.2ms_gain5.0x.jpg\n", + " → Brightness: mean=19.5, max=255.0 [TOO DARK]\n", + "\n", + "Test 7: Exposure=0.2ms, Gain=10.0x\n", + " → Saved: exposure_tests/test_07_exp0.2ms_gain10.0x.jpg\n", + " → Brightness: mean=25.3, max=255.0 [TOO DARK]\n", + "\n", + "Test 8: Exposure=0.2ms, Gain=16.0x\n", + " → Saved: exposure_tests/test_08_exp0.2ms_gain16.0x.jpg\n", + " → Brightness: mean=36.6, max=255.0 [TOO DARK]\n", + "\n", + "Test 9: Exposure=0.5ms, Gain=2.5x\n", + " → Saved: exposure_tests/test_09_exp0.5ms_gain2.5x.jpg\n", + " → Brightness: mean=55.8, max=255.0 [OVEREXPOSED]\n", + "\n", + "Test 10: Exposure=0.5ms, Gain=5.0x\n", + " → Saved: exposure_tests/test_10_exp0.5ms_gain5.0x.jpg\n", + " → Brightness: mean=38.5, max=255.0 [TOO DARK]\n", + "\n", + "Test 11: Exposure=0.5ms, Gain=10.0x\n", + " → Saved: exposure_tests/test_11_exp0.5ms_gain10.0x.jpg\n", + " → Brightness: mean=60.2, max=255.0 [OVEREXPOSED]\n", + "\n", + "Test 12: Exposure=0.5ms, Gain=16.0x\n", + " → Saved: exposure_tests/test_12_exp0.5ms_gain16.0x.jpg\n", + " → Brightness: mean=99.3, max=255.0 [OVEREXPOSED]\n", + "\n", + "Test 13: Exposure=1.0ms, Gain=2.5x\n", + " → Saved: exposure_tests/test_13_exp1.0ms_gain2.5x.jpg\n", + " → Brightness: mean=121.1, max=255.0 [OVEREXPOSED]\n", + "\n", + "Test 14: Exposure=1.0ms, Gain=5.0x\n", + " → Saved: exposure_tests/test_14_exp1.0ms_gain5.0x.jpg\n", + " → Brightness: mean=68.8, max=255.0 [OVEREXPOSED]\n", + "\n", + "Test 15: Exposure=1.0ms, Gain=10.0x\n", + " → Saved: exposure_tests/test_15_exp1.0ms_gain10.0x.jpg\n", + " → Brightness: mean=109.6, max=255.0 [OVEREXPOSED]\n", + "\n", + "Test 16: Exposure=1.0ms, Gain=16.0x\n", + " → Saved: exposure_tests/test_16_exp1.0ms_gain16.0x.jpg\n", + " → Brightness: mean=148.7, max=255.0 [OVEREXPOSED]\n", + "\n", + "Test 17: Exposure=2.0ms, Gain=2.5x\n", + " → Saved: exposure_tests/test_17_exp2.0ms_gain2.5x.jpg\n", + " → Brightness: mean=171.9, max=255.0 [OVEREXPOSED]\n", + "\n", + "Test 18: Exposure=2.0ms, Gain=5.0x\n", + " → Saved: exposure_tests/test_18_exp2.0ms_gain5.0x.jpg\n", + " → Brightness: mean=117.9, max=255.0 [OVEREXPOSED]\n", + "\n", + "Test 19: Exposure=2.0ms, Gain=10.0x\n", + " → Saved: exposure_tests/test_19_exp2.0ms_gain10.0x.jpg\n", + " → Brightness: mean=159.0, max=255.0 [OVEREXPOSED]\n", + "\n", + "Test 20: Exposure=2.0ms, Gain=16.0x\n", + " → Saved: exposure_tests/test_20_exp2.0ms_gain16.0x.jpg\n", + " → Brightness: mean=195.7, max=255.0 [OVEREXPOSED]\n", + "\n", + "Test 21: Exposure=5.0ms, Gain=2.5x\n", + " → Saved: exposure_tests/test_21_exp5.0ms_gain2.5x.jpg\n", + " → Brightness: mean=214.6, max=255.0 [TOO BRIGHT]\n", + "\n", + "Test 22: Exposure=5.0ms, Gain=5.0x\n", + " → Saved: exposure_tests/test_22_exp5.0ms_gain5.0x.jpg\n", + " → Brightness: mean=180.2, max=255.0 [OVEREXPOSED]\n", + "\n", + "Test 23: Exposure=5.0ms, Gain=10.0x\n", + " → Saved: exposure_tests/test_23_exp5.0ms_gain10.0x.jpg\n", + " → Brightness: mean=214.6, max=255.0 [TOO BRIGHT]\n", + "\n", + "Test 24: Exposure=5.0ms, Gain=16.0x\n", + " → Saved: exposure_tests/test_24_exp5.0ms_gain16.0x.jpg\n", + " → Brightness: mean=239.6, max=255.0 [TOO BRIGHT]\n", + "\n", + "Test 25: Exposure=10.0ms, Gain=2.5x\n", + " → Saved: exposure_tests/test_25_exp10.0ms_gain2.5x.jpg\n", + " → Brightness: mean=247.5, max=255.0 [TOO BRIGHT]\n", + "\n", + "Test 26: Exposure=10.0ms, Gain=5.0x\n", + " → Saved: exposure_tests/test_26_exp10.0ms_gain5.0x.jpg\n", + " → Brightness: mean=252.4, max=255.0 [TOO BRIGHT]\n", + "\n", + "Test 27: Exposure=10.0ms, Gain=10.0x\n", + " → Saved: exposure_tests/test_27_exp10.0ms_gain10.0x.jpg\n", + " → Brightness: mean=218.9, max=255.0 [TOO BRIGHT]\n", + "\n", + "Test 28: Exposure=10.0ms, Gain=16.0x\n", + " → Saved: exposure_tests/test_28_exp10.0ms_gain16.0x.jpg\n", + " → Brightness: mean=250.8, max=255.0 [TOO BRIGHT]\n", + "\n", + "Test 29: Exposure=20.0ms, Gain=2.5x\n", + " → Saved: exposure_tests/test_29_exp20.0ms_gain2.5x.jpg\n", + " → Brightness: mean=252.4, max=255.0 [TOO BRIGHT]\n", + "\n", + "Test 30: Exposure=20.0ms, Gain=5.0x\n", + " → Saved: exposure_tests/test_30_exp20.0ms_gain5.0x.jpg\n", + " → Brightness: mean=244.4, max=255.0 [TOO BRIGHT]\n", + "\n", + "Test 31: Exposure=20.0ms, Gain=10.0x\n", + " → Saved: exposure_tests/test_31_exp20.0ms_gain10.0x.jpg\n", + " → Brightness: mean=251.5, max=255.0 [TOO BRIGHT]\n", + "\n", + "Test 32: Exposure=20.0ms, Gain=16.0x\n", + " → Saved: exposure_tests/test_32_exp20.0ms_gain16.0x.jpg\n", + " → Brightness: mean=253.4, max=255.0 [TOO BRIGHT]\n", + "\n", + "Completed 32 test captures!\n", + "Check the 'exposure_tests' directory to see the results.\n", + "\n", + "Recommendations:\n", + "- Look for images marked as 'GOOD' - these have optimal exposure\n", + "- If all images are 'TOO BRIGHT', try lower exposure times or gains\n", + "- If all images are 'TOO DARK', try higher exposure times or gains\n", + "- Avoid 'OVEREXPOSED' images as they have clipped highlights\n", + "\n", + "Camera closed\n", + "\n", + "Testing completed successfully!\n" + ] + } + ], + "source": [ + "\n", + "\n", + "if __name__ == \"__main__\":\n", + " print(\"GigE Camera Exposure Test Script\")\n", + " print(\"=\" * 40)\n", + " print(\"This script will test different exposure settings and save sample images.\")\n", + " print(\"Use this to find the optimal settings for your lighting conditions.\")\n", + " print()\n", + "\n", + " success = test_exposure_settings()\n", + "\n", + " if success:\n", + " print(\"\\nTesting completed successfully!\")\n", + " else:\n", + " print(\"\\nTesting failed!\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ead8d889", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "cc_pecan", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python demo/__pycache__/mvsdk.cpython-313.pyc b/python demo/__pycache__/mvsdk.cpython-313.pyc new file mode 100644 index 0000000..a1b88db Binary files /dev/null and b/python demo/__pycache__/mvsdk.cpython-313.pyc differ diff --git a/python demo/cv_grab.py b/python demo/cv_grab.py new file mode 100644 index 0000000..e49ab8b --- /dev/null +++ b/python demo/cv_grab.py @@ -0,0 +1,95 @@ +#coding=utf-8 +import cv2 +import numpy as np +import mvsdk +import platform + +def main_loop(): + # 枚举相机 + DevList = mvsdk.CameraEnumerateDevice() + nDev = len(DevList) + if nDev < 1: + print("No camera was found!") + return + + for i, DevInfo in enumerate(DevList): + print("{}: {} {}".format(i, DevInfo.GetFriendlyName(), DevInfo.GetPortType())) + i = 0 if nDev == 1 else int(input("Select camera: ")) + DevInfo = DevList[i] + print(DevInfo) + + # 打开相机 + hCamera = 0 + try: + hCamera = mvsdk.CameraInit(DevInfo, -1, -1) + except mvsdk.CameraException as e: + print("CameraInit Failed({}): {}".format(e.error_code, e.message) ) + return + + # 获取相机特性描述 + cap = mvsdk.CameraGetCapability(hCamera) + + # 判断是黑白相机还是彩色相机 + monoCamera = (cap.sIspCapacity.bMonoSensor != 0) + + # 黑白相机让ISP直接输出MONO数据,而不是扩展成R=G=B的24位灰度 + if monoCamera: + mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_MONO8) + else: + mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_BGR8) + + # 相机模式切换成连续采集 + mvsdk.CameraSetTriggerMode(hCamera, 0) + + # 手动曝光,曝光时间30ms + mvsdk.CameraSetAeState(hCamera, 0) + mvsdk.CameraSetExposureTime(hCamera, 30 * 1000) + + # 让SDK内部取图线程开始工作 + mvsdk.CameraPlay(hCamera) + + # 计算RGB buffer所需的大小,这里直接按照相机的最大分辨率来分配 + FrameBufferSize = cap.sResolutionRange.iWidthMax * cap.sResolutionRange.iHeightMax * (1 if monoCamera else 3) + + # 分配RGB buffer,用来存放ISP输出的图像 + # 备注:从相机传输到PC端的是RAW数据,在PC端通过软件ISP转为RGB数据(如果是黑白相机就不需要转换格式,但是ISP还有其它处理,所以也需要分配这个buffer) + pFrameBuffer = mvsdk.CameraAlignMalloc(FrameBufferSize, 16) + + while (cv2.waitKey(1) & 0xFF) != ord('q'): + # 从相机取一帧图片 + try: + pRawData, FrameHead = mvsdk.CameraGetImageBuffer(hCamera, 200) + mvsdk.CameraImageProcess(hCamera, pRawData, pFrameBuffer, FrameHead) + mvsdk.CameraReleaseImageBuffer(hCamera, pRawData) + + # windows下取到的图像数据是上下颠倒的,以BMP格式存放。转换成opencv则需要上下翻转成正的 + # linux下直接输出正的,不需要上下翻转 + if platform.system() == "Windows": + mvsdk.CameraFlipFrameBuffer(pFrameBuffer, FrameHead, 1) + + # 此时图片已经存储在pFrameBuffer中,对于彩色相机pFrameBuffer=RGB数据,黑白相机pFrameBuffer=8位灰度数据 + # 把pFrameBuffer转换成opencv的图像格式以进行后续算法处理 + frame_data = (mvsdk.c_ubyte * FrameHead.uBytes).from_address(pFrameBuffer) + frame = np.frombuffer(frame_data, dtype=np.uint8) + frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth, 1 if FrameHead.uiMediaType == mvsdk.CAMERA_MEDIA_TYPE_MONO8 else 3) ) + + frame = cv2.resize(frame, (640,480), interpolation = cv2.INTER_LINEAR) + cv2.imshow("Press q to end", frame) + + except mvsdk.CameraException as e: + if e.error_code != mvsdk.CAMERA_STATUS_TIME_OUT: + print("CameraGetImageBuffer failed({}): {}".format(e.error_code, e.message) ) + + # 关闭相机 + mvsdk.CameraUnInit(hCamera) + + # 释放帧缓存 + mvsdk.CameraAlignFree(pFrameBuffer) + +def main(): + try: + main_loop() + finally: + cv2.destroyAllWindows() + +main() diff --git a/python demo/cv_grab2.py b/python demo/cv_grab2.py new file mode 100644 index 0000000..1d257cb --- /dev/null +++ b/python demo/cv_grab2.py @@ -0,0 +1,127 @@ +#coding=utf-8 +import cv2 +import numpy as np +import mvsdk +import platform + +class Camera(object): + def __init__(self, DevInfo): + super(Camera, self).__init__() + self.DevInfo = DevInfo + self.hCamera = 0 + self.cap = None + self.pFrameBuffer = 0 + + def open(self): + if self.hCamera > 0: + return True + + # 打开相机 + hCamera = 0 + try: + hCamera = mvsdk.CameraInit(self.DevInfo, -1, -1) + except mvsdk.CameraException as e: + print("CameraInit Failed({}): {}".format(e.error_code, e.message) ) + return False + + # 获取相机特性描述 + cap = mvsdk.CameraGetCapability(hCamera) + + # 判断是黑白相机还是彩色相机 + monoCamera = (cap.sIspCapacity.bMonoSensor != 0) + + # 黑白相机让ISP直接输出MONO数据,而不是扩展成R=G=B的24位灰度 + if monoCamera: + mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_MONO8) + else: + mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_BGR8) + + # 计算RGB buffer所需的大小,这里直接按照相机的最大分辨率来分配 + FrameBufferSize = cap.sResolutionRange.iWidthMax * cap.sResolutionRange.iHeightMax * (1 if monoCamera else 3) + + # 分配RGB buffer,用来存放ISP输出的图像 + # 备注:从相机传输到PC端的是RAW数据,在PC端通过软件ISP转为RGB数据(如果是黑白相机就不需要转换格式,但是ISP还有其它处理,所以也需要分配这个buffer) + pFrameBuffer = mvsdk.CameraAlignMalloc(FrameBufferSize, 16) + + # 相机模式切换成连续采集 + mvsdk.CameraSetTriggerMode(hCamera, 0) + + # 手动曝光,曝光时间30ms + mvsdk.CameraSetAeState(hCamera, 0) + mvsdk.CameraSetExposureTime(hCamera, 30 * 1000) + + # 让SDK内部取图线程开始工作 + mvsdk.CameraPlay(hCamera) + + self.hCamera = hCamera + self.pFrameBuffer = pFrameBuffer + self.cap = cap + return True + + def close(self): + if self.hCamera > 0: + mvsdk.CameraUnInit(self.hCamera) + self.hCamera = 0 + + mvsdk.CameraAlignFree(self.pFrameBuffer) + self.pFrameBuffer = 0 + + def grab(self): + # 从相机取一帧图片 + hCamera = self.hCamera + pFrameBuffer = self.pFrameBuffer + try: + pRawData, FrameHead = mvsdk.CameraGetImageBuffer(hCamera, 200) + mvsdk.CameraImageProcess(hCamera, pRawData, pFrameBuffer, FrameHead) + mvsdk.CameraReleaseImageBuffer(hCamera, pRawData) + + # windows下取到的图像数据是上下颠倒的,以BMP格式存放。转换成opencv则需要上下翻转成正的 + # linux下直接输出正的,不需要上下翻转 + if platform.system() == "Windows": + mvsdk.CameraFlipFrameBuffer(pFrameBuffer, FrameHead, 1) + + # 此时图片已经存储在pFrameBuffer中,对于彩色相机pFrameBuffer=RGB数据,黑白相机pFrameBuffer=8位灰度数据 + # 把pFrameBuffer转换成opencv的图像格式以进行后续算法处理 + frame_data = (mvsdk.c_ubyte * FrameHead.uBytes).from_address(pFrameBuffer) + frame = np.frombuffer(frame_data, dtype=np.uint8) + frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth, 1 if FrameHead.uiMediaType == mvsdk.CAMERA_MEDIA_TYPE_MONO8 else 3) ) + return frame + except mvsdk.CameraException as e: + if e.error_code != mvsdk.CAMERA_STATUS_TIME_OUT: + print("CameraGetImageBuffer failed({}): {}".format(e.error_code, e.message) ) + return None + +def main_loop(): + # 枚举相机 + DevList = mvsdk.CameraEnumerateDevice() + nDev = len(DevList) + if nDev < 1: + print("No camera was found!") + return + + for i, DevInfo in enumerate(DevList): + print("{}: {} {}".format(i, DevInfo.GetFriendlyName(), DevInfo.GetPortType())) + + cams = [] + for i in map(lambda x: int(x), raw_input("Select cameras: ").split()): + cam = Camera(DevList[i]) + if cam.open(): + cams.append(cam) + + while (cv2.waitKey(1) & 0xFF) != ord('q'): + for cam in cams: + frame = cam.grab() + if frame is not None: + frame = cv2.resize(frame, (640,480), interpolation = cv2.INTER_LINEAR) + cv2.imshow("{} Press q to end".format(cam.DevInfo.GetFriendlyName()), frame) + + for cam in cams: + cam.close() + +def main(): + try: + main_loop() + finally: + cv2.destroyAllWindows() + +main() diff --git a/python demo/cv_grab_callback.py b/python demo/cv_grab_callback.py new file mode 100644 index 0000000..137868d --- /dev/null +++ b/python demo/cv_grab_callback.py @@ -0,0 +1,110 @@ +#coding=utf-8 +import cv2 +import numpy as np +import mvsdk +import time +import platform + +class App(object): + def __init__(self): + super(App, self).__init__() + self.pFrameBuffer = 0 + self.quit = False + + def main(self): + # 枚举相机 + DevList = mvsdk.CameraEnumerateDevice() + nDev = len(DevList) + if nDev < 1: + print("No camera was found!") + return + + for i, DevInfo in enumerate(DevList): + print("{}: {} {}".format(i, DevInfo.GetFriendlyName(), DevInfo.GetPortType())) + i = 0 if nDev == 1 else int(input("Select camera: ")) + DevInfo = DevList[i] + print(DevInfo) + + # 打开相机 + hCamera = 0 + try: + hCamera = mvsdk.CameraInit(DevInfo, -1, -1) + except mvsdk.CameraException as e: + print("CameraInit Failed({}): {}".format(e.error_code, e.message) ) + return + + # 获取相机特性描述 + cap = mvsdk.CameraGetCapability(hCamera) + + # 判断是黑白相机还是彩色相机 + monoCamera = (cap.sIspCapacity.bMonoSensor != 0) + + # 黑白相机让ISP直接输出MONO数据,而不是扩展成R=G=B的24位灰度 + if monoCamera: + mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_MONO8) + else: + mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_BGR8) + + # 相机模式切换成连续采集 + mvsdk.CameraSetTriggerMode(hCamera, 0) + + # 手动曝光,曝光时间30ms + mvsdk.CameraSetAeState(hCamera, 0) + mvsdk.CameraSetExposureTime(hCamera, 30 * 1000) + + # 让SDK内部取图线程开始工作 + mvsdk.CameraPlay(hCamera) + + # 计算RGB buffer所需的大小,这里直接按照相机的最大分辨率来分配 + FrameBufferSize = cap.sResolutionRange.iWidthMax * cap.sResolutionRange.iHeightMax * (1 if monoCamera else 3) + + # 分配RGB buffer,用来存放ISP输出的图像 + # 备注:从相机传输到PC端的是RAW数据,在PC端通过软件ISP转为RGB数据(如果是黑白相机就不需要转换格式,但是ISP还有其它处理,所以也需要分配这个buffer) + self.pFrameBuffer = mvsdk.CameraAlignMalloc(FrameBufferSize, 16) + + # 设置采集回调函数 + self.quit = False + mvsdk.CameraSetCallbackFunction(hCamera, self.GrabCallback, 0) + + # 等待退出 + while not self.quit: + time.sleep(0.1) + + # 关闭相机 + mvsdk.CameraUnInit(hCamera) + + # 释放帧缓存 + mvsdk.CameraAlignFree(self.pFrameBuffer) + + @mvsdk.method(mvsdk.CAMERA_SNAP_PROC) + def GrabCallback(self, hCamera, pRawData, pFrameHead, pContext): + FrameHead = pFrameHead[0] + pFrameBuffer = self.pFrameBuffer + + mvsdk.CameraImageProcess(hCamera, pRawData, pFrameBuffer, FrameHead) + mvsdk.CameraReleaseImageBuffer(hCamera, pRawData) + + # windows下取到的图像数据是上下颠倒的,以BMP格式存放。转换成opencv则需要上下翻转成正的 + # linux下直接输出正的,不需要上下翻转 + if platform.system() == "Windows": + mvsdk.CameraFlipFrameBuffer(pFrameBuffer, FrameHead, 1) + + # 此时图片已经存储在pFrameBuffer中,对于彩色相机pFrameBuffer=RGB数据,黑白相机pFrameBuffer=8位灰度数据 + # 把pFrameBuffer转换成opencv的图像格式以进行后续算法处理 + frame_data = (mvsdk.c_ubyte * FrameHead.uBytes).from_address(pFrameBuffer) + frame = np.frombuffer(frame_data, dtype=np.uint8) + frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth, 1 if FrameHead.uiMediaType == mvsdk.CAMERA_MEDIA_TYPE_MONO8 else 3) ) + + frame = cv2.resize(frame, (640,480), interpolation = cv2.INTER_LINEAR) + cv2.imshow("Press q to end", frame) + if (cv2.waitKey(1) & 0xFF) == ord('q'): + self.quit = True + +def main(): + try: + app = App() + app.main() + finally: + cv2.destroyAllWindows() + +main() diff --git a/python demo/grab.py b/python demo/grab.py new file mode 100644 index 0000000..59bfe2c --- /dev/null +++ b/python demo/grab.py @@ -0,0 +1,111 @@ +#coding=utf-8 +import mvsdk + +def main(): + # 枚举相机 + DevList = mvsdk.CameraEnumerateDevice() + nDev = len(DevList) + if nDev < 1: + print("No camera was found!") + return + + for i, DevInfo in enumerate(DevList): + print("{}: {} {}".format(i, DevInfo.GetFriendlyName(), DevInfo.GetPortType())) + i = 0 if nDev == 1 else int(input("Select camera: ")) + DevInfo = DevList[i] + print(DevInfo) + + # 打开相机 + hCamera = 0 + try: + hCamera = mvsdk.CameraInit(DevInfo, -1, -1) + except mvsdk.CameraException as e: + print("CameraInit Failed({}): {}".format(e.error_code, e.message) ) + return + + # 获取相机特性描述 + cap = mvsdk.CameraGetCapability(hCamera) + PrintCapbility(cap) + + # 判断是黑白相机还是彩色相机 + monoCamera = (cap.sIspCapacity.bMonoSensor != 0) + + # 黑白相机让ISP直接输出MONO数据,而不是扩展成R=G=B的24位灰度 + if monoCamera: + mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_MONO8) + + # 相机模式切换成连续采集 + mvsdk.CameraSetTriggerMode(hCamera, 0) + + # 手动曝光,曝光时间30ms + mvsdk.CameraSetAeState(hCamera, 0) + mvsdk.CameraSetExposureTime(hCamera, 30 * 1000) + + # 让SDK内部取图线程开始工作 + mvsdk.CameraPlay(hCamera) + + # 计算RGB buffer所需的大小,这里直接按照相机的最大分辨率来分配 + FrameBufferSize = cap.sResolutionRange.iWidthMax * cap.sResolutionRange.iHeightMax * (1 if monoCamera else 3) + + # 分配RGB buffer,用来存放ISP输出的图像 + # 备注:从相机传输到PC端的是RAW数据,在PC端通过软件ISP转为RGB数据(如果是黑白相机就不需要转换格式,但是ISP还有其它处理,所以也需要分配这个buffer) + pFrameBuffer = mvsdk.CameraAlignMalloc(FrameBufferSize, 16) + + # 从相机取一帧图片 + try: + pRawData, FrameHead = mvsdk.CameraGetImageBuffer(hCamera, 2000) + mvsdk.CameraImageProcess(hCamera, pRawData, pFrameBuffer, FrameHead) + mvsdk.CameraReleaseImageBuffer(hCamera, pRawData) + + # 此时图片已经存储在pFrameBuffer中,对于彩色相机pFrameBuffer=RGB数据,黑白相机pFrameBuffer=8位灰度数据 + # 该示例中我们只是把图片保存到硬盘文件中 + status = mvsdk.CameraSaveImage(hCamera, "./grab.bmp", pFrameBuffer, FrameHead, mvsdk.FILE_BMP, 100) + if status == mvsdk.CAMERA_STATUS_SUCCESS: + print("Save image successfully. image_size = {}X{}".format(FrameHead.iWidth, FrameHead.iHeight) ) + else: + print("Save image failed. err={}".format(status) ) + except mvsdk.CameraException as e: + print("CameraGetImageBuffer failed({}): {}".format(e.error_code, e.message) ) + + # 关闭相机 + mvsdk.CameraUnInit(hCamera) + + # 释放帧缓存 + mvsdk.CameraAlignFree(pFrameBuffer) + +def PrintCapbility(cap): + for i in range(cap.iTriggerDesc): + desc = cap.pTriggerDesc[i] + print("{}: {}".format(desc.iIndex, desc.GetDescription()) ) + for i in range(cap.iImageSizeDesc): + desc = cap.pImageSizeDesc[i] + print("{}: {}".format(desc.iIndex, desc.GetDescription()) ) + for i in range(cap.iClrTempDesc): + desc = cap.pClrTempDesc[i] + print("{}: {}".format(desc.iIndex, desc.GetDescription()) ) + for i in range(cap.iMediaTypeDesc): + desc = cap.pMediaTypeDesc[i] + print("{}: {}".format(desc.iIndex, desc.GetDescription()) ) + for i in range(cap.iFrameSpeedDesc): + desc = cap.pFrameSpeedDesc[i] + print("{}: {}".format(desc.iIndex, desc.GetDescription()) ) + for i in range(cap.iPackLenDesc): + desc = cap.pPackLenDesc[i] + print("{}: {}".format(desc.iIndex, desc.GetDescription()) ) + for i in range(cap.iPresetLut): + desc = cap.pPresetLutDesc[i] + print("{}: {}".format(desc.iIndex, desc.GetDescription()) ) + for i in range(cap.iAeAlmSwDesc): + desc = cap.pAeAlmSwDesc[i] + print("{}: {}".format(desc.iIndex, desc.GetDescription()) ) + for i in range(cap.iAeAlmHdDesc): + desc = cap.pAeAlmHdDesc[i] + print("{}: {}".format(desc.iIndex, desc.GetDescription()) ) + for i in range(cap.iBayerDecAlmSwDesc): + desc = cap.pBayerDecAlmSwDesc[i] + print("{}: {}".format(desc.iIndex, desc.GetDescription()) ) + for i in range(cap.iBayerDecAlmHdDesc): + desc = cap.pBayerDecAlmHdDesc[i] + print("{}: {}".format(desc.iIndex, desc.GetDescription()) ) + +main() diff --git a/python demo/mvsdk.py b/python demo/mvsdk.py new file mode 100644 index 0000000..6a3af90 --- /dev/null +++ b/python demo/mvsdk.py @@ -0,0 +1,2454 @@ +#coding=utf-8 +import platform +from ctypes import * +from threading import local + +# 回调函数类型 +CALLBACK_FUNC_TYPE = None + +# SDK动态库 +_sdk = None + +def _Init(): + global _sdk + global CALLBACK_FUNC_TYPE + + is_win = (platform.system() == "Windows") + is_x86 = (platform.architecture()[0] == '32bit') + + if is_win: + _sdk = windll.MVCAMSDK if is_x86 else windll.MVCAMSDK_X64 + CALLBACK_FUNC_TYPE = WINFUNCTYPE + else: + _sdk = cdll.LoadLibrary("libMVSDK.so") + CALLBACK_FUNC_TYPE = CFUNCTYPE + +_Init() + +#-------------------------------------------类型定义-------------------------------------------------- + +# 状态码定义 +CAMERA_STATUS_SUCCESS = 0 # 操作成功 +CAMERA_STATUS_FAILED = -1 # 操作失败 +CAMERA_STATUS_INTERNAL_ERROR = -2 # 内部错误 +CAMERA_STATUS_UNKNOW = -3 # 未知错误 +CAMERA_STATUS_NOT_SUPPORTED = -4 # 不支持该功能 +CAMERA_STATUS_NOT_INITIALIZED = -5 # 初始化未完成 +CAMERA_STATUS_PARAMETER_INVALID = -6 # 参数无效 +CAMERA_STATUS_PARAMETER_OUT_OF_BOUND = -7 # 参数越界 +CAMERA_STATUS_UNENABLED = -8 # 未使能 +CAMERA_STATUS_USER_CANCEL = -9 # 用户手动取消了,比如roi面板点击取消,返回 +CAMERA_STATUS_PATH_NOT_FOUND = -10 # 注册表中没有找到对应的路径 +CAMERA_STATUS_SIZE_DISMATCH = -11 # 获得图像数据长度和定义的尺寸不匹配 +CAMERA_STATUS_TIME_OUT = -12 # 超时错误 +CAMERA_STATUS_IO_ERROR = -13 # 硬件IO错误 +CAMERA_STATUS_COMM_ERROR = -14 # 通讯错误 +CAMERA_STATUS_BUS_ERROR = -15 # 总线错误 +CAMERA_STATUS_NO_DEVICE_FOUND = -16 # 没有发现设备 +CAMERA_STATUS_NO_LOGIC_DEVICE_FOUND = -17 # 未找到逻辑设备 +CAMERA_STATUS_DEVICE_IS_OPENED = -18 # 设备已经打开 +CAMERA_STATUS_DEVICE_IS_CLOSED = -19 # 设备已经关闭 +CAMERA_STATUS_DEVICE_VEDIO_CLOSED = -20 # 没有打开设备视频,调用录像相关的函数时,如果相机视频没有打开,则回返回该错误。 +CAMERA_STATUS_NO_MEMORY = -21 # 没有足够系统内存 +CAMERA_STATUS_FILE_CREATE_FAILED = -22 # 创建文件失败 +CAMERA_STATUS_FILE_INVALID = -23 # 文件格式无效 +CAMERA_STATUS_WRITE_PROTECTED = -24 # 写保护,不可写 +CAMERA_STATUS_GRAB_FAILED = -25 # 数据采集失败 +CAMERA_STATUS_LOST_DATA = -26 # 数据丢失,不完整 +CAMERA_STATUS_EOF_ERROR = -27 # 未接收到帧结束符 +CAMERA_STATUS_BUSY = -28 # 正忙(上一次操作还在进行中),此次操作不能进行 +CAMERA_STATUS_WAIT = -29 # 需要等待(进行操作的条件不成立),可以再次尝试 +CAMERA_STATUS_IN_PROCESS = -30 # 正在进行,已经被操作过 +CAMERA_STATUS_IIC_ERROR = -31 # IIC传输错误 +CAMERA_STATUS_SPI_ERROR = -32 # SPI传输错误 +CAMERA_STATUS_USB_CONTROL_ERROR = -33 # USB控制传输错误 +CAMERA_STATUS_USB_BULK_ERROR = -34 # USB BULK传输错误 +CAMERA_STATUS_SOCKET_INIT_ERROR = -35 # 网络传输套件初始化失败 +CAMERA_STATUS_GIGE_FILTER_INIT_ERROR = -36 # 网络相机内核过滤驱动初始化失败,请检查是否正确安装了驱动,或者重新安装。 +CAMERA_STATUS_NET_SEND_ERROR = -37 # 网络数据发送错误 +CAMERA_STATUS_DEVICE_LOST = -38 # 与网络相机失去连接,心跳检测超时 +CAMERA_STATUS_DATA_RECV_LESS = -39 # 接收到的字节数比请求的少 +CAMERA_STATUS_FUNCTION_LOAD_FAILED = -40 # 从文件中加载程序失败 +CAMERA_STATUS_CRITICAL_FILE_LOST = -41 # 程序运行所必须的文件丢失。 +CAMERA_STATUS_SENSOR_ID_DISMATCH = -42 # 固件和程序不匹配,原因是下载了错误的固件。 +CAMERA_STATUS_OUT_OF_RANGE = -43 # 参数超出有效范围。 +CAMERA_STATUS_REGISTRY_ERROR = -44 # 安装程序注册错误。请重新安装程序,或者运行安装目录Setup/Installer.exe +CAMERA_STATUS_ACCESS_DENY = -45 # 禁止访问。指定相机已经被其他程序占用时,再申请访问该相机,会返回该状态。(一个相机不能被多个程序同时访问) +#AIA的标准兼容的错误码 +CAMERA_AIA_PACKET_RESEND = 0x0100 #该帧需要重传 +CAMERA_AIA_NOT_IMPLEMENTED = 0x8001 #设备不支持的命令 +CAMERA_AIA_INVALID_PARAMETER = 0x8002 #命令参数非法 +CAMERA_AIA_INVALID_ADDRESS = 0x8003 #不可访问的地址 +CAMERA_AIA_WRITE_PROTECT = 0x8004 #访问的对象不可写 +CAMERA_AIA_BAD_ALIGNMENT = 0x8005 #访问的地址没有按照要求对齐 +CAMERA_AIA_ACCESS_DENIED = 0x8006 #没有访问权限 +CAMERA_AIA_BUSY = 0x8007 #命令正在处理中 +CAMERA_AIA_DEPRECATED = 0x8008 #0x8008-0x0800B 0x800F 该指令已经废弃 +CAMERA_AIA_PACKET_UNAVAILABLE = 0x800C #包无效 +CAMERA_AIA_DATA_OVERRUN = 0x800D #数据溢出,通常是收到的数据比需要的多 +CAMERA_AIA_INVALID_HEADER = 0x800E #数据包头部中某些区域与协议不匹配 +CAMERA_AIA_PACKET_NOT_YET_AVAILABLE = 0x8010 #图像分包数据还未准备好,多用于触发模式,应用程序访问超时 +CAMERA_AIA_PACKET_AND_PREV_REMOVED_FROM_MEMORY = 0x8011 #需要访问的分包已经不存在。多用于重传时数据已经不在缓冲区中 +CAMERA_AIA_PACKET_REMOVED_FROM_MEMORY = 0x8012 #CAMERA_AIA_PACKET_AND_PREV_REMOVED_FROM_MEMORY +CAMERA_AIA_NO_REF_TIME = 0x0813 #没有参考时钟源。多用于时间同步的命令执行时 +CAMERA_AIA_PACKET_TEMPORARILY_UNAVAILABLE = 0x0814 #由于信道带宽问题,当前分包暂时不可用,需稍后进行访问 +CAMERA_AIA_OVERFLOW = 0x0815 #设备端数据溢出,通常是队列已满 +CAMERA_AIA_ACTION_LATE = 0x0816 #命令执行已经超过有效的指定时间 +CAMERA_AIA_ERROR = 0x8FFF #错误 + +# 图像格式定义 +CAMERA_MEDIA_TYPE_MONO = 0x01000000 +CAMERA_MEDIA_TYPE_RGB = 0x02000000 +CAMERA_MEDIA_TYPE_COLOR = 0x02000000 +CAMERA_MEDIA_TYPE_OCCUPY1BIT = 0x00010000 +CAMERA_MEDIA_TYPE_OCCUPY2BIT = 0x00020000 +CAMERA_MEDIA_TYPE_OCCUPY4BIT = 0x00040000 +CAMERA_MEDIA_TYPE_OCCUPY8BIT = 0x00080000 +CAMERA_MEDIA_TYPE_OCCUPY10BIT = 0x000A0000 +CAMERA_MEDIA_TYPE_OCCUPY12BIT = 0x000C0000 +CAMERA_MEDIA_TYPE_OCCUPY16BIT = 0x00100000 +CAMERA_MEDIA_TYPE_OCCUPY24BIT = 0x00180000 +CAMERA_MEDIA_TYPE_OCCUPY32BIT = 0x00200000 +CAMERA_MEDIA_TYPE_OCCUPY36BIT = 0x00240000 +CAMERA_MEDIA_TYPE_OCCUPY48BIT = 0x00300000 +CAMERA_MEDIA_TYPE_EFFECTIVE_PIXEL_SIZE_MASK = 0x00FF0000 +CAMERA_MEDIA_TYPE_EFFECTIVE_PIXEL_SIZE_SHIFT = 16 +CAMERA_MEDIA_TYPE_ID_MASK = 0x0000FFFF +CAMERA_MEDIA_TYPE_COUNT = 0x46 + +#mono +CAMERA_MEDIA_TYPE_MONO1P = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY1BIT | 0x0037) +CAMERA_MEDIA_TYPE_MONO2P = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY2BIT | 0x0038) +CAMERA_MEDIA_TYPE_MONO4P = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY4BIT | 0x0039) +CAMERA_MEDIA_TYPE_MONO8 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY8BIT | 0x0001) +CAMERA_MEDIA_TYPE_MONO8S = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY8BIT | 0x0002) +CAMERA_MEDIA_TYPE_MONO10 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x0003) +CAMERA_MEDIA_TYPE_MONO10_PACKED = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY12BIT | 0x0004) +CAMERA_MEDIA_TYPE_MONO12 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x0005) +CAMERA_MEDIA_TYPE_MONO12_PACKED = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY12BIT | 0x0006) +CAMERA_MEDIA_TYPE_MONO14 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x0025) +CAMERA_MEDIA_TYPE_MONO16 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x0007) + +# Bayer +CAMERA_MEDIA_TYPE_BAYGR8 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY8BIT | 0x0008) +CAMERA_MEDIA_TYPE_BAYRG8 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY8BIT | 0x0009) +CAMERA_MEDIA_TYPE_BAYGB8 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY8BIT | 0x000A) +CAMERA_MEDIA_TYPE_BAYBG8 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY8BIT | 0x000B) + +CAMERA_MEDIA_TYPE_BAYGR10_MIPI = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY10BIT | 0x0026) +CAMERA_MEDIA_TYPE_BAYRG10_MIPI = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY10BIT | 0x0027) +CAMERA_MEDIA_TYPE_BAYGB10_MIPI = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY10BIT | 0x0028) +CAMERA_MEDIA_TYPE_BAYBG10_MIPI = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY10BIT | 0x0029) + +CAMERA_MEDIA_TYPE_BAYGR10 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x000C) +CAMERA_MEDIA_TYPE_BAYRG10 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x000D) +CAMERA_MEDIA_TYPE_BAYGB10 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x000E) +CAMERA_MEDIA_TYPE_BAYBG10 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x000F) + +CAMERA_MEDIA_TYPE_BAYGR12 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x0010) +CAMERA_MEDIA_TYPE_BAYRG12 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x0011) +CAMERA_MEDIA_TYPE_BAYGB12 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x0012) +CAMERA_MEDIA_TYPE_BAYBG12 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x0013) + +CAMERA_MEDIA_TYPE_BAYGR10_PACKED = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY12BIT | 0x0026) +CAMERA_MEDIA_TYPE_BAYRG10_PACKED = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY12BIT | 0x0027) +CAMERA_MEDIA_TYPE_BAYGB10_PACKED = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY12BIT | 0x0028) +CAMERA_MEDIA_TYPE_BAYBG10_PACKED = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY12BIT | 0x0029) + +CAMERA_MEDIA_TYPE_BAYGR12_PACKED = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY12BIT | 0x002A) +CAMERA_MEDIA_TYPE_BAYRG12_PACKED = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY12BIT | 0x002B) +CAMERA_MEDIA_TYPE_BAYGB12_PACKED = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY12BIT | 0x002C) +CAMERA_MEDIA_TYPE_BAYBG12_PACKED = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY12BIT | 0x002D) + +CAMERA_MEDIA_TYPE_BAYGR16 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x002E) +CAMERA_MEDIA_TYPE_BAYRG16 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x002F) +CAMERA_MEDIA_TYPE_BAYGB16 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x0030) +CAMERA_MEDIA_TYPE_BAYBG16 = (CAMERA_MEDIA_TYPE_MONO | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x0031) + +# RGB +CAMERA_MEDIA_TYPE_RGB8 = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY24BIT | 0x0014) +CAMERA_MEDIA_TYPE_BGR8 = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY24BIT | 0x0015) +CAMERA_MEDIA_TYPE_RGBA8 = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY32BIT | 0x0016) +CAMERA_MEDIA_TYPE_BGRA8 = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY32BIT | 0x0017) +CAMERA_MEDIA_TYPE_RGB10 = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY48BIT | 0x0018) +CAMERA_MEDIA_TYPE_BGR10 = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY48BIT | 0x0019) +CAMERA_MEDIA_TYPE_RGB12 = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY48BIT | 0x001A) +CAMERA_MEDIA_TYPE_BGR12 = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY48BIT | 0x001B) +CAMERA_MEDIA_TYPE_RGB16 = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY48BIT | 0x0033) +CAMERA_MEDIA_TYPE_RGB10V1_PACKED = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY32BIT | 0x001C) +CAMERA_MEDIA_TYPE_RGB10P32 = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY32BIT | 0x001D) +CAMERA_MEDIA_TYPE_RGB12V1_PACKED = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY36BIT | 0X0034) +CAMERA_MEDIA_TYPE_RGB565P = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x0035) +CAMERA_MEDIA_TYPE_BGR565P = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0X0036) + +# YUV and YCbCr +CAMERA_MEDIA_TYPE_YUV411_8_UYYVYY = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY12BIT | 0x001E) +CAMERA_MEDIA_TYPE_YUV422_8_UYVY = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x001F) +CAMERA_MEDIA_TYPE_YUV422_8 = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x0032) +CAMERA_MEDIA_TYPE_YUV8_UYV = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY24BIT | 0x0020) +CAMERA_MEDIA_TYPE_YCBCR8_CBYCR = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY24BIT | 0x003A) +#CAMERA_MEDIA_TYPE_YCBCR422_8 : YYYYCbCrCbCr +CAMERA_MEDIA_TYPE_YCBCR422_8 = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x003B) +CAMERA_MEDIA_TYPE_YCBCR422_8_CBYCRY = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x0043) +CAMERA_MEDIA_TYPE_YCBCR411_8_CBYYCRYY = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY12BIT | 0x003C) +CAMERA_MEDIA_TYPE_YCBCR601_8_CBYCR = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY24BIT | 0x003D) +CAMERA_MEDIA_TYPE_YCBCR601_422_8 = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x003E) +CAMERA_MEDIA_TYPE_YCBCR601_422_8_CBYCRY = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x0044) +CAMERA_MEDIA_TYPE_YCBCR601_411_8_CBYYCRYY = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY12BIT | 0x003F) +CAMERA_MEDIA_TYPE_YCBCR709_8_CBYCR = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY24BIT | 0x0040) +CAMERA_MEDIA_TYPE_YCBCR709_422_8 = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x0041) +CAMERA_MEDIA_TYPE_YCBCR709_422_8_CBYCRY = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY16BIT | 0x0045) +CAMERA_MEDIA_TYPE_YCBCR709_411_8_CBYYCRYY = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY12BIT | 0x0042) + +# RGB Planar +CAMERA_MEDIA_TYPE_RGB8_PLANAR = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY24BIT | 0x0021) +CAMERA_MEDIA_TYPE_RGB10_PLANAR = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY48BIT | 0x0022) +CAMERA_MEDIA_TYPE_RGB12_PLANAR = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY48BIT | 0x0023) +CAMERA_MEDIA_TYPE_RGB16_PLANAR = (CAMERA_MEDIA_TYPE_COLOR | CAMERA_MEDIA_TYPE_OCCUPY48BIT | 0x0024) + +# 保存格式 +FILE_JPG = 1 +FILE_BMP = 2 +FILE_RAW = 4 +FILE_PNG = 8 +FILE_BMP_8BIT = 16 +FILE_PNG_8BIT = 32 +FILE_RAW_16BIT = 64 + +# 触发信号 +EXT_TRIG_LEADING_EDGE = 0 +EXT_TRIG_TRAILING_EDGE = 1 +EXT_TRIG_HIGH_LEVEL = 2 +EXT_TRIG_LOW_LEVEL = 3 +EXT_TRIG_DOUBLE_EDGE = 4 + +# IO模式 +IOMODE_TRIG_INPUT = 0 +IOMODE_STROBE_OUTPUT = 1 +IOMODE_GP_INPUT = 2 +IOMODE_GP_OUTPUT = 3 +IOMODE_PWM_OUTPUT = 4 + + +# 相机操作异常信息 +class CameraException(Exception): + """docstring for CameraException""" + def __init__(self, error_code): + super(CameraException, self).__init__() + self.error_code = error_code + self.message = CameraGetErrorString(error_code) + + def __str__(self): + return 'error_code:{} message:{}'.format(self.error_code, self.message) + +class MvStructure(Structure): + def __str__(self): + strs = [] + for field in self._fields_: + name = field[0] + value = getattr(self, name) + if isinstance(value, type(b'')): + value = _string_buffer_to_str(value) + strs.append("{}:{}".format(name, value)) + return '\n'.join(strs) + + def __repr__(self): + return self.__str__() + + def clone(self): + obj = type(self)() + memmove(byref(obj), byref(self), sizeof(self)) + return obj + +# 相机的设备信息,只读信息,请勿修改 +class tSdkCameraDevInfo(MvStructure): + _fields_ = [("acProductSeries", c_char * 32), #产品系列 + ("acProductName", c_char * 32), #产品名称 + ("acFriendlyName", c_char * 32), #产品昵称 + ("acLinkName", c_char * 32), #内核符号连接名,内部使用 + ("acDriverVersion", c_char * 32), #驱动版本 + ("acSensorType", c_char * 32), #sensor类型 + ("acPortType", c_char * 32), #接口类型 + ("acSn", c_char * 32), #产品唯一序列号 + ("uInstance", c_uint)] #该型号相机在该电脑上的实例索引号,用于区分同型号多相机 + + def GetProductSeries(self): + return _string_buffer_to_str(self.acProductSeries) + def GetProductName(self): + return _string_buffer_to_str(self.acProductName) + def GetFriendlyName(self): + return _string_buffer_to_str(self.acFriendlyName) + def GetLinkName(self): + return _string_buffer_to_str(self.acLinkName) + def GetDriverVersion(self): + return _string_buffer_to_str(self.acDriverVersion) + def GetSensorType(self): + return _string_buffer_to_str(self.acSensorType) + def GetPortType(self): + return _string_buffer_to_str(self.acPortType) + def GetSn(self): + return _string_buffer_to_str(self.acSn) + +# 相机的分辨率设定范围 +class tSdkResolutionRange(MvStructure): + _fields_ = [("iHeightMax", c_int), #图像最大高度 + ("iHeightMin", c_int), #图像最小高度 + ("iWidthMax", c_int), #图像最大宽度 + ("iWidthMin", c_int), #图像最小宽度 + ("uSkipModeMask", c_uint), #SKIP模式掩码,为0,表示不支持SKIP 。bit0为1,表示支持SKIP 2x2 bit1为1,表示支持SKIP 3x3.... + ("uBinSumModeMask", c_uint), #BIN(求和)模式掩码,为0,表示不支持BIN 。bit0为1,表示支持BIN 2x2 bit1为1,表示支持BIN 3x3.... + ("uBinAverageModeMask", c_uint),#BIN(求均值)模式掩码,为0,表示不支持BIN 。bit0为1,表示支持BIN 2x2 bit1为1,表示支持BIN 3x3.... + ("uResampleMask", c_uint)] #硬件重采样的掩码 + +#相机的分辨率描述 +class tSdkImageResolution(MvStructure): + _fields_ = [ + ("iIndex", c_int), # 索引号,[0,N]表示预设的分辨率(N 为预设分辨率的最大个数,一般不超过20),OXFF 表示自定义分辨率(ROI) + ("acDescription", c_char * 32), # 该分辨率的描述信息。仅预设分辨率时该信息有效。自定义分辨率可忽略该信息 + ("uBinSumMode", c_uint), # BIN(求和)的模式,范围不能超过tSdkResolutionRange中uBinSumModeMask + ("uBinAverageMode", c_uint), # BIN(求均值)的模式,范围不能超过tSdkResolutionRange中uBinAverageModeMask + ("uSkipMode", c_uint), # 是否SKIP的尺寸,为0表示禁止SKIP模式,范围不能超过tSdkResolutionRange中uSkipModeMask + ("uResampleMask", c_uint), # 硬件重采样的掩码 + ("iHOffsetFOV", c_int), # 采集视场相对于Sensor最大视场左上角的垂直偏移 + ("iVOffsetFOV", c_int), # 采集视场相对于Sensor最大视场左上角的水平偏移 + ("iWidthFOV", c_int), # 采集视场的宽度 + ("iHeightFOV", c_int), # 采集视场的高度 + ("iWidth", c_int), # 相机最终输出的图像的宽度 + ("iHeight", c_int), # 相机最终输出的图像的高度 + ("iWidthZoomHd", c_int), # 硬件缩放的宽度,不需要进行此操作的分辨率,此变量设置为0. + ("iHeightZoomHd", c_int), # 硬件缩放的高度,不需要进行此操作的分辨率,此变量设置为0. + ("iWidthZoomSw", c_int), # 软件缩放的宽度,不需要进行此操作的分辨率,此变量设置为0. + ("iHeightZoomSw", c_int), # 软件缩放的高度,不需要进行此操作的分辨率,此变量设置为0. + ] + + def GetDescription(self): + return _string_buffer_to_str(self.acDescription) + +#相机白平衡模式描述信息 +class tSdkColorTemperatureDes(MvStructure): + _fields_ = [ + ("iIndex", c_int), # 模式索引号 + ("acDescription", c_char * 32), # 描述信息 + ] + + def GetDescription(self): + return _string_buffer_to_str(self.acDescription) + +#相机帧率描述信息 +class tSdkFrameSpeed(MvStructure): + _fields_ = [ + ("iIndex", c_int), # 帧率索引号,一般0对应于低速模式,1对应于普通模式,2对应于高速模式 + ("acDescription", c_char * 32), # 描述信息 + ] + + def GetDescription(self): + return _string_buffer_to_str(self.acDescription) + +#相机曝光功能范围定义 +class tSdkExpose(MvStructure): + _fields_ = [ + ("uiTargetMin", c_uint), #自动曝光亮度目标最小值 + ("uiTargetMax", c_uint), #自动曝光亮度目标最大值 + ("uiAnalogGainMin", c_uint), #模拟增益的最小值,单位为fAnalogGainStep中定义 + ("uiAnalogGainMax", c_uint), #模拟增益的最大值,单位为fAnalogGainStep中定义 + ("fAnalogGainStep", c_float), #模拟增益每增加1,对应的增加的放大倍数。例如,uiAnalogGainMin一般为16,fAnalogGainStep一般为0.125,那么最小放大倍数就是16*0.125 = 2倍 + ("uiExposeTimeMin", c_uint), #手动模式下,曝光时间的最小值,单位:行。根据CameraGetExposureLineTime可以获得一行对应的时间(微秒),从而得到整帧的曝光时间 + ("uiExposeTimeMax", c_uint), #手动模式下,曝光时间的最大值,单位:行 + ] + +#触发模式描述 +class tSdkTrigger(MvStructure): + _fields_ = [ + ("iIndex", c_int), # 模式索引号 + ("acDescription", c_char * 32), # 描述信息 + ] + + def GetDescription(self): + return _string_buffer_to_str(self.acDescription) + +#传输分包大小描述(主要是针对网络相机有效) +class tSdkPackLength(MvStructure): + _fields_ = [ + ("iIndex", c_int), # 模式索引号 + ("acDescription", c_char * 32), # 描述信息 + ("iPackSize", c_uint), + ] + + def GetDescription(self): + return _string_buffer_to_str(self.acDescription) + +#预设的LUT表描述 +class tSdkPresetLut(MvStructure): + _fields_ = [ + ("iIndex", c_int), # 编号 + ("acDescription", c_char * 32), # 描述信息 + ] + + def GetDescription(self): + return _string_buffer_to_str(self.acDescription) + +#AE算法描述 +class tSdkAeAlgorithm(MvStructure): + _fields_ = [ + ("iIndex", c_int), # 编号 + ("acDescription", c_char * 32), # 描述信息 + ] + + def GetDescription(self): + return _string_buffer_to_str(self.acDescription) + +#RAW转RGB算法描述 +class tSdkBayerDecodeAlgorithm(MvStructure): + _fields_ = [ + ("iIndex", c_int), # 编号 + ("acDescription", c_char * 32), # 描述信息 + ] + + def GetDescription(self): + return _string_buffer_to_str(self.acDescription) + +#帧率统计信息 +class tSdkFrameStatistic(MvStructure): + _fields_ = [ + ("iTotal", c_int), #当前采集的总帧数(包括错误帧) + ("iCapture", c_int), #当前采集的有效帧的数量 + ("iLost", c_int), #当前丢帧的数量 + ] + +#相机输出的图像数据格式 +class tSdkMediaType(MvStructure): + _fields_ = [ + ("iIndex", c_int), # 格式种类编号 + ("acDescription", c_char * 32), # 描述信息 + ("iMediaType", c_uint), # 对应的图像格式编码,如CAMERA_MEDIA_TYPE_BAYGR8。 + ] + + def GetDescription(self): + return _string_buffer_to_str(self.acDescription) + +#伽马的设定范围 +class tGammaRange(MvStructure): + _fields_ = [ + ("iMin", c_int), #最小值 + ("iMax", c_int), #最大值 + ] + +#对比度的设定范围 +class tContrastRange(MvStructure): + _fields_ = [ + ("iMin", c_int), #最小值 + ("iMax", c_int), #最大值 + ] + +#RGB三通道数字增益的设定范围 +class tRgbGainRange(MvStructure): + _fields_ = [ + ("iRGainMin", c_int), #红色增益的最小值 + ("iRGainMax", c_int), #红色增益的最大值 + ("iGGainMin", c_int), #绿色增益的最小值 + ("iGGainMax", c_int), #绿色增益的最大值 + ("iBGainMin", c_int), #蓝色增益的最小值 + ("iBGainMax", c_int), #蓝色增益的最大值 + ] + +#饱和度设定的范围 +class tSaturationRange(MvStructure): + _fields_ = [ + ("iMin", c_int), #最小值 + ("iMax", c_int), #最大值 + ] + +#锐化的设定范围 +class tSharpnessRange(MvStructure): + _fields_ = [ + ("iMin", c_int), #最小值 + ("iMax", c_int), #最大值 + ] + +#ISP模块的使能信息 +class tSdkIspCapacity(MvStructure): + _fields_ = [ + ("bMonoSensor", c_int), #表示该型号相机是否为黑白相机,如果是黑白相机,则颜色相关的功能都无法调节 + ("bWbOnce", c_int), #表示该型号相机是否支持手动白平衡功能 + ("bAutoWb", c_int), #表示该型号相机是否支持自动白平衡功能 + ("bAutoExposure", c_int), #表示该型号相机是否支持自动曝光功能 + ("bManualExposure", c_int), #表示该型号相机是否支持手动曝光功能 + ("bAntiFlick", c_int), #表示该型号相机是否支持抗频闪功能 + ("bDeviceIsp", c_int), #表示该型号相机是否支持硬件ISP功能 + ("bForceUseDeviceIsp", c_int), #bDeviceIsp和bForceUseDeviceIsp同时为TRUE时,表示强制只用硬件ISP,不可取消。 + ("bZoomHD", c_int), #相机硬件是否支持图像缩放输出(只能是缩小)。 + ] + +# 定义整合的设备描述信息,这些信息可以用于动态构建UI +class tSdkCameraCapbility(MvStructure): + _fields_ = [ + ("pTriggerDesc", POINTER(tSdkTrigger)), + ("iTriggerDesc", c_int), #触发模式的个数,即pTriggerDesc数组的大小 + ("pImageSizeDesc", POINTER(tSdkImageResolution)), + ("iImageSizeDesc", c_int), #预设分辨率的个数,即pImageSizeDesc数组的大小 + ("pClrTempDesc", POINTER(tSdkColorTemperatureDes)), + ("iClrTempDesc", c_int), #预设色温个数 + ("pMediaTypeDesc", POINTER(tSdkMediaType)), + ("iMediaTypeDesc", c_int), #相机输出图像格式的种类个数,即pMediaTypeDesc数组的大小。 + ("pFrameSpeedDesc", POINTER(tSdkFrameSpeed)), #可调节帧速类型,对应界面上普通 高速 和超级三种速度设置 + ("iFrameSpeedDesc", c_int), #可调节帧速类型的个数,即pFrameSpeedDesc数组的大小。 + ("pPackLenDesc", POINTER(tSdkPackLength)), #传输包长度,一般用于网络设备 + ("iPackLenDesc", c_int), #可供选择的传输分包长度的个数,即pPackLenDesc数组的大小。 + ("iOutputIoCounts", c_int), #可编程输出IO的个数 + ("iInputIoCounts", c_int), #可编程输入IO的个数 + ("pPresetLutDesc", POINTER(tSdkPresetLut)), #相机预设的LUT表 + ("iPresetLut", c_int), #相机预设的LUT表的个数,即pPresetLutDesc数组的大小 + ("iUserDataMaxLen", c_int), #指示该相机中用于保存用户数据区的最大长度。为0表示无。 + ("bParamInDevice", c_int), #指示该设备是否支持从设备中读写参数组。1为支持,0不支持。 + ("pAeAlmSwDesc", POINTER(tSdkAeAlgorithm)),#软件自动曝光算法描述 + ("iAeAlmSwDesc", c_int), #软件自动曝光算法个数 + ("pAeAlmHdDesc", POINTER(tSdkAeAlgorithm)),#硬件自动曝光算法描述,为NULL表示不支持硬件自动曝光 + ("iAeAlmHdDesc", c_int), #硬件自动曝光算法个数,为0表示不支持硬件自动曝光 + ("pBayerDecAlmSwDesc", POINTER(tSdkBayerDecodeAlgorithm)),#软件Bayer转换为RGB数据的算法描述 + ("iBayerDecAlmSwDesc", c_int), #软件Bayer转换为RGB数据的算法个数 + ("pBayerDecAlmHdDesc", POINTER(tSdkBayerDecodeAlgorithm)),#硬件Bayer转换为RGB数据的算法描述,为NULL表示不支持 + ("iBayerDecAlmHdDesc", c_int), #硬件Bayer转换为RGB数据的算法个数,为0表示不支持 + + # 图像参数的调节范围定义,用于动态构建UI + ("sExposeDesc", tSdkExpose), #曝光的范围值 + ("sResolutionRange", tSdkResolutionRange), #分辨率范围描述 + ("sRgbGainRange", tRgbGainRange), #图像数字增益范围描述 + ("sSaturationRange", tSaturationRange), #饱和度范围描述 + ("sGammaRange", tGammaRange), #伽马范围描述 + ("sContrastRange", tContrastRange), #对比度范围描述 + ("sSharpnessRange", tSharpnessRange), #锐化范围描述 + ("sIspCapacity", tSdkIspCapacity), #ISP能力描述 + ] + +#图像帧头信息 +class tSdkFrameHead(MvStructure): + _fields_ = [ + ("uiMediaType", c_uint), # 图像格式,Image Format + ("uBytes", c_uint), # 图像数据字节数,Total bytes + ("iWidth", c_int), # 宽度 Image height + ("iHeight", c_int), # 高度 Image width + ("iWidthZoomSw", c_int), # 软件缩放的宽度,不需要进行软件裁剪的图像,此变量设置为0. + ("iHeightZoomSw", c_int), # 软件缩放的高度,不需要进行软件裁剪的图像,此变量设置为0. + ("bIsTrigger", c_int), # 指示是否为触发帧 is trigger + ("uiTimeStamp", c_uint), # 该帧的采集时间,单位0.1毫秒 + ("uiExpTime", c_uint), # 当前图像的曝光值,单位为微秒us + ("fAnalogGain", c_float), # 当前图像的模拟增益倍数 + ("iGamma", c_int), # 该帧图像的伽马设定值,仅当LUT模式为动态参数生成时有效,其余模式下为-1 + ("iContrast", c_int), # 该帧图像的对比度设定值,仅当LUT模式为动态参数生成时有效,其余模式下为-1 + ("iSaturation", c_int), # 该帧图像的饱和度设定值,对于黑白相机无意义,为0 + ("fRgain", c_float), # 该帧图像处理的红色数字增益倍数,对于黑白相机无意义,为1 + ("fGgain", c_float), # 该帧图像处理的绿色数字增益倍数,对于黑白相机无意义,为1 + ("fBgain", c_float), # 该帧图像处理的蓝色数字增益倍数,对于黑白相机无意义,为1 + ] + +# Grabber统计信息 +class tSdkGrabberStat(MvStructure): + _fields_ = [ + ("Width", c_int), # 帧图像大小 + ("Height", c_int), # 帧图像大小 + ("Disp", c_int), # 显示帧数量 + ("Capture", c_int), # 采集的有效帧的数量 + ("Lost", c_int), # 丢帧的数量 + ("Error", c_int), # 错帧的数量 + ("DispFps", c_float), # 显示帧率 + ("CapFps", c_float), # 捕获帧率 + ] + +# 方法回调辅助类 +class method(object): + def __init__(self, FuncType): + super(method, self).__init__() + self.FuncType = FuncType + self.cache = {} + + def __call__(self, cb): + self.cb = cb + return self + + def __get__(self, obj, objtype): + try: + return self.cache[obj] + except KeyError as e: + def cl(*args): + return self.cb(obj, *args) + r = self.cache[obj] = self.FuncType(cl) + return r + +# 图像捕获的回调函数定义 +CAMERA_SNAP_PROC = CALLBACK_FUNC_TYPE(None, c_int, c_void_p, POINTER(tSdkFrameHead), c_void_p) + +# 相机连接状态回调 +CAMERA_CONNECTION_STATUS_CALLBACK = CALLBACK_FUNC_TYPE(None, c_int, c_uint, c_uint, c_void_p) + +# 异步抓图完成回调 +pfnCameraGrabberSaveImageComplete = CALLBACK_FUNC_TYPE(None, c_void_p, c_void_p, c_int, c_void_p) + +# 帧监听回调 +pfnCameraGrabberFrameListener = CALLBACK_FUNC_TYPE(c_int, c_void_p, c_int, c_void_p, POINTER(tSdkFrameHead), c_void_p) + +# 采集器图像捕获的回调 +pfnCameraGrabberFrameCallback = CALLBACK_FUNC_TYPE(None, c_void_p, c_void_p, POINTER(tSdkFrameHead), c_void_p) + +#-----------------------------------函数接口------------------------------------------ + +# 线程局部存储 +_tls = local() + +# 存储最后一次SDK调用返回的错误码 +def GetLastError(): + try: + return _tls.last_error + except AttributeError as e: + _tls.last_error = 0 + return 0 + +def SetLastError(err_code): + _tls.last_error = err_code + +def _string_buffer_to_str(buf): + s = buf if isinstance(buf, type(b'')) else buf.value + + for codec in ('gbk', 'utf-8'): + try: + s = s.decode(codec) + break + except UnicodeDecodeError as e: + continue + + if isinstance(s, str): + return s + else: + return s.encode('utf-8') + +def _str_to_string_buffer(str): + if type(str) is type(u''): + s = str.encode('gbk') + else: + s = str.decode('utf-8').encode('gbk') + return create_string_buffer(s) + +def CameraSdkInit(iLanguageSel): + err_code = _sdk.CameraSdkInit(iLanguageSel) + SetLastError(err_code) + return err_code + +def CameraSetSysOption(optionName, value): + err_code = _sdk.CameraSetSysOption(_str_to_string_buffer(optionName), _str_to_string_buffer(str(value))) + SetLastError(err_code) + return err_code + +def CameraEnumerateDevice(MaxCount = 32): + Nums = c_int(MaxCount) + pCameraList = (tSdkCameraDevInfo * Nums.value)() + err_code = _sdk.CameraEnumerateDevice(pCameraList, byref(Nums)) + SetLastError(err_code) + return pCameraList[0:Nums.value] + +def CameraEnumerateDeviceEx(): + return _sdk.CameraEnumerateDeviceEx() + +def CameraIsOpened(pCameraInfo): + pOpened = c_int() + err_code = _sdk.CameraIsOpened(byref(pCameraInfo), byref(pOpened) ) + SetLastError(err_code) + return pOpened.value != 0 + +def CameraInit(pCameraInfo, emParamLoadMode = -1, emTeam = -1): + pCameraHandle = c_int() + err_code = _sdk.CameraInit(byref(pCameraInfo), emParamLoadMode, emTeam, byref(pCameraHandle)) + SetLastError(err_code) + if err_code != 0: + raise CameraException(err_code) + return pCameraHandle.value + +def CameraInitEx(iDeviceIndex, emParamLoadMode = -1, emTeam = -1): + pCameraHandle = c_int() + err_code = _sdk.CameraInitEx(iDeviceIndex, emParamLoadMode, emTeam, byref(pCameraHandle)) + SetLastError(err_code) + if err_code != 0: + raise CameraException(err_code) + return pCameraHandle.value + +def CameraInitEx2(CameraName): + pCameraHandle = c_int() + err_code = _sdk.CameraInitEx2(_str_to_string_buffer(CameraName), byref(pCameraHandle)) + SetLastError(err_code) + if err_code != 0: + raise CameraException(err_code) + return pCameraHandle.value + +def CameraSetCallbackFunction(hCamera, pCallBack, pContext = 0): + err_code = _sdk.CameraSetCallbackFunction(hCamera, pCallBack, c_void_p(pContext), None) + SetLastError(err_code) + return err_code + +def CameraUnInit(hCamera): + err_code = _sdk.CameraUnInit(hCamera) + SetLastError(err_code) + return err_code + +def CameraGetInformation(hCamera): + pbuffer = c_char_p() + err_code = _sdk.CameraGetInformation(hCamera, byref(pbuffer) ) + SetLastError(err_code) + if err_code == 0 and pbuffer.value is not None: + return _string_buffer_to_str(pbuffer) + return '' + +def CameraImageProcess(hCamera, pbyIn, pbyOut, pFrInfo): + err_code = _sdk.CameraImageProcess(hCamera, c_void_p(pbyIn), c_void_p(pbyOut), byref(pFrInfo)) + SetLastError(err_code) + return err_code + +def CameraImageProcessEx(hCamera, pbyIn, pbyOut, pFrInfo, uOutFormat, uReserved): + err_code = _sdk.CameraImageProcessEx(hCamera, c_void_p(pbyIn), c_void_p(pbyOut), byref(pFrInfo), uOutFormat, uReserved) + SetLastError(err_code) + return err_code + +def CameraDisplayInit(hCamera, hWndDisplay): + err_code = _sdk.CameraDisplayInit(hCamera, hWndDisplay) + SetLastError(err_code) + return err_code + +def CameraDisplayRGB24(hCamera, pFrameBuffer, pFrInfo): + err_code = _sdk.CameraDisplayRGB24(hCamera, c_void_p(pFrameBuffer), byref(pFrInfo) ) + SetLastError(err_code) + return err_code + +def CameraSetDisplayMode(hCamera, iMode): + err_code = _sdk.CameraSetDisplayMode(hCamera, iMode) + SetLastError(err_code) + return err_code + +def CameraSetDisplayOffset(hCamera, iOffsetX, iOffsetY): + err_code = _sdk.CameraSetDisplayOffset(hCamera, iOffsetX, iOffsetY) + SetLastError(err_code) + return err_code + +def CameraSetDisplaySize(hCamera, iWidth, iHeight): + err_code = _sdk.CameraSetDisplaySize(hCamera, iWidth, iHeight) + SetLastError(err_code) + return err_code + +def CameraGetImageBuffer(hCamera, wTimes): + pbyBuffer = c_void_p() + pFrameInfo = tSdkFrameHead() + err_code = _sdk.CameraGetImageBuffer(hCamera, byref(pFrameInfo), byref(pbyBuffer), wTimes) + SetLastError(err_code) + if err_code != 0: + raise CameraException(err_code) + return (pbyBuffer.value, pFrameInfo) + +def CameraGetImageBufferEx(hCamera, wTimes): + _sdk.CameraGetImageBufferEx.restype = c_void_p + piWidth = c_int() + piHeight = c_int() + pFrameBuffer = _sdk.CameraGetImageBufferEx(hCamera, byref(piWidth), byref(piHeight), wTimes) + err_code = CAMERA_STATUS_SUCCESS if pFrameBuffer else CAMERA_STATUS_TIME_OUT + SetLastError(err_code) + if pFrameBuffer: + return (pFrameBuffer, piWidth.value, piHeight.value) + else: + raise CameraException(err_code) + +def CameraSnapToBuffer(hCamera, wTimes): + pbyBuffer = c_void_p() + pFrameInfo = tSdkFrameHead() + err_code = _sdk.CameraSnapToBuffer(hCamera, byref(pFrameInfo), byref(pbyBuffer), wTimes) + SetLastError(err_code) + if err_code != 0: + raise CameraException(err_code) + return (pbyBuffer.value, pFrameInfo) + +def CameraReleaseImageBuffer(hCamera, pbyBuffer): + err_code = _sdk.CameraReleaseImageBuffer(hCamera, c_void_p(pbyBuffer) ) + SetLastError(err_code) + return err_code + +def CameraPlay(hCamera): + err_code = _sdk.CameraPlay(hCamera) + SetLastError(err_code) + return err_code + +def CameraPause(hCamera): + err_code = _sdk.CameraPause(hCamera) + SetLastError(err_code) + return err_code + +def CameraStop(hCamera): + err_code = _sdk.CameraStop(hCamera) + SetLastError(err_code) + return err_code + +def CameraInitRecord(hCamera, iFormat, pcSavePath, b2GLimit, dwQuality, iFrameRate): + err_code = _sdk.CameraInitRecord(hCamera, iFormat, _str_to_string_buffer(pcSavePath), b2GLimit, dwQuality, iFrameRate) + SetLastError(err_code) + return err_code + +def CameraStopRecord(hCamera): + err_code = _sdk.CameraStopRecord(hCamera) + SetLastError(err_code) + return err_code + +def CameraPushFrame(hCamera, pbyImageBuffer, pFrInfo): + err_code = _sdk.CameraPushFrame(hCamera, c_void_p(pbyImageBuffer), byref(pFrInfo) ) + SetLastError(err_code) + return err_code + +def CameraSaveImage(hCamera, lpszFileName, pbyImageBuffer, pFrInfo, byFileType, byQuality): + err_code = _sdk.CameraSaveImage(hCamera, _str_to_string_buffer(lpszFileName), c_void_p(pbyImageBuffer), byref(pFrInfo), byFileType, byQuality) + SetLastError(err_code) + return err_code + +def CameraSaveImageEx(hCamera, lpszFileName, pbyImageBuffer, uImageFormat, iWidth, iHeight, byFileType, byQuality): + err_code = _sdk.CameraSaveImageEx(hCamera, _str_to_string_buffer(lpszFileName), c_void_p(pbyImageBuffer), uImageFormat, iWidth, iHeight, byFileType, byQuality) + SetLastError(err_code) + return err_code + +def CameraGetImageResolution(hCamera): + psCurVideoSize = tSdkImageResolution() + err_code = _sdk.CameraGetImageResolution(hCamera, byref(psCurVideoSize) ) + SetLastError(err_code) + return psCurVideoSize + +def CameraSetImageResolution(hCamera, pImageResolution): + err_code = _sdk.CameraSetImageResolution(hCamera, byref(pImageResolution) ) + SetLastError(err_code) + return err_code + +def CameraSetImageResolutionEx(hCamera, iIndex, Mode, ModeSize, x, y, width, height, ZoomWidth, ZoomHeight): + err_code = _sdk.CameraSetImageResolutionEx(hCamera, iIndex, Mode, ModeSize, x, y, width, height, ZoomWidth, ZoomHeight) + SetLastError(err_code) + return err_code + +def CameraGetMediaType(hCamera): + piMediaType = c_int() + err_code = _sdk.CameraGetMediaType(hCamera, byref(piMediaType) ) + SetLastError(err_code) + return piMediaType.value + +def CameraSetMediaType(hCamera, iMediaType): + err_code = _sdk.CameraSetMediaType(hCamera, iMediaType) + SetLastError(err_code) + return err_code + +def CameraSetAeState(hCamera, bAeState): + err_code = _sdk.CameraSetAeState(hCamera, bAeState) + SetLastError(err_code) + return err_code + +def CameraGetAeState(hCamera): + pAeState = c_int() + err_code = _sdk.CameraGetAeState(hCamera, byref(pAeState) ) + SetLastError(err_code) + return pAeState.value + +def CameraSetSharpness(hCamera, iSharpness): + err_code = _sdk.CameraSetSharpness(hCamera, iSharpness) + SetLastError(err_code) + return err_code + +def CameraGetSharpness(hCamera): + piSharpness = c_int() + err_code = _sdk.CameraGetSharpness(hCamera, byref(piSharpness) ) + SetLastError(err_code) + return piSharpness.value + +def CameraSetLutMode(hCamera, emLutMode): + err_code = _sdk.CameraSetLutMode(hCamera, emLutMode) + SetLastError(err_code) + return err_code + +def CameraGetLutMode(hCamera): + pemLutMode = c_int() + err_code = _sdk.CameraGetLutMode(hCamera, byref(pemLutMode) ) + SetLastError(err_code) + return pemLutMode.value + +def CameraSelectLutPreset(hCamera, iSel): + err_code = _sdk.CameraSelectLutPreset(hCamera, iSel) + SetLastError(err_code) + return err_code + +def CameraGetLutPresetSel(hCamera): + piSel = c_int() + err_code = _sdk.CameraGetLutPresetSel(hCamera, byref(piSel) ) + SetLastError(err_code) + return piSel.value + +def CameraSetCustomLut(hCamera, iChannel, pLut): + pLutNative = (c_ushort * 4096)(*pLut) + err_code = _sdk.CameraSetCustomLut(hCamera, iChannel, pLutNative) + SetLastError(err_code) + return err_code + +def CameraGetCustomLut(hCamera, iChannel): + pLutNative = (c_ushort * 4096)() + err_code = _sdk.CameraGetCustomLut(hCamera, iChannel, pLutNative) + SetLastError(err_code) + return pLutNative[:] + +def CameraGetCurrentLut(hCamera, iChannel): + pLutNative = (c_ushort * 4096)() + err_code = _sdk.CameraGetCurrentLut(hCamera, iChannel, pLutNative) + SetLastError(err_code) + return pLutNative[:] + +def CameraSetWbMode(hCamera, bAuto): + err_code = _sdk.CameraSetWbMode(hCamera, bAuto) + SetLastError(err_code) + return err_code + +def CameraGetWbMode(hCamera): + pbAuto = c_int() + err_code = _sdk.CameraGetWbMode(hCamera, byref(pbAuto) ) + SetLastError(err_code) + return pbAuto.value + +def CameraSetPresetClrTemp(hCamera, iSel): + err_code = _sdk.CameraSetPresetClrTemp(hCamera, iSel) + SetLastError(err_code) + return err_code + +def CameraGetPresetClrTemp(hCamera): + piSel = c_int() + err_code = _sdk.CameraGetPresetClrTemp(hCamera, byref(piSel) ) + SetLastError(err_code) + return piSel.value + +def CameraSetUserClrTempGain(hCamera, iRgain, iGgain, iBgain): + err_code = _sdk.CameraSetUserClrTempGain(hCamera, iRgain, iGgain, iBgain) + SetLastError(err_code) + return err_code + +def CameraGetUserClrTempGain(hCamera): + piRgain = c_int() + piGgain = c_int() + piBgain = c_int() + err_code = _sdk.CameraGetUserClrTempGain(hCamera, byref(piRgain), byref(piGgain), byref(piBgain) ) + SetLastError(err_code) + return (piRgain.value, piGgain.value, piBgain.value) + +def CameraSetUserClrTempMatrix(hCamera, pMatrix): + pMatrixNative = (c_float * 9)(*pMatrix) + err_code = _sdk.CameraSetUserClrTempMatrix(hCamera, pMatrixNative) + SetLastError(err_code) + return err_code + +def CameraGetUserClrTempMatrix(hCamera): + pMatrixNative = (c_float * 9)() + err_code = _sdk.CameraGetUserClrTempMatrix(hCamera, pMatrixNative) + SetLastError(err_code) + return pMatrixNative[:] + +def CameraSetClrTempMode(hCamera, iMode): + err_code = _sdk.CameraSetClrTempMode(hCamera, iMode) + SetLastError(err_code) + return err_code + +def CameraGetClrTempMode(hCamera): + piMode = c_int() + err_code = _sdk.CameraGetClrTempMode(hCamera, byref(piMode) ) + SetLastError(err_code) + return piMode.value + +def CameraSetOnceWB(hCamera): + err_code = _sdk.CameraSetOnceWB(hCamera) + SetLastError(err_code) + return err_code + +def CameraSetOnceBB(hCamera): + err_code = _sdk.CameraSetOnceBB(hCamera) + SetLastError(err_code) + return err_code + +def CameraSetAeTarget(hCamera, iAeTarget): + err_code = _sdk.CameraSetAeTarget(hCamera, iAeTarget) + SetLastError(err_code) + return err_code + +def CameraGetAeTarget(hCamera): + piAeTarget = c_int() + err_code = _sdk.CameraGetAeTarget(hCamera, byref(piAeTarget) ) + SetLastError(err_code) + return piAeTarget.value + +def CameraSetAeExposureRange(hCamera, fMinExposureTime, fMaxExposureTime): + err_code = _sdk.CameraSetAeExposureRange(hCamera, c_double(fMinExposureTime), c_double(fMaxExposureTime) ) + SetLastError(err_code) + return err_code + +def CameraGetAeExposureRange(hCamera): + fMinExposureTime = c_double() + fMaxExposureTime = c_double() + err_code = _sdk.CameraGetAeExposureRange(hCamera, byref(fMinExposureTime), byref(fMaxExposureTime) ) + SetLastError(err_code) + return (fMinExposureTime.value, fMaxExposureTime.value) + +def CameraSetAeAnalogGainRange(hCamera, iMinAnalogGain, iMaxAnalogGain): + err_code = _sdk.CameraSetAeAnalogGainRange(hCamera, iMinAnalogGain, iMaxAnalogGain) + SetLastError(err_code) + return err_code + +def CameraGetAeAnalogGainRange(hCamera): + iMinAnalogGain = c_int() + iMaxAnalogGain = c_int() + err_code = _sdk.CameraGetAeAnalogGainRange(hCamera, byref(iMinAnalogGain), byref(iMaxAnalogGain) ) + SetLastError(err_code) + return (iMinAnalogGain.value, iMaxAnalogGain.value) + +def CameraSetAeThreshold(hCamera, iThreshold): + err_code = _sdk.CameraSetAeThreshold(hCamera, iThreshold) + SetLastError(err_code) + return err_code + +def CameraGetAeThreshold(hCamera): + iThreshold = c_int() + err_code = _sdk.CameraGetAeThreshold(hCamera, byref(iThreshold)) + SetLastError(err_code) + return iThreshold.value + +def CameraSetExposureTime(hCamera, fExposureTime): + err_code = _sdk.CameraSetExposureTime(hCamera, c_double(fExposureTime) ) + SetLastError(err_code) + return err_code + +def CameraGetExposureLineTime(hCamera): + pfLineTime = c_double() + err_code = _sdk.CameraGetExposureLineTime(hCamera, byref(pfLineTime)) + SetLastError(err_code) + return pfLineTime.value + +def CameraGetExposureTime(hCamera): + pfExposureTime = c_double() + err_code = _sdk.CameraGetExposureTime(hCamera, byref(pfExposureTime)) + SetLastError(err_code) + return pfExposureTime.value + +def CameraGetExposureTimeRange(hCamera): + pfMin = c_double() + pfMax = c_double() + pfStep = c_double() + err_code = _sdk.CameraGetExposureTimeRange(hCamera, byref(pfMin), byref(pfMax), byref(pfStep)) + SetLastError(err_code) + return (pfMin.value, pfMax.value, pfStep.value) + +def CameraSetAnalogGain(hCamera, iAnalogGain): + err_code = _sdk.CameraSetAnalogGain(hCamera, iAnalogGain) + SetLastError(err_code) + return err_code + +def CameraGetAnalogGain(hCamera): + piAnalogGain = c_int() + err_code = _sdk.CameraGetAnalogGain(hCamera, byref(piAnalogGain)) + SetLastError(err_code) + return piAnalogGain.value + +def CameraSetAnalogGainX(hCamera, fGain): + err_code = _sdk.CameraSetAnalogGainX(hCamera, c_float(fGain) ) + SetLastError(err_code) + return err_code + +def CameraGetAnalogGainX(hCamera): + fGain = c_float() + err_code = _sdk.CameraGetAnalogGainX(hCamera, byref(fGain)) + SetLastError(err_code) + return fGain.value + +def CameraGetAnalogGainXRange(hCamera): + pfMin = c_float() + pfMax = c_float() + pfStep = c_float() + err_code = _sdk.CameraGetAnalogGainXRange(hCamera, byref(pfMin), byref(pfMax), byref(pfStep)) + SetLastError(err_code) + return (pfMin.value, pfMax.value, pfStep.value) + +def CameraSetGain(hCamera, iRGain, iGGain, iBGain): + err_code = _sdk.CameraSetGain(hCamera, iRGain, iGGain, iBGain) + SetLastError(err_code) + return err_code + +def CameraGetGain(hCamera): + piRGain = c_int() + piGGain = c_int() + piBGain = c_int() + err_code = _sdk.CameraGetGain(hCamera, byref(piRGain), byref(piGGain), byref(piBGain)) + SetLastError(err_code) + return (piRGain.value, piGGain.value, piBGain.value) + +def CameraSetGamma(hCamera, iGamma): + err_code = _sdk.CameraSetGamma(hCamera, iGamma) + SetLastError(err_code) + return err_code + +def CameraGetGamma(hCamera): + piGamma = c_int() + err_code = _sdk.CameraGetGamma(hCamera, byref(piGamma)) + SetLastError(err_code) + return piGamma.value + +def CameraSetContrast(hCamera, iContrast): + err_code = _sdk.CameraSetContrast(hCamera, iContrast) + SetLastError(err_code) + return err_code + +def CameraGetContrast(hCamera): + piContrast = c_int() + err_code = _sdk.CameraGetContrast(hCamera, byref(piContrast)) + SetLastError(err_code) + return piContrast.value + +def CameraSetSaturation(hCamera, iSaturation): + err_code = _sdk.CameraSetSaturation(hCamera, iSaturation) + SetLastError(err_code) + return err_code + +def CameraGetSaturation(hCamera): + piSaturation = c_int() + err_code = _sdk.CameraGetSaturation(hCamera, byref(piSaturation)) + SetLastError(err_code) + return piSaturation.value + +def CameraSetMonochrome(hCamera, bEnable): + err_code = _sdk.CameraSetMonochrome(hCamera, bEnable) + SetLastError(err_code) + return err_code + +def CameraGetMonochrome(hCamera): + pbEnable = c_int() + err_code = _sdk.CameraGetMonochrome(hCamera, byref(pbEnable)) + SetLastError(err_code) + return pbEnable.value + +def CameraSetInverse(hCamera, bEnable): + err_code = _sdk.CameraSetInverse(hCamera, bEnable) + SetLastError(err_code) + return err_code + +def CameraGetInverse(hCamera): + pbEnable = c_int() + err_code = _sdk.CameraGetInverse(hCamera, byref(pbEnable)) + SetLastError(err_code) + return pbEnable.value + +def CameraSetAntiFlick(hCamera, bEnable): + err_code = _sdk.CameraSetAntiFlick(hCamera, bEnable) + SetLastError(err_code) + return err_code + +def CameraGetAntiFlick(hCamera): + pbEnable = c_int() + err_code = _sdk.CameraGetAntiFlick(hCamera, byref(pbEnable)) + SetLastError(err_code) + return pbEnable.value + +def CameraGetLightFrequency(hCamera): + piFrequencySel = c_int() + err_code = _sdk.CameraGetLightFrequency(hCamera, byref(piFrequencySel)) + SetLastError(err_code) + return piFrequencySel.value + +def CameraSetLightFrequency(hCamera, iFrequencySel): + err_code = _sdk.CameraSetLightFrequency(hCamera, iFrequencySel) + SetLastError(err_code) + return err_code + +def CameraSetFrameSpeed(hCamera, iFrameSpeed): + err_code = _sdk.CameraSetFrameSpeed(hCamera, iFrameSpeed) + SetLastError(err_code) + return err_code + +def CameraGetFrameSpeed(hCamera): + piFrameSpeed = c_int() + err_code = _sdk.CameraGetFrameSpeed(hCamera, byref(piFrameSpeed)) + SetLastError(err_code) + return piFrameSpeed.value + +def CameraSetParameterMode(hCamera, iMode): + err_code = _sdk.CameraSetParameterMode(hCamera, iMode) + SetLastError(err_code) + return err_code + +def CameraGetParameterMode(hCamera): + piTarget = c_int() + err_code = _sdk.CameraGetParameterMode(hCamera, byref(piTarget)) + SetLastError(err_code) + return piTarget.value + +def CameraSetParameterMask(hCamera, uMask): + err_code = _sdk.CameraSetParameterMask(hCamera, uMask) + SetLastError(err_code) + return err_code + +def CameraSaveParameter(hCamera, iTeam): + err_code = _sdk.CameraSaveParameter(hCamera, iTeam) + SetLastError(err_code) + return err_code + +def CameraSaveParameterToFile(hCamera, sFileName): + err_code = _sdk.CameraSaveParameterToFile(hCamera, _str_to_string_buffer(sFileName)) + SetLastError(err_code) + return err_code + +def CameraReadParameterFromFile(hCamera, sFileName): + err_code = _sdk.CameraReadParameterFromFile(hCamera, _str_to_string_buffer(sFileName)) + SetLastError(err_code) + return err_code + +def CameraLoadParameter(hCamera, iTeam): + err_code = _sdk.CameraLoadParameter(hCamera, iTeam) + SetLastError(err_code) + return err_code + +def CameraGetCurrentParameterGroup(hCamera): + piTeam = c_int() + err_code = _sdk.CameraGetCurrentParameterGroup(hCamera, byref(piTeam)) + SetLastError(err_code) + return piTeam.value + +def CameraSetTransPackLen(hCamera, iPackSel): + err_code = _sdk.CameraSetTransPackLen(hCamera, iPackSel) + SetLastError(err_code) + return err_code + +def CameraGetTransPackLen(hCamera): + piPackSel = c_int() + err_code = _sdk.CameraGetTransPackLen(hCamera, byref(piPackSel)) + SetLastError(err_code) + return piPackSel.value + +def CameraIsAeWinVisible(hCamera): + pbIsVisible = c_int() + err_code = _sdk.CameraIsAeWinVisible(hCamera, byref(pbIsVisible)) + SetLastError(err_code) + return pbIsVisible.value + +def CameraSetAeWinVisible(hCamera, bIsVisible): + err_code = _sdk.CameraSetAeWinVisible(hCamera, bIsVisible) + SetLastError(err_code) + return err_code + +def CameraGetAeWindow(hCamera): + piHOff = c_int() + piVOff = c_int() + piWidth = c_int() + piHeight = c_int() + err_code = _sdk.CameraGetAeWindow(hCamera, byref(piHOff), byref(piVOff), byref(piWidth), byref(piHeight)) + SetLastError(err_code) + return (piHOff.value, piVOff.value, piWidth.value, piHeight.value) + +def CameraSetAeWindow(hCamera, iHOff, iVOff, iWidth, iHeight): + err_code = _sdk.CameraSetAeWindow(hCamera, iHOff, iVOff, iWidth, iHeight) + SetLastError(err_code) + return err_code + +def CameraSetMirror(hCamera, iDir, bEnable): + err_code = _sdk.CameraSetMirror(hCamera, iDir, bEnable) + SetLastError(err_code) + return err_code + +def CameraGetMirror(hCamera, iDir): + pbEnable = c_int() + err_code = _sdk.CameraGetMirror(hCamera, iDir, byref(pbEnable)) + SetLastError(err_code) + return pbEnable.value + +def CameraSetRotate(hCamera, iRot): + err_code = _sdk.CameraSetRotate(hCamera, iRot) + SetLastError(err_code) + return err_code + +def CameraGetRotate(hCamera): + iRot = c_int() + err_code = _sdk.CameraGetRotate(hCamera, byref(iRot)) + SetLastError(err_code) + return iRot.value + +def CameraGetWbWindow(hCamera): + PiHOff = c_int() + PiVOff = c_int() + PiWidth = c_int() + PiHeight = c_int() + err_code = _sdk.CameraGetWbWindow(hCamera, byref(PiHOff), byref(PiVOff), byref(PiWidth), byref(PiHeight)) + SetLastError(err_code) + return (PiHOff.value, PiVOff.value, PiWidth.value, PiHeight.value) + +def CameraSetWbWindow(hCamera, iHOff, iVOff, iWidth, iHeight): + err_code = _sdk.CameraSetWbWindow(hCamera, iHOff, iVOff, iWidth, iHeight) + SetLastError(err_code) + return err_code + +def CameraIsWbWinVisible(hCamera): + pbShow = c_int() + err_code = _sdk.CameraIsWbWinVisible(hCamera, byref(pbShow)) + SetLastError(err_code) + return pbShow.value + +def CameraSetWbWinVisible(hCamera, bShow): + err_code = _sdk.CameraSetWbWinVisible(hCamera, bShow) + SetLastError(err_code) + return err_code + +def CameraImageOverlay(hCamera, pRgbBuffer, pFrInfo): + err_code = _sdk.CameraImageOverlay(hCamera, c_void_p(pRgbBuffer), byref(pFrInfo)) + SetLastError(err_code) + return err_code + +def CameraSetCrossLine(hCamera, iLine, x, y, uColor, bVisible): + err_code = _sdk.CameraSetCrossLine(hCamera, iLine, x, y, uColor, bVisible) + SetLastError(err_code) + return err_code + +def CameraGetCrossLine(hCamera, iLine): + px = c_int() + py = c_int() + pcolor = c_uint() + pbVisible = c_int() + err_code = _sdk.CameraGetCrossLine(hCamera, iLine, byref(px), byref(py), byref(pcolor), byref(pbVisible)) + SetLastError(err_code) + return (px.value, py.value, pcolor.value, pbVisible.value) + +def CameraGetCapability(hCamera): + pCameraInfo = tSdkCameraCapbility() + err_code = _sdk.CameraGetCapability(hCamera, byref(pCameraInfo)) + SetLastError(err_code) + return pCameraInfo + +def CameraWriteSN(hCamera, pbySN, iLevel): + err_code = _sdk.CameraWriteSN(hCamera, _str_to_string_buffer(pbySN), iLevel) + SetLastError(err_code) + return err_code + +def CameraReadSN(hCamera, iLevel): + pbySN = create_string_buffer(64) + err_code = _sdk.CameraReadSN(hCamera, pbySN, iLevel) + SetLastError(err_code) + return _string_buffer_to_str(pbySN) + +def CameraSetTriggerDelayTime(hCamera, uDelayTimeUs): + err_code = _sdk.CameraSetTriggerDelayTime(hCamera, uDelayTimeUs) + SetLastError(err_code) + return err_code + +def CameraGetTriggerDelayTime(hCamera): + puDelayTimeUs = c_uint() + err_code = _sdk.CameraGetTriggerDelayTime(hCamera, byref(puDelayTimeUs)) + SetLastError(err_code) + return puDelayTimeUs.value + +def CameraSetTriggerCount(hCamera, iCount): + err_code = _sdk.CameraSetTriggerCount(hCamera, iCount) + SetLastError(err_code) + return err_code + +def CameraGetTriggerCount(hCamera): + piCount = c_int() + err_code = _sdk.CameraGetTriggerCount(hCamera, byref(piCount)) + SetLastError(err_code) + return piCount.value + +def CameraSoftTrigger(hCamera): + err_code = _sdk.CameraSoftTrigger(hCamera) + SetLastError(err_code) + return err_code + +def CameraSetTriggerMode(hCamera, iModeSel): + err_code = _sdk.CameraSetTriggerMode(hCamera, iModeSel) + SetLastError(err_code) + return err_code + +def CameraGetTriggerMode(hCamera): + piModeSel = c_int() + err_code = _sdk.CameraGetTriggerMode(hCamera, byref(piModeSel)) + SetLastError(err_code) + return piModeSel.value + +def CameraSetStrobeMode(hCamera, iMode): + err_code = _sdk.CameraSetStrobeMode(hCamera, iMode) + SetLastError(err_code) + return err_code + +def CameraGetStrobeMode(hCamera): + piMode = c_int() + err_code = _sdk.CameraGetStrobeMode(hCamera, byref(piMode)) + SetLastError(err_code) + return piMode.value + +def CameraSetStrobeDelayTime(hCamera, uDelayTimeUs): + err_code = _sdk.CameraSetStrobeDelayTime(hCamera, uDelayTimeUs) + SetLastError(err_code) + return err_code + +def CameraGetStrobeDelayTime(hCamera): + upDelayTimeUs = c_uint() + err_code = _sdk.CameraGetStrobeDelayTime(hCamera, byref(upDelayTimeUs)) + SetLastError(err_code) + return upDelayTimeUs.value + +def CameraSetStrobePulseWidth(hCamera, uTimeUs): + err_code = _sdk.CameraSetStrobePulseWidth(hCamera, uTimeUs) + SetLastError(err_code) + return err_code + +def CameraGetStrobePulseWidth(hCamera): + upTimeUs = c_uint() + err_code = _sdk.CameraGetStrobePulseWidth(hCamera, byref(upTimeUs)) + SetLastError(err_code) + return upTimeUs.value + +def CameraSetStrobePolarity(hCamera, uPolarity): + err_code = _sdk.CameraSetStrobePolarity(hCamera, uPolarity) + SetLastError(err_code) + return err_code + +def CameraGetStrobePolarity(hCamera): + upPolarity = c_uint() + err_code = _sdk.CameraGetStrobePolarity(hCamera, byref(upPolarity)) + SetLastError(err_code) + return upPolarity.value + +def CameraSetExtTrigSignalType(hCamera, iType): + err_code = _sdk.CameraSetExtTrigSignalType(hCamera, iType) + SetLastError(err_code) + return err_code + +def CameraGetExtTrigSignalType(hCamera): + ipType = c_int() + err_code = _sdk.CameraGetExtTrigSignalType(hCamera, byref(ipType)) + SetLastError(err_code) + return ipType.value + +def CameraSetExtTrigShutterType(hCamera, iType): + err_code = _sdk.CameraSetExtTrigShutterType(hCamera, iType) + SetLastError(err_code) + return err_code + +def CameraGetExtTrigShutterType(hCamera): + ipType = c_int() + err_code = _sdk.CameraGetExtTrigShutterType(hCamera, byref(ipType)) + SetLastError(err_code) + return ipType.value + +def CameraSetExtTrigDelayTime(hCamera, uDelayTimeUs): + err_code = _sdk.CameraSetExtTrigDelayTime(hCamera, uDelayTimeUs) + SetLastError(err_code) + return err_code + +def CameraGetExtTrigDelayTime(hCamera): + upDelayTimeUs = c_uint() + err_code = _sdk.CameraGetExtTrigDelayTime(hCamera, byref(upDelayTimeUs)) + SetLastError(err_code) + return upDelayTimeUs.value + +def CameraSetExtTrigJitterTime(hCamera, uTimeUs): + err_code = _sdk.CameraSetExtTrigJitterTime(hCamera, uTimeUs) + SetLastError(err_code) + return err_code + +def CameraGetExtTrigJitterTime(hCamera): + upTimeUs = c_uint() + err_code = _sdk.CameraGetExtTrigJitterTime(hCamera, byref(upTimeUs)) + SetLastError(err_code) + return upTimeUs.value + +def CameraGetExtTrigCapability(hCamera): + puCapabilityMask = c_uint() + err_code = _sdk.CameraGetExtTrigCapability(hCamera, byref(puCapabilityMask)) + SetLastError(err_code) + return puCapabilityMask.value + +def CameraPauseLevelTrigger(hCamera): + err_code = _sdk.CameraPauseLevelTrigger(hCamera) + SetLastError(err_code) + return err_code + +def CameraGetResolutionForSnap(hCamera): + pImageResolution = tSdkImageResolution() + err_code = _sdk.CameraGetResolutionForSnap(hCamera, byref(pImageResolution)) + SetLastError(err_code) + return pImageResolution + +def CameraSetResolutionForSnap(hCamera, pImageResolution): + err_code = _sdk.CameraSetResolutionForSnap(hCamera, byref(pImageResolution)) + SetLastError(err_code) + return err_code + +def CameraCustomizeResolution(hCamera): + pImageCustom = tSdkImageResolution() + err_code = _sdk.CameraCustomizeResolution(hCamera, byref(pImageCustom)) + SetLastError(err_code) + return pImageCustom + +def CameraCustomizeReferWin(hCamera, iWinType, hParent): + piHOff = c_int() + piVOff = c_int() + piWidth = c_int() + piHeight = c_int() + err_code = _sdk.CameraCustomizeReferWin(hCamera, iWinType, hParent, byref(piHOff), byref(piVOff), byref(piWidth), byref(piHeight)) + SetLastError(err_code) + return (piHOff.value, piVOff.value, piWidth.value, piHeight.value) + +def CameraShowSettingPage(hCamera, bShow): + err_code = _sdk.CameraShowSettingPage(hCamera, bShow) + SetLastError(err_code) + return err_code + +def CameraCreateSettingPage(hCamera, hParent, pWinText, pCallbackFunc = None, pCallbackCtx = 0, uReserved = 0): + err_code = _sdk.CameraCreateSettingPage(hCamera, hParent, _str_to_string_buffer(pWinText), pCallbackFunc, c_void_p(pCallbackCtx), uReserved) + SetLastError(err_code) + return err_code + +def CameraCreateSettingPageEx(hCamera): + err_code = _sdk.CameraCreateSettingPageEx(hCamera) + SetLastError(err_code) + return err_code + +def CameraSetActiveSettingSubPage(hCamera, index): + err_code = _sdk.CameraSetActiveSettingSubPage(hCamera, index) + SetLastError(err_code) + return err_code + +def CameraSetSettingPageParent(hCamera, hParentWnd, Flags): + err_code = _sdk.CameraSetSettingPageParent(hCamera, hParentWnd, Flags) + SetLastError(err_code) + return err_code + +def CameraGetSettingPageHWnd(hCamera): + hWnd = c_void_p() + err_code = _sdk.CameraGetSettingPageHWnd(hCamera, byref(hWnd)) + SetLastError(err_code) + return hWnd.value + +def CameraSpecialControl(hCamera, dwCtrlCode, dwParam, lpData): + err_code = _sdk.CameraSpecialControl(hCamera, dwCtrlCode, dwParam, c_void_p(lpData) ) + SetLastError(err_code) + return err_code + +def CameraGetFrameStatistic(hCamera): + psFrameStatistic = tSdkFrameStatistic() + err_code = _sdk.CameraGetFrameStatistic(hCamera, byref(psFrameStatistic)) + SetLastError(err_code) + return psFrameStatistic + +def CameraSetNoiseFilter(hCamera, bEnable): + err_code = _sdk.CameraSetNoiseFilter(hCamera, bEnable) + SetLastError(err_code) + return err_code + +def CameraGetNoiseFilterState(hCamera): + pEnable = c_int() + err_code = _sdk.CameraGetNoiseFilterState(hCamera, byref(pEnable)) + SetLastError(err_code) + return pEnable.value + +def CameraRstTimeStamp(hCamera): + err_code = _sdk.CameraRstTimeStamp(hCamera) + SetLastError(err_code) + return err_code + +def CameraSaveUserData(hCamera, uStartAddr, pbData): + err_code = _sdk.CameraSaveUserData(hCamera, uStartAddr, pbData, len(pbData)) + SetLastError(err_code) + return err_code + +def CameraLoadUserData(hCamera, uStartAddr, ilen): + pbData = create_string_buffer(ilen) + err_code = _sdk.CameraLoadUserData(hCamera, uStartAddr, pbData, ilen) + SetLastError(err_code) + return pbData[:] + +def CameraGetFriendlyName(hCamera): + pName = create_string_buffer(64) + err_code = _sdk.CameraGetFriendlyName(hCamera, pName) + SetLastError(err_code) + return _string_buffer_to_str(pName) + +def CameraSetFriendlyName(hCamera, pName): + pNameBuf = _str_to_string_buffer(pName) + resize(pNameBuf, 64) + err_code = _sdk.CameraSetFriendlyName(hCamera, pNameBuf) + SetLastError(err_code) + return err_code + +def CameraSdkGetVersionString(): + pVersionString = create_string_buffer(64) + err_code = _sdk.CameraSdkGetVersionString(pVersionString) + SetLastError(err_code) + return _string_buffer_to_str(pVersionString) + +def CameraCheckFwUpdate(hCamera): + pNeedUpdate = c_int() + err_code = _sdk.CameraCheckFwUpdate(hCamera, byref(pNeedUpdate)) + SetLastError(err_code) + return pNeedUpdate.value + +def CameraGetFirmwareVersion(hCamera): + pVersion = create_string_buffer(64) + err_code = _sdk.CameraGetFirmwareVersion(hCamera, pVersion) + SetLastError(err_code) + return _string_buffer_to_str(pVersion) + +def CameraGetEnumInfo(hCamera): + pCameraInfo = tSdkCameraDevInfo() + err_code = _sdk.CameraGetEnumInfo(hCamera, byref(pCameraInfo)) + SetLastError(err_code) + return pCameraInfo + +def CameraGetInerfaceVersion(hCamera): + pVersion = create_string_buffer(64) + err_code = _sdk.CameraGetInerfaceVersion(hCamera, pVersion) + SetLastError(err_code) + return _string_buffer_to_str(pVersion) + +def CameraSetIOState(hCamera, iOutputIOIndex, uState): + err_code = _sdk.CameraSetIOState(hCamera, iOutputIOIndex, uState) + SetLastError(err_code) + return err_code + +def CameraSetIOStateEx(hCamera, iOutputIOIndex, uState): + err_code = _sdk.CameraSetIOStateEx(hCamera, iOutputIOIndex, uState) + SetLastError(err_code) + return err_code + +def CameraGetOutPutIOState(hCamera, iOutputIOIndex): + puState = c_int() + err_code = _sdk.CameraGetOutPutIOState(hCamera, iOutputIOIndex, byref(puState)) + SetLastError(err_code) + return puState.value + +def CameraGetOutPutIOStateEx(hCamera, iOutputIOIndex): + puState = c_int() + err_code = _sdk.CameraGetOutPutIOStateEx(hCamera, iOutputIOIndex, byref(puState)) + SetLastError(err_code) + return puState.value + +def CameraGetIOState(hCamera, iInputIOIndex): + puState = c_int() + err_code = _sdk.CameraGetIOState(hCamera, iInputIOIndex, byref(puState)) + SetLastError(err_code) + return puState.value + +def CameraGetIOStateEx(hCamera, iInputIOIndex): + puState = c_int() + err_code = _sdk.CameraGetIOStateEx(hCamera, iInputIOIndex, byref(puState)) + SetLastError(err_code) + return puState.value + +def CameraSetInPutIOMode(hCamera, iInputIOIndex, iMode): + err_code = _sdk.CameraSetInPutIOMode(hCamera, iInputIOIndex, iMode) + SetLastError(err_code) + return err_code + +def CameraSetOutPutIOMode(hCamera, iOutputIOIndex, iMode): + err_code = _sdk.CameraSetOutPutIOMode(hCamera, iOutputIOIndex, iMode) + SetLastError(err_code) + return err_code + +def CameraSetOutPutPWM(hCamera, iOutputIOIndex, iCycle, uDuty): + err_code = _sdk.CameraSetOutPutPWM(hCamera, iOutputIOIndex, iCycle, uDuty) + SetLastError(err_code) + return err_code + +def CameraSetAeAlgorithm(hCamera, iIspProcessor, iAeAlgorithmSel): + err_code = _sdk.CameraSetAeAlgorithm(hCamera, iIspProcessor, iAeAlgorithmSel) + SetLastError(err_code) + return err_code + +def CameraGetAeAlgorithm(hCamera, iIspProcessor): + piAlgorithmSel = c_int() + err_code = _sdk.CameraGetAeAlgorithm(hCamera, iIspProcessor, byref(piAlgorithmSel)) + SetLastError(err_code) + return piAlgorithmSel.value + +def CameraSetBayerDecAlgorithm(hCamera, iIspProcessor, iAlgorithmSel): + err_code = _sdk.CameraSetBayerDecAlgorithm(hCamera, iIspProcessor, iAlgorithmSel) + SetLastError(err_code) + return err_code + +def CameraGetBayerDecAlgorithm(hCamera, iIspProcessor): + piAlgorithmSel = c_int() + err_code = _sdk.CameraGetBayerDecAlgorithm(hCamera, iIspProcessor, byref(piAlgorithmSel)) + SetLastError(err_code) + return piAlgorithmSel.value + +def CameraSetIspProcessor(hCamera, iIspProcessor): + err_code = _sdk.CameraSetIspProcessor(hCamera, iIspProcessor) + SetLastError(err_code) + return err_code + +def CameraGetIspProcessor(hCamera): + piIspProcessor = c_int() + err_code = _sdk.CameraGetIspProcessor(hCamera, byref(piIspProcessor)) + SetLastError(err_code) + return piIspProcessor.value + +def CameraSetBlackLevel(hCamera, iBlackLevel): + err_code = _sdk.CameraSetBlackLevel(hCamera, iBlackLevel) + SetLastError(err_code) + return err_code + +def CameraGetBlackLevel(hCamera): + piBlackLevel = c_int() + err_code = _sdk.CameraGetBlackLevel(hCamera, byref(piBlackLevel)) + SetLastError(err_code) + return piBlackLevel.value + +def CameraSetWhiteLevel(hCamera, iWhiteLevel): + err_code = _sdk.CameraSetWhiteLevel(hCamera, iWhiteLevel) + SetLastError(err_code) + return err_code + +def CameraGetWhiteLevel(hCamera): + piWhiteLevel = c_int() + err_code = _sdk.CameraGetWhiteLevel(hCamera, byref(piWhiteLevel)) + SetLastError(err_code) + return piWhiteLevel.value + +def CameraSetIspOutFormat(hCamera, uFormat): + err_code = _sdk.CameraSetIspOutFormat(hCamera, uFormat) + SetLastError(err_code) + return err_code + +def CameraGetIspOutFormat(hCamera): + puFormat = c_int() + err_code = _sdk.CameraGetIspOutFormat(hCamera, byref(puFormat)) + SetLastError(err_code) + return puFormat.value + +def CameraGetErrorString(iStatusCode): + _sdk.CameraGetErrorString.restype = c_char_p + msg = _sdk.CameraGetErrorString(iStatusCode) + if msg: + return _string_buffer_to_str(msg) + else: + return '' + +def CameraGetImageBufferEx2(hCamera, pImageData, uOutFormat, wTimes): + piWidth = c_int() + piHeight = c_int() + err_code = _sdk.CameraGetImageBufferEx2(hCamera, c_void_p(pImageData), uOutFormat, byref(piWidth), byref(piHeight), wTimes) + SetLastError(err_code) + if err_code != 0: + raise CameraException(err_code) + return (piWidth.value, piHeight.value) + +def CameraGetImageBufferEx3(hCamera, pImageData, uOutFormat, wTimes): + piWidth = c_int() + piHeight = c_int() + puTimeStamp = c_int() + err_code = _sdk.CameraGetImageBufferEx3(hCamera, c_void_p(pImageData), uOutFormat, byref(piWidth), byref(piHeight), byref(puTimeStamp), wTimes) + SetLastError(err_code) + if err_code != 0: + raise CameraException(err_code) + return (piWidth.value, piHeight.value, puTimeStamp.value) + +def CameraGetCapabilityEx2(hCamera): + pMaxWidth = c_int() + pMaxHeight = c_int() + pbColorCamera = c_int() + err_code = _sdk.CameraGetCapabilityEx2(hCamera, byref(pMaxWidth), byref(pMaxHeight), byref(pbColorCamera)) + SetLastError(err_code) + return (pMaxWidth.value, pMaxHeight.value, pbColorCamera.value) + +def CameraReConnect(hCamera): + err_code = _sdk.CameraReConnect(hCamera) + SetLastError(err_code) + return err_code + +def CameraConnectTest(hCamera): + err_code = _sdk.CameraConnectTest(hCamera) + SetLastError(err_code) + return err_code + +def CameraSetLedEnable(hCamera, index, enable): + err_code = _sdk.CameraSetLedEnable(hCamera, index, enable) + SetLastError(err_code) + return err_code + +def CameraGetLedEnable(hCamera, index): + enable = c_int() + err_code = _sdk.CameraGetLedEnable(hCamera, index, byref(enable)) + SetLastError(err_code) + return enable.value + +def CameraSetLedOnOff(hCamera, index, onoff): + err_code = _sdk.CameraSetLedOnOff(hCamera, index, onoff) + SetLastError(err_code) + return err_code + +def CameraGetLedOnOff(hCamera, index): + onoff = c_int() + err_code = _sdk.CameraGetLedOnOff(hCamera, index, byref(onoff)) + SetLastError(err_code) + return onoff.value + +def CameraSetLedDuration(hCamera, index, duration): + err_code = _sdk.CameraSetLedDuration(hCamera, index, duration) + SetLastError(err_code) + return err_code + +def CameraGetLedDuration(hCamera, index): + duration = c_uint() + err_code = _sdk.CameraGetLedDuration(hCamera, index, byref(duration)) + SetLastError(err_code) + return duration.value + +def CameraSetLedBrightness(hCamera, index, uBrightness): + err_code = _sdk.CameraSetLedBrightness(hCamera, index, uBrightness) + SetLastError(err_code) + return err_code + +def CameraGetLedBrightness(hCamera, index): + uBrightness = c_uint() + err_code = _sdk.CameraGetLedBrightness(hCamera, index, byref(uBrightness)) + SetLastError(err_code) + return uBrightness.value + +def CameraEnableTransferRoi(hCamera, uEnableMask): + err_code = _sdk.CameraEnableTransferRoi(hCamera, uEnableMask) + SetLastError(err_code) + return err_code + +def CameraSetTransferRoi(hCamera, index, X1, Y1, X2, Y2): + err_code = _sdk.CameraSetTransferRoi(hCamera, index, X1, Y1, X2, Y2) + SetLastError(err_code) + return err_code + +def CameraGetTransferRoi(hCamera, index): + pX1 = c_uint() + pY1 = c_uint() + pX2 = c_uint() + pY2 = c_uint() + err_code = _sdk.CameraGetTransferRoi(hCamera, index, byref(pX1), byref(pY1), byref(pX2), byref(pY2)) + SetLastError(err_code) + return (pX1.value, pY1.value, pX2.value, pY2.value) + +def CameraAlignMalloc(size, align = 16): + _sdk.CameraAlignMalloc.restype = c_void_p + r = _sdk.CameraAlignMalloc(size, align) + return r + +def CameraAlignFree(membuffer): + _sdk.CameraAlignFree(c_void_p(membuffer)) + +def CameraSetAutoConnect(hCamera, bEnable): + err_code = _sdk.CameraSetAutoConnect(hCamera, bEnable) + SetLastError(err_code) + return err_code + +def CameraGetAutoConnect(hCamera): + pbEnable = c_int() + err_code = _sdk.CameraGetAutoConnect(hCamera, byref(pbEnable)) + SetLastError(err_code) + return pbEnable.value + +def CameraGetReConnectCounts(hCamera): + puCounts = c_int() + err_code = _sdk.CameraGetReConnectCounts(hCamera, byref(puCounts)) + SetLastError(err_code) + return puCounts.value + +def CameraSetSingleGrabMode(hCamera, bEnable): + err_code = _sdk.CameraSetSingleGrabMode(hCamera, bEnable) + SetLastError(err_code) + return err_code + +def CameraGetSingleGrabMode(hCamera): + pbEnable = c_int() + err_code = _sdk.CameraGetSingleGrabMode(hCamera, byref(pbEnable)) + SetLastError(err_code) + return pbEnable.value + +def CameraRestartGrab(hCamera): + err_code = _sdk.CameraRestartGrab(hCamera) + SetLastError(err_code) + return err_code + +def CameraEvaluateImageDefinition(hCamera, iAlgorithSel, pbyIn, pFrInfo): + DefinitionValue = c_double() + err_code = _sdk.CameraEvaluateImageDefinition(hCamera, iAlgorithSel, c_void_p(pbyIn), byref(pFrInfo), byref(DefinitionValue)) + SetLastError(err_code) + return DefinitionValue.value + +def CameraDrawText(pRgbBuffer, pFrInfo, pFontFileName, FontWidth, FontHeight, pText, Left, Top, Width, Height, TextColor, uFlags): + err_code = _sdk.CameraDrawText(c_void_p(pRgbBuffer), byref(pFrInfo), _str_to_string_buffer(pFontFileName), FontWidth, FontHeight, _str_to_string_buffer(pText), Left, Top, Width, Height, TextColor, uFlags) + SetLastError(err_code) + return err_code + +def CameraGigeEnumerateDevice(ipList, MaxCount = 32): + if type(ipList) in (list, tuple): + ipList = map(lambda x: _str_to_string_buffer(x), ipList) + else: + ipList = (_str_to_string_buffer(ipList),) + numIP = len(ipList) + ppIpList = (c_void_p * numIP)(*map(lambda x: addressof(x), ipList)) + Nums = c_int(MaxCount) + pCameraList = (tSdkCameraDevInfo * Nums.value)() + err_code = _sdk.CameraGigeEnumerateDevice(ppIpList, numIP, pCameraList, byref(Nums)) + SetLastError(err_code) + return pCameraList[0:Nums.value] + +def CameraGigeGetIp(pCameraInfo): + CamIp = create_string_buffer(32) + CamMask = create_string_buffer(32) + CamGateWay = create_string_buffer(32) + EtIp = create_string_buffer(32) + EtMask = create_string_buffer(32) + EtGateWay = create_string_buffer(32) + err_code = _sdk.CameraGigeGetIp(byref(pCameraInfo), CamIp, CamMask, CamGateWay, EtIp, EtMask, EtGateWay) + SetLastError(err_code) + return (_string_buffer_to_str(CamIp), _string_buffer_to_str(CamMask), _string_buffer_to_str(CamGateWay), + _string_buffer_to_str(EtIp), _string_buffer_to_str(EtMask), _string_buffer_to_str(EtGateWay) ) + +def CameraGigeSetIp(pCameraInfo, Ip, SubMask, GateWay, bPersistent): + err_code = _sdk.CameraGigeSetIp(byref(pCameraInfo), + _str_to_string_buffer(Ip), _str_to_string_buffer(SubMask), _str_to_string_buffer(GateWay), bPersistent) + SetLastError(err_code) + return err_code + +def CameraGigeGetMac(pCameraInfo): + CamMac = create_string_buffer(32) + EtMac = create_string_buffer(32) + err_code = _sdk.CameraGigeGetMac(byref(pCameraInfo), CamMac, EtMac) + SetLastError(err_code) + return (_string_buffer_to_str(CamMac), _string_buffer_to_str(EtMac) ) + +def CameraEnableFastResponse(hCamera): + err_code = _sdk.CameraEnableFastResponse(hCamera) + SetLastError(err_code) + return err_code + +def CameraSetCorrectDeadPixel(hCamera, bEnable): + err_code = _sdk.CameraSetCorrectDeadPixel(hCamera, bEnable) + SetLastError(err_code) + return err_code + +def CameraGetCorrectDeadPixel(hCamera): + pbEnable = c_int() + err_code = _sdk.CameraGetCorrectDeadPixel(hCamera, byref(pbEnable)) + SetLastError(err_code) + return pbEnable.value + +def CameraFlatFieldingCorrectSetEnable(hCamera, bEnable): + err_code = _sdk.CameraFlatFieldingCorrectSetEnable(hCamera, bEnable) + SetLastError(err_code) + return err_code + +def CameraFlatFieldingCorrectGetEnable(hCamera): + pbEnable = c_int() + err_code = _sdk.CameraFlatFieldingCorrectGetEnable(hCamera, byref(pbEnable)) + SetLastError(err_code) + return pbEnable.value + +def CameraFlatFieldingCorrectSetParameter(hCamera, pDarkFieldingImage, pDarkFieldingFrInfo, pLightFieldingImage, pLightFieldingFrInfo): + err_code = _sdk.CameraFlatFieldingCorrectSetParameter(hCamera, c_void_p(pDarkFieldingImage), byref(pDarkFieldingFrInfo), c_void_p(pLightFieldingImage), byref(pLightFieldingFrInfo)) + SetLastError(err_code) + return err_code + +def CameraFlatFieldingCorrectGetParameterState(hCamera): + pbValid = c_int() + pFilePath = create_string_buffer(1024) + err_code = _sdk.CameraFlatFieldingCorrectGetParameterState(hCamera, byref(pbValid), pFilePath) + SetLastError(err_code) + return (pbValid.value, _string_buffer_to_str(pFilePath) ) + +def CameraFlatFieldingCorrectSaveParameterToFile(hCamera, pszFileName): + err_code = _sdk.CameraFlatFieldingCorrectSaveParameterToFile(hCamera, _str_to_string_buffer(pszFileName)) + SetLastError(err_code) + return err_code + +def CameraFlatFieldingCorrectLoadParameterFromFile(hCamera, pszFileName): + err_code = _sdk.CameraFlatFieldingCorrectLoadParameterFromFile(hCamera, _str_to_string_buffer(pszFileName)) + SetLastError(err_code) + return err_code + +def CameraCommonCall(hCamera, pszCall, uResultBufSize): + pszResult = create_string_buffer(uResultBufSize) if uResultBufSize > 0 else None + err_code = _sdk.CameraCommonCall(hCamera, _str_to_string_buffer(pszCall), pszResult, uResultBufSize) + SetLastError(err_code) + return _string_buffer_to_str(pszResult) if pszResult else '' + +def CameraSetDenoise3DParams(hCamera, bEnable, nCount, Weights): + assert(nCount >= 2 and nCount <= 8) + if Weights: + assert(len(Weights) == nCount) + WeightsNative = (c_float * nCount)(*Weights) + else: + WeightsNative = None + err_code = _sdk.CameraSetDenoise3DParams(hCamera, bEnable, nCount, WeightsNative) + SetLastError(err_code) + return err_code + +def CameraGetDenoise3DParams(hCamera): + bEnable = c_int() + nCount = c_int() + bUseWeight = c_int() + Weights = (c_float * 8)() + err_code = _sdk.CameraGetDenoise3DParams(hCamera, byref(bEnable), byref(nCount), byref(bUseWeight), Weights) + SetLastError(err_code) + bEnable, nCount, bUseWeight = bEnable.value, nCount.value, bUseWeight.value + if bUseWeight: + Weights = Weights[:nCount] + else: + Weights = None + return (bEnable, nCount, bUseWeight, Weights) + +def CameraManualDenoise3D(InFramesHead, InFramesData, nCount, Weights, OutFrameHead, OutFrameData): + assert(nCount > 0) + assert(len(InFramesData) == nCount) + assert(Weights is None or len(Weights) == nCount) + InFramesDataNative = (c_void_p * nCount)(*InFramesData) + WeightsNative = (c_float * nCount)(*Weights) if Weights else None + err_code = _sdk.CameraManualDenoise3D(byref(InFramesHead), InFramesDataNative, nCount, WeightsNative, byref(OutFrameHead), c_void_p(OutFrameData)) + SetLastError(err_code) + return err_code + +def CameraCustomizeDeadPixels(hCamera, hParent): + err_code = _sdk.CameraCustomizeDeadPixels(hCamera, hParent) + SetLastError(err_code) + return err_code + +def CameraReadDeadPixels(hCamera): + pNumPixel = c_int() + err_code = _sdk.CameraReadDeadPixels(hCamera, None, None, byref(pNumPixel)) + SetLastError(err_code) + if pNumPixel.value < 1: + return None + UShortArray = c_ushort * pNumPixel.value + pRows = UShortArray() + pCols = UShortArray() + err_code = _sdk.CameraReadDeadPixels(hCamera, pRows, pCols, byref(pNumPixel)) + SetLastError(err_code) + if err_code == 0: + pNumPixel = pNumPixel.value + else: + pNumPixel = 0 + return (pRows[:pNumPixel], pCols[:pNumPixel]) + +def CameraAddDeadPixels(hCamera, pRows, pCols, NumPixel): + UShortArray = c_ushort * NumPixel + pRowsNative = UShortArray(*pRows) + pColsNative = UShortArray(*pCols) + err_code = _sdk.CameraAddDeadPixels(hCamera, pRowsNative, pColsNative, NumPixel) + SetLastError(err_code) + return err_code + +def CameraRemoveDeadPixels(hCamera, pRows, pCols, NumPixel): + UShortArray = c_ushort * NumPixel + pRowsNative = UShortArray(*pRows) + pColsNative = UShortArray(*pCols) + err_code = _sdk.CameraRemoveDeadPixels(hCamera, pRowsNative, pColsNative, NumPixel) + SetLastError(err_code) + return err_code + +def CameraRemoveAllDeadPixels(hCamera): + err_code = _sdk.CameraRemoveAllDeadPixels(hCamera) + SetLastError(err_code) + return err_code + +def CameraSaveDeadPixels(hCamera): + err_code = _sdk.CameraSaveDeadPixels(hCamera) + SetLastError(err_code) + return err_code + +def CameraSaveDeadPixelsToFile(hCamera, sFileName): + err_code = _sdk.CameraSaveDeadPixelsToFile(hCamera, _str_to_string_buffer(sFileName)) + SetLastError(err_code) + return err_code + +def CameraLoadDeadPixelsFromFile(hCamera, sFileName): + err_code = _sdk.CameraLoadDeadPixelsFromFile(hCamera, _str_to_string_buffer(sFileName)) + SetLastError(err_code) + return err_code + +def CameraGetImageBufferPriority(hCamera, wTimes, Priority): + pFrameInfo = tSdkFrameHead() + pbyBuffer = c_void_p() + err_code = _sdk.CameraGetImageBufferPriority(hCamera, byref(pFrameInfo), byref(pbyBuffer), wTimes, Priority) + SetLastError(err_code) + if err_code != 0: + raise CameraException(err_code) + return (pbyBuffer.value, pFrameInfo) + +def CameraGetImageBufferPriorityEx(hCamera, wTimes, Priority): + _sdk.CameraGetImageBufferPriorityEx.restype = c_void_p + piWidth = c_int() + piHeight = c_int() + pFrameBuffer = _sdk.CameraGetImageBufferPriorityEx(hCamera, byref(piWidth), byref(piHeight), wTimes, Priority) + err_code = CAMERA_STATUS_SUCCESS if pFrameBuffer else CAMERA_STATUS_TIME_OUT + SetLastError(err_code) + if pFrameBuffer: + return (pFrameBuffer, piWidth.value, piHeight.value) + else: + raise CameraException(err_code) + +def CameraGetImageBufferPriorityEx2(hCamera, pImageData, uOutFormat, wTimes, Priority): + piWidth = c_int() + piHeight = c_int() + err_code = _sdk.CameraGetImageBufferPriorityEx2(hCamera, c_void_p(pImageData), uOutFormat, byref(piWidth), byref(piHeight), wTimes, Priority) + SetLastError(err_code) + if err_code != 0: + raise CameraException(err_code) + return (piWidth.value, piHeight.value) + +def CameraGetImageBufferPriorityEx3(hCamera, pImageData, uOutFormat, wTimes, Priority): + piWidth = c_int() + piHeight = c_int() + puTimeStamp = c_uint() + err_code = _sdk.CameraGetImageBufferPriorityEx3(hCamera, c_void_p(pImageData), uOutFormat, byref(piWidth), byref(piHeight), byref(puTimeStamp), wTimes, Priority) + SetLastError(err_code) + if err_code != 0: + raise CameraException(err_code) + return (piWidth.value, piHeight.value, puTimeStamp.value) + +def CameraClearBuffer(hCamera): + err_code = _sdk.CameraClearBuffer(hCamera) + SetLastError(err_code) + return err_code + +def CameraSoftTriggerEx(hCamera, uFlags): + err_code = _sdk.CameraSoftTriggerEx(hCamera, uFlags) + SetLastError(err_code) + return err_code + +def CameraSetHDR(hCamera, value): + err_code = _sdk.CameraSetHDR(hCamera, value) + SetLastError(err_code) + return err_code + +def CameraGetHDR(hCamera): + value = c_int() + err_code = _sdk.CameraGetHDR(hCamera, byref(value)) + SetLastError(err_code) + return value.value + +def CameraGetFrameID(hCamera): + FrameID = c_uint() + err_code = _sdk.CameraGetFrameID(hCamera, byref(FrameID)) + SetLastError(err_code) + return FrameID.value + +def CameraGetFrameTimeStamp(hCamera): + TimeStamp = c_uint64() + TimeStampL = c_uint32.from_buffer(TimeStamp) + TimeStampH = c_uint32.from_buffer(TimeStamp, 4) + err_code = _sdk.CameraGetFrameTimeStamp(hCamera, byref(TimeStampL), byref(TimeStampH)) + SetLastError(err_code) + return TimeStamp.value + +def CameraSetHDRGainMode(hCamera, value): + err_code = _sdk.CameraSetHDRGainMode(hCamera, value) + SetLastError(err_code) + return err_code + +def CameraGetHDRGainMode(hCamera): + value = c_int() + err_code = _sdk.CameraGetHDRGainMode(hCamera, byref(value)) + SetLastError(err_code) + return value.value + +def CameraCreateDIBitmap(hDC, pFrameBuffer, pFrameHead): + outBitmap = c_void_p() + err_code = _sdk.CameraCreateDIBitmap(hDC, c_void_p(pFrameBuffer), byref(pFrameHead), byref(outBitmap)) + SetLastError(err_code) + return outBitmap.value + +def CameraDrawFrameBuffer(pFrameBuffer, pFrameHead, hWnd, Algorithm, Mode): + err_code = _sdk.CameraDrawFrameBuffer(c_void_p(pFrameBuffer), byref(pFrameHead), c_void_p(hWnd), Algorithm, Mode) + SetLastError(err_code) + return err_code + +def CameraFlipFrameBuffer(pFrameBuffer, pFrameHead, Flags): + err_code = _sdk.CameraFlipFrameBuffer(c_void_p(pFrameBuffer), byref(pFrameHead), Flags) + SetLastError(err_code) + return err_code + +def CameraConvertFrameBufferFormat(hCamera, pInFrameBuffer, pOutFrameBuffer, outWidth, outHeight, outMediaType, pFrameHead): + err_code = _sdk.CameraConvertFrameBufferFormat(hCamera, c_void_p(pInFrameBuffer), c_void_p(pOutFrameBuffer), outWidth, outHeight, outMediaType, byref(pFrameHead)) + SetLastError(err_code) + return err_code + +def CameraSetConnectionStatusCallback(hCamera, pCallBack, pContext = 0): + err_code = _sdk.CameraSetConnectionStatusCallback(hCamera, pCallBack, c_void_p(pContext) ) + SetLastError(err_code) + return err_code + +def CameraSetLightingControllerMode(hCamera, index, mode): + err_code = _sdk.CameraSetLightingControllerMode(hCamera, index, mode) + SetLastError(err_code) + return err_code + +def CameraSetLightingControllerState(hCamera, index, state): + err_code = _sdk.CameraSetLightingControllerState(hCamera, index, state) + SetLastError(err_code) + return err_code + +def CameraSetFrameResendCount(hCamera, count): + err_code = _sdk.CameraSetFrameResendCount(hCamera, count) + SetLastError(err_code) + return err_code + +def CameraSetUndistortParams(hCamera, width, height, cameraMatrix, distCoeffs): + assert(len(cameraMatrix) == 4) + assert(len(distCoeffs) == 5) + cameraMatrixNative = (c_double * len(cameraMatrix))(*cameraMatrix) + distCoeffsNative = (c_double * len(distCoeffs))(*distCoeffs) + err_code = _sdk.CameraSetUndistortParams(hCamera, width, height, cameraMatrixNative, distCoeffsNative) + SetLastError(err_code) + return err_code + +def CameraGetUndistortParams(hCamera): + width = c_int() + height = c_int() + cameraMatrix = (c_double * 4)() + distCoeffs = (c_double * 5)() + err_code = _sdk.CameraGetUndistortParams(hCamera, byref(width), byref(height), cameraMatrix, distCoeffs) + SetLastError(err_code) + width, height = width.value, height.value + cameraMatrix = cameraMatrix[:] + distCoeffs = distCoeffs[:] + return (width, height, cameraMatrix, distCoeffs) + +def CameraSetUndistortEnable(hCamera, bEnable): + err_code = _sdk.CameraSetUndistortEnable(hCamera, bEnable) + SetLastError(err_code) + return err_code + +def CameraGetUndistortEnable(hCamera): + value = c_int() + err_code = _sdk.CameraGetUndistortEnable(hCamera, byref(value)) + SetLastError(err_code) + return value.value + +def CameraCustomizeUndistort(hCamera, hParent): + err_code = _sdk.CameraCustomizeUndistort(hCamera, hParent) + SetLastError(err_code) + return err_code + +def CameraGetEyeCount(hCamera): + EyeCount = c_int() + err_code = _sdk.CameraGetEyeCount(hCamera, byref(EyeCount)) + SetLastError(err_code) + return EyeCount.value + +def CameraMultiEyeImageProcess(hCamera, iEyeIndex, pbyIn, pInFrInfo, pbyOut, pOutFrInfo, uOutFormat, uReserved): + err_code = _sdk.CameraMultiEyeImageProcess(hCamera, iEyeIndex, c_void_p(pbyIn), byref(pInFrInfo), c_void_p(pbyOut), byref(pOutFrInfo), uOutFormat, uReserved) + SetLastError(err_code) + return err_code + +# CameraGrabber + +def CameraGrabber_CreateFromDevicePage(): + Grabber = c_void_p() + err_code = _sdk.CameraGrabber_CreateFromDevicePage(byref(Grabber)) + SetLastError(err_code) + if err_code != 0: + raise CameraException(err_code) + return Grabber.value + +def CameraGrabber_CreateByIndex(Index): + Grabber = c_void_p() + err_code = _sdk.CameraGrabber_CreateByIndex(byref(Grabber), Index) + SetLastError(err_code) + if err_code != 0: + raise CameraException(err_code) + return Grabber.value + +def CameraGrabber_CreateByName(Name): + Grabber = c_void_p() + err_code = _sdk.CameraGrabber_CreateByName(byref(Grabber), _str_to_string_buffer(Name)) + SetLastError(err_code) + if err_code != 0: + raise CameraException(err_code) + return Grabber.value + +def CameraGrabber_Create(pDevInfo): + Grabber = c_void_p() + err_code = _sdk.CameraGrabber_Create(byref(Grabber), byref(pDevInfo)) + SetLastError(err_code) + if err_code != 0: + raise CameraException(err_code) + return Grabber.value + +def CameraGrabber_Destroy(Grabber): + err_code = _sdk.CameraGrabber_Destroy(c_void_p(Grabber)) + SetLastError(err_code) + return err_code + +def CameraGrabber_SetHWnd(Grabber, hWnd): + err_code = _sdk.CameraGrabber_SetHWnd(c_void_p(Grabber), c_void_p(hWnd) ) + SetLastError(err_code) + return err_code + +def CameraGrabber_SetPriority(Grabber, Priority): + err_code = _sdk.CameraGrabber_SetPriority(c_void_p(Grabber), Priority) + SetLastError(err_code) + return err_code + +def CameraGrabber_StartLive(Grabber): + err_code = _sdk.CameraGrabber_StartLive(c_void_p(Grabber)) + SetLastError(err_code) + return err_code + +def CameraGrabber_StopLive(Grabber): + err_code = _sdk.CameraGrabber_StopLive(c_void_p(Grabber)) + SetLastError(err_code) + return err_code + +def CameraGrabber_SaveImage(Grabber, TimeOut): + Image = c_void_p() + err_code = _sdk.CameraGrabber_SaveImage(c_void_p(Grabber), byref(Image), TimeOut) + SetLastError(err_code) + if err_code != 0: + raise CameraException(err_code) + return Image.value + +def CameraGrabber_SaveImageAsync(Grabber): + err_code = _sdk.CameraGrabber_SaveImageAsync(c_void_p(Grabber)) + SetLastError(err_code) + return err_code + +def CameraGrabber_SaveImageAsyncEx(Grabber, UserData): + err_code = _sdk.CameraGrabber_SaveImageAsyncEx(c_void_p(Grabber), c_void_p(UserData)) + SetLastError(err_code) + return err_code + +def CameraGrabber_SetSaveImageCompleteCallback(Grabber, Callback, Context = 0): + err_code = _sdk.CameraGrabber_SetSaveImageCompleteCallback(c_void_p(Grabber), Callback, c_void_p(Context)) + SetLastError(err_code) + return err_code + +def CameraGrabber_SetFrameListener(Grabber, Listener, Context = 0): + err_code = _sdk.CameraGrabber_SetFrameListener(c_void_p(Grabber), Listener, c_void_p(Context)) + SetLastError(err_code) + return err_code + +def CameraGrabber_SetRawCallback(Grabber, Callback, Context = 0): + err_code = _sdk.CameraGrabber_SetRawCallback(c_void_p(Grabber), Callback, c_void_p(Context)) + SetLastError(err_code) + return err_code + +def CameraGrabber_SetRGBCallback(Grabber, Callback, Context = 0): + err_code = _sdk.CameraGrabber_SetRGBCallback(c_void_p(Grabber), Callback, c_void_p(Context)) + SetLastError(err_code) + return err_code + +def CameraGrabber_GetCameraHandle(Grabber): + hCamera = c_int() + err_code = _sdk.CameraGrabber_GetCameraHandle(c_void_p(Grabber), byref(hCamera)) + SetLastError(err_code) + return hCamera.value + +def CameraGrabber_GetStat(Grabber): + stat = tSdkGrabberStat() + err_code = _sdk.CameraGrabber_GetStat(c_void_p(Grabber), byref(stat)) + SetLastError(err_code) + return stat + +def CameraGrabber_GetCameraDevInfo(Grabber): + DevInfo = tSdkCameraDevInfo() + err_code = _sdk.CameraGrabber_GetCameraDevInfo(c_void_p(Grabber), byref(DevInfo)) + SetLastError(err_code) + return DevInfo + +# CameraImage + +def CameraImage_Create(pFrameBuffer, pFrameHead, bCopy): + Image = c_void_p() + err_code = _sdk.CameraImage_Create(byref(Image), c_void_p(pFrameBuffer), byref(pFrameHead), bCopy) + SetLastError(err_code) + return Image.value + +def CameraImage_CreateEmpty(): + Image = c_void_p() + err_code = _sdk.CameraImage_CreateEmpty(byref(Image)) + SetLastError(err_code) + return Image.value + +def CameraImage_Destroy(Image): + err_code = _sdk.CameraImage_Destroy(c_void_p(Image)) + SetLastError(err_code) + return err_code + +def CameraImage_GetData(Image): + DataBuffer = c_void_p() + HeadPtr = c_void_p() + err_code = _sdk.CameraImage_GetData(c_void_p(Image), byref(DataBuffer), byref(HeadPtr)) + SetLastError(err_code) + if err_code == 0: + return (DataBuffer.value, tSdkFrameHead.from_address(HeadPtr.value) ) + else: + return (0, None) + +def CameraImage_GetUserData(Image): + UserData = c_void_p() + err_code = _sdk.CameraImage_GetUserData(c_void_p(Image), byref(UserData)) + SetLastError(err_code) + return UserData.value + +def CameraImage_SetUserData(Image, UserData): + err_code = _sdk.CameraImage_SetUserData(c_void_p(Image), c_void_p(UserData)) + SetLastError(err_code) + return err_code + +def CameraImage_IsEmpty(Image): + IsEmpty = c_int() + err_code = _sdk.CameraImage_IsEmpty(c_void_p(Image), byref(IsEmpty)) + SetLastError(err_code) + return IsEmpty.value + +def CameraImage_Draw(Image, hWnd, Algorithm): + err_code = _sdk.CameraImage_Draw(c_void_p(Image), c_void_p(hWnd), Algorithm) + SetLastError(err_code) + return err_code + +def CameraImage_DrawFit(Image, hWnd, Algorithm): + err_code = _sdk.CameraImage_DrawFit(c_void_p(Image), c_void_p(hWnd), Algorithm) + SetLastError(err_code) + return err_code + +def CameraImage_DrawToDC(Image, hDC, Algorithm, xDst, yDst, cxDst, cyDst): + err_code = _sdk.CameraImage_DrawToDC(c_void_p(Image), c_void_p(hDC), Algorithm, xDst, yDst, cxDst, cyDst) + SetLastError(err_code) + return err_code + +def CameraImage_DrawToDCFit(Image, hDC, Algorithm, xDst, yDst, cxDst, cyDst): + err_code = _sdk.CameraImage_DrawToDCFit(c_void_p(Image), c_void_p(hDC), Algorithm, xDst, yDst, cxDst, cyDst) + SetLastError(err_code) + return err_code + +def CameraImage_BitBlt(Image, hWnd, xDst, yDst, cxDst, cyDst, xSrc, ySrc): + err_code = _sdk.CameraImage_BitBlt(c_void_p(Image), c_void_p(hWnd), xDst, yDst, cxDst, cyDst, xSrc, ySrc) + SetLastError(err_code) + return err_code + +def CameraImage_BitBltToDC(Image, hDC, xDst, yDst, cxDst, cyDst, xSrc, ySrc): + err_code = _sdk.CameraImage_BitBltToDC(c_void_p(Image), c_void_p(hDC), xDst, yDst, cxDst, cyDst, xSrc, ySrc) + SetLastError(err_code) + return err_code + +def CameraImage_SaveAsBmp(Image, FileName): + err_code = _sdk.CameraImage_SaveAsBmp(c_void_p(Image), _str_to_string_buffer(FileName)) + SetLastError(err_code) + return err_code + +def CameraImage_SaveAsJpeg(Image, FileName, Quality): + err_code = _sdk.CameraImage_SaveAsJpeg(c_void_p(Image), _str_to_string_buffer(FileName), Quality) + SetLastError(err_code) + return err_code + +def CameraImage_SaveAsPng(Image, FileName): + err_code = _sdk.CameraImage_SaveAsPng(c_void_p(Image), _str_to_string_buffer(FileName)) + SetLastError(err_code) + return err_code + +def CameraImage_SaveAsRaw(Image, FileName, Format): + err_code = _sdk.CameraImage_SaveAsRaw(c_void_p(Image), _str_to_string_buffer(FileName), Format) + SetLastError(err_code) + return err_code + +def CameraImage_IPicture(Image): + NewPic = c_void_p() + err_code = _sdk.CameraImage_IPicture(c_void_p(Image), byref(NewPic)) + SetLastError(err_code) + return NewPic.value diff --git a/python demo/readme.txt b/python demo/readme.txt new file mode 100644 index 0000000..749c79e --- /dev/null +++ b/python demo/readme.txt @@ -0,0 +1,4 @@ +mvsdk.py: 相机SDK接口库(参考文档 WindowsSDK安装目录\Document\MVSDK_API_CHS.chm) + +grab.py: 使用SDK采集图片,并保存到硬盘文件 +cv_grab.py: 使用SDK采集图片,转换为opencv的图像格式 diff --git a/test_exposure.py b/test_exposure.py new file mode 100644 index 0000000..bcfb0fd --- /dev/null +++ b/test_exposure.py @@ -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...")