mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-30 02:31:44 +00:00
Removes NiVision from allwpilib (#305)
This commit is contained in:
committed by
Peter Johnson
parent
ecb873ff45
commit
ac50d7cf8a
@@ -1,86 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "ErrorBase.h"
|
||||
#include "HAL/cpp/priority_mutex.h"
|
||||
#include "NIIMAQdx.h"
|
||||
#include "USBCamera.h"
|
||||
#include "nivision.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
class CameraServer : public ErrorBase {
|
||||
private:
|
||||
static constexpr uint16_t kPort = 1180;
|
||||
static constexpr uint8_t kMagicNumber[] = {0x01, 0x00, 0x00, 0x00};
|
||||
static constexpr int kSize640x480 = 0;
|
||||
static constexpr int kSize320x240 = 1;
|
||||
static constexpr int kSize160x120 = 2;
|
||||
static constexpr int kHardwareCompression = -1;
|
||||
static constexpr int kMaxImageSize = 200000;
|
||||
|
||||
protected:
|
||||
CameraServer();
|
||||
|
||||
std::shared_ptr<USBCamera> m_camera;
|
||||
std::thread m_serverThread;
|
||||
std::thread m_captureThread;
|
||||
priority_recursive_mutex m_imageMutex;
|
||||
std::condition_variable_any m_newImageVariable;
|
||||
std::vector<uint8_t*> m_dataPool;
|
||||
int m_quality;
|
||||
bool m_autoCaptureStarted;
|
||||
bool m_hwClient;
|
||||
std::tuple<uint8_t*, int, int, bool> m_imageData;
|
||||
|
||||
void Serve();
|
||||
void AutoCapture();
|
||||
void SetImageData(uint8_t* data, int size, int start = 0,
|
||||
bool imaqData = false);
|
||||
void FreeImageData(std::tuple<uint8_t*, int, int, bool> imageData);
|
||||
|
||||
struct Request {
|
||||
int fps;
|
||||
int compression;
|
||||
int size;
|
||||
};
|
||||
|
||||
public:
|
||||
static CameraServer* GetInstance();
|
||||
void SetImage(Image const* image);
|
||||
|
||||
void StartAutomaticCapture(
|
||||
char const* cameraName = USBCamera::kDefaultCameraName);
|
||||
|
||||
/**
|
||||
* Start automatically capturing images to send to the dashboard.
|
||||
*
|
||||
* You should call this method to just see a camera feed on the
|
||||
* dashboard without doing any vision processing on the roboRIO.
|
||||
* {@link #SetImage} should not be called after this is called.
|
||||
*
|
||||
* @param camera The camera interface (eg. USBCamera)
|
||||
*/
|
||||
void StartAutomaticCapture(std::shared_ptr<USBCamera> camera);
|
||||
|
||||
bool IsAutoCaptureStarted();
|
||||
|
||||
void SetQuality(int quality);
|
||||
int GetQuality();
|
||||
|
||||
void SetSize(int size);
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
@@ -1,950 +0,0 @@
|
||||
//==============================================================================
|
||||
//
|
||||
// Title : NIIMAQdx.h
|
||||
// Created : 1403685834 seconds after 1/1/1970 12:00:00 UTC
|
||||
// Copyright : © Copyright 2006, National Instruments Corporation, All rights
|
||||
// reserved
|
||||
// Purpose : Include file for NI-IMAQdx library support.
|
||||
//
|
||||
//==============================================================================
|
||||
#ifndef ___niimaqdx_h___
|
||||
#define ___niimaqdx_h___
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined(niimaqdx_types)
|
||||
#define niimaqdx_types
|
||||
|
||||
#ifdef _CVI_
|
||||
#pragma EnableLibraryRuntimeChecking
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
// Typedefs
|
||||
//==============================================================================
|
||||
#ifndef _NI_uInt8_DEFINED_
|
||||
#define _NI_uInt8_DEFINED_
|
||||
typedef unsigned char uInt8;
|
||||
#endif
|
||||
|
||||
#ifndef _NI_uInt16_DEFINED_
|
||||
#define _NI_uInt16_DEFINED_
|
||||
typedef unsigned short int uInt16;
|
||||
#endif
|
||||
|
||||
#ifndef _NI_uInt32_DEFINED_
|
||||
#define _NI_uInt32_DEFINED_
|
||||
#if defined(_MSC_VER)
|
||||
typedef unsigned long uInt32;
|
||||
#elif __GNUC__
|
||||
#if __x86_64__
|
||||
typedef unsigned int uInt32;
|
||||
#else
|
||||
typedef unsigned long uInt32;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _NI_uInt64_DEFINED_
|
||||
#define _NI_uInt64_DEFINED_
|
||||
#if defined(_MSC_VER) || _CVI_ >= 700
|
||||
typedef unsigned __int64 uInt64;
|
||||
#elif __GNUC__
|
||||
typedef unsigned long long uInt64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _NI_Int8_DEFINED_
|
||||
#define _NI_Int8_DEFINED_
|
||||
typedef char Int8;
|
||||
#endif
|
||||
|
||||
#ifndef _NI_Int16_DEFINED_
|
||||
#define _NI_Int16_DEFINED_
|
||||
typedef short int Int16;
|
||||
#endif
|
||||
|
||||
#ifndef _NI_Int32_DEFINED_
|
||||
#define _NI_Int32_DEFINED_
|
||||
#if defined(_MSC_VER)
|
||||
typedef long Int32;
|
||||
#elif __GNUC__
|
||||
#if __x86_64__
|
||||
typedef int Int32;
|
||||
#else
|
||||
typedef long Int32;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _NI_Int64_DEFINED_
|
||||
#define _NI_Int64_DEFINED_
|
||||
#if defined(_MSC_VER) || _CVI_ >= 700
|
||||
typedef __int64 Int64;
|
||||
#elif __GNUC__
|
||||
typedef long long int Int64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _NI_float32_DEFINED_
|
||||
#define _NI_float32_DEFINED_
|
||||
typedef float float32;
|
||||
#endif
|
||||
|
||||
#ifndef _NI_float64_DEFINED_
|
||||
#define _NI_float64_DEFINED_
|
||||
typedef double float64;
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE (1L)
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE (0L)
|
||||
#endif
|
||||
|
||||
#ifndef _NI_GUIDHNDL_DEFINED
|
||||
typedef uInt32 GUIHNDL;
|
||||
#endif
|
||||
|
||||
#if (defined(_MSC_VER) || defined(_CVI_))
|
||||
#ifndef _NI_FUNC_DEFINED
|
||||
#define NI_FUNC __stdcall
|
||||
#endif
|
||||
|
||||
#ifndef _NI_FUNCC_DEFINED
|
||||
#define NI_FUNCC __cdecl
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
#ifndef _NI_FUNC_DEFINED
|
||||
#define NI_FUNC
|
||||
#endif
|
||||
|
||||
#ifndef _NI_FUNCC_DEFINED
|
||||
#define NI_FUNCC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _NI_bool32_DEFINED_
|
||||
#define _NI_bool32_DEFINED_
|
||||
typedef uInt32 bool32;
|
||||
#endif
|
||||
|
||||
#ifndef _NI_IMAQdxSession_DEFINED_
|
||||
#define _NI_IMAQdxSession_DEFINED_
|
||||
typedef uInt32 IMAQdxSession;
|
||||
#endif
|
||||
|
||||
#define IMAQDX_MAX_API_STRING_LENGTH 512
|
||||
|
||||
//==============================================================================
|
||||
// Forward Declare Data Structures
|
||||
//==============================================================================
|
||||
typedef struct Image_struct Image;
|
||||
|
||||
//==============================================================================
|
||||
// Error Codes Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxError_enum {
|
||||
IMAQdxErrorSuccess = 0x0, // Success
|
||||
IMAQdxErrorSystemMemoryFull = 0xBFF69000, // Not enough memory
|
||||
IMAQdxErrorInternal, // Internal error
|
||||
IMAQdxErrorInvalidParameter, // Invalid parameter
|
||||
IMAQdxErrorInvalidPointer, // Invalid pointer
|
||||
IMAQdxErrorInvalidInterface, // Invalid camera session
|
||||
IMAQdxErrorInvalidRegistryKey, // Invalid registry key
|
||||
IMAQdxErrorInvalidAddress, // Invalid address
|
||||
IMAQdxErrorInvalidDeviceType, // Invalid device type
|
||||
IMAQdxErrorNotImplemented, // Not implemented
|
||||
IMAQdxErrorCameraNotFound, // Camera not found
|
||||
IMAQdxErrorCameraInUse, // Camera is already in use.
|
||||
IMAQdxErrorCameraNotInitialized, // Camera is not initialized.
|
||||
IMAQdxErrorCameraRemoved, // Camera has been removed.
|
||||
IMAQdxErrorCameraRunning, // Acquisition in progress.
|
||||
IMAQdxErrorCameraNotRunning, // No acquisition in progress.
|
||||
IMAQdxErrorAttributeNotSupported, // Attribute not supported by the camera.
|
||||
IMAQdxErrorAttributeNotSettable, // Unable to set attribute.
|
||||
IMAQdxErrorAttributeNotReadable, // Unable to get attribute.
|
||||
IMAQdxErrorAttributeOutOfRange, // Attribute value is out of range.
|
||||
IMAQdxErrorBufferNotAvailable, // Requested buffer is unavailable.
|
||||
IMAQdxErrorBufferListEmpty, // Buffer list is empty. Add one or more buffers.
|
||||
IMAQdxErrorBufferListLocked, // Buffer list is already locked. Reconfigure
|
||||
// acquisition and try again.
|
||||
IMAQdxErrorBufferListNotLocked, // No buffer list. Reconfigure acquisition
|
||||
// and try again.
|
||||
IMAQdxErrorResourcesAllocated, // Transfer engine resources already
|
||||
// allocated. Reconfigure acquisition and try
|
||||
// again.
|
||||
IMAQdxErrorResourcesUnavailable, // Insufficient transfer engine resources.
|
||||
IMAQdxErrorAsyncWrite, // Unable to perform asychronous register write.
|
||||
IMAQdxErrorAsyncRead, // Unable to perform asychronous register read.
|
||||
IMAQdxErrorTimeout, // Timeout.
|
||||
IMAQdxErrorBusReset, // Bus reset occurred during a transaction.
|
||||
IMAQdxErrorInvalidXML, // Unable to load camera's XML file.
|
||||
IMAQdxErrorFileAccess, // Unable to read/write to file.
|
||||
IMAQdxErrorInvalidCameraURLString, // Camera has malformed URL string.
|
||||
IMAQdxErrorInvalidCameraFile, // Invalid camera file.
|
||||
IMAQdxErrorGenICamError, // Unknown Genicam error.
|
||||
IMAQdxErrorFormat7Parameters, // For format 7: The combination of speed,
|
||||
// image position, image size, and color coding
|
||||
// is incorrect.
|
||||
IMAQdxErrorInvalidAttributeType, // The attribute type is not compatible with
|
||||
// the passed variable type.
|
||||
IMAQdxErrorDLLNotFound, // The DLL could not be found.
|
||||
IMAQdxErrorFunctionNotFound, // The function could not be found.
|
||||
IMAQdxErrorLicenseNotActivated, // License not activated.
|
||||
IMAQdxErrorCameraNotConfiguredForListener, // The camera is not configured
|
||||
// properly to support a listener.
|
||||
IMAQdxErrorCameraMulticastNotAvailable, // Unable to configure the system for
|
||||
// multicast support.
|
||||
IMAQdxErrorBufferHasLostPackets, // The requested buffer has lost packets and
|
||||
// the user requested an error to be
|
||||
// generated.
|
||||
IMAQdxErrorGiGEVisionError, // Unknown GiGE Vision error.
|
||||
IMAQdxErrorNetworkError, // Unknown network error.
|
||||
IMAQdxErrorCameraUnreachable, // Unable to connect to the camera.
|
||||
IMAQdxErrorHighPerformanceNotSupported, // High performance acquisition is
|
||||
// not supported on the specified
|
||||
// network interface. Connect the
|
||||
// camera to a network interface
|
||||
// running the high performance
|
||||
// driver.
|
||||
IMAQdxErrorInterfaceNotRenamed, // Unable to rename interface. Invalid or
|
||||
// duplicate name specified.
|
||||
IMAQdxErrorNoSupportedVideoModes, // The camera does not have any video modes
|
||||
// which are supported.
|
||||
IMAQdxErrorSoftwareTriggerOverrun, // Software trigger overrun.
|
||||
IMAQdxErrorTestPacketNotReceived, // The system did not receive a test packet
|
||||
// from the camera. The packet size may be
|
||||
// too large for the network configuration
|
||||
// or a firewall may be enabled.
|
||||
IMAQdxErrorCorruptedImageReceived, // The camera returned a corrupted image.
|
||||
IMAQdxErrorCameraConfigurationHasChanged, // The camera did not return an
|
||||
// image of the correct type it was
|
||||
// configured for previously.
|
||||
IMAQdxErrorCameraInvalidAuthentication, // The camera is configured with
|
||||
// password authentication and either
|
||||
// the user name and password were
|
||||
// not configured or they are
|
||||
// incorrect.
|
||||
IMAQdxErrorUnknownHTTPError, // The camera returned an unknown HTTP error.
|
||||
IMAQdxErrorKernelDriverUnavailable, // Unable to attach to the kernel mode
|
||||
// driver.
|
||||
IMAQdxErrorPixelFormatDecoderUnavailable, // No decoder available for
|
||||
// selected pixel format.
|
||||
IMAQdxErrorFirmwareUpdateNeeded, // The acquisition hardware needs a firmware
|
||||
// update before it can be used.
|
||||
IMAQdxErrorFirmwareUpdateRebootNeeded, // The firmware on the acquisition
|
||||
// hardware has been updated and the
|
||||
// system must be rebooted before use.
|
||||
IMAQdxErrorLightingCurrentOutOfRange, // The requested current level from the
|
||||
// lighting controller is not possible.
|
||||
IMAQdxErrorUSB3VisionError, // Unknown USB3 Vision error.
|
||||
IMAQdxErrorInvalidU3VUSBDescriptor, // The camera has a USB descriptor that
|
||||
// is incompatible with the USB3 Vision
|
||||
// specification.
|
||||
IMAQdxErrorU3VInvalidControlInterface, // The USB3 Vision control interface
|
||||
// is not implemented or is invalid on
|
||||
// this camera.
|
||||
IMAQdxErrorU3VControlInterfaceError, // There was an error from the control
|
||||
// interface of the USB3 Vision camera.
|
||||
IMAQdxErrorU3VInvalidEventInterface, // The USB3 Vision event interface is
|
||||
// not implemented or is invalid on this
|
||||
// camera.
|
||||
IMAQdxErrorU3VEventInterfaceError, // There was an error from the event
|
||||
// interface of the USB3 Vision camera.
|
||||
IMAQdxErrorU3VInvalidStreamInterface, // The USB3 Vision stream interface is
|
||||
// not implemented or is invalid on
|
||||
// this camera.
|
||||
IMAQdxErrorU3VStreamInterfaceError, // There was an error from the stream
|
||||
// interface of the USB3 Vision camera.
|
||||
IMAQdxErrorU3VUnsupportedConnectionSpeed, // The USB connection speed is not
|
||||
// supported by the camera. Check
|
||||
// whether the camera is plugged
|
||||
// into a USB 2.0 port instead of a
|
||||
// USB 3.0 port. If so, verify
|
||||
// that the camera supports this
|
||||
// use case.
|
||||
IMAQdxErrorU3VInsufficientPower, // The USB3 Vision camera requires more
|
||||
// current than can be supplied by the USB
|
||||
// port in use.
|
||||
IMAQdxErrorU3VInvalidMaxCurrent, // The U3V_MaximumCurrentUSB20_mA registry
|
||||
// value is not valid for the connected USB3
|
||||
// Vision camera.
|
||||
IMAQdxErrorBufferIncompleteData, // The requested buffer has incomplete data
|
||||
// and the user requested an error to be
|
||||
// generated.
|
||||
IMAQdxErrorCameraAcquisitionConfigFailed, // The camera returned an error
|
||||
// starting the acquisition.
|
||||
IMAQdxErrorCameraClosePending, // The camera still has outstanding references
|
||||
// and will be closed when these operations
|
||||
// complete.
|
||||
IMAQdxErrorSoftwareFault, // An unexpected software error occurred.
|
||||
IMAQdxErrorCameraPropertyInvalid, // The value for an invalid camera property
|
||||
// was requested.
|
||||
IMAQdxErrorJumboFramesNotEnabled, // Jumbo frames are not enabled on the
|
||||
// host. Maximum packet size is 1500
|
||||
// bytes.
|
||||
IMAQdxErrorBayerPixelFormatNotSelected, // This operation requires that the
|
||||
// camera has a Bayer pixel format
|
||||
// selected.
|
||||
IMAQdxErrorGuard = 0xFFFFFFFF,
|
||||
} IMAQdxError;
|
||||
|
||||
//==============================================================================
|
||||
// Bus Type Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxBusType_enum {
|
||||
IMAQdxBusTypeFireWire = 0x31333934,
|
||||
IMAQdxBusTypeEthernet = 0x69707634,
|
||||
IMAQdxBusTypeSimulator = 0x2073696D,
|
||||
IMAQdxBusTypeDirectShow = 0x64736877,
|
||||
IMAQdxBusTypeIP = 0x4950636D,
|
||||
IMAQdxBusTypeSmartCam2 = 0x53436132,
|
||||
IMAQdxBusTypeUSB3Vision = 0x55534233,
|
||||
IMAQdxBusTypeUVC = 0x55564320,
|
||||
IMAQdxBusTypeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxBusType;
|
||||
|
||||
//==============================================================================
|
||||
// Camera Control Mode Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxCameraControlMode_enum {
|
||||
IMAQdxCameraControlModeController,
|
||||
IMAQdxCameraControlModeListener,
|
||||
IMAQdxCameraControlModeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxCameraControlMode;
|
||||
|
||||
//==============================================================================
|
||||
// Buffer Number Mode Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxBufferNumberMode_enum {
|
||||
IMAQdxBufferNumberModeNext,
|
||||
IMAQdxBufferNumberModeLast,
|
||||
IMAQdxBufferNumberModeBufferNumber,
|
||||
IMAQdxBufferNumberModeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxBufferNumberMode;
|
||||
|
||||
//==============================================================================
|
||||
// Plug n Play Event Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxPnpEvent_enum {
|
||||
IMAQdxPnpEventCameraAttached,
|
||||
IMAQdxPnpEventCameraDetached,
|
||||
IMAQdxPnpEventBusReset,
|
||||
IMAQdxPnpEventGuard = 0xFFFFFFFF,
|
||||
} IMAQdxPnpEvent;
|
||||
|
||||
//==============================================================================
|
||||
// Bayer Pattern Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxBayerPattern_enum {
|
||||
IMAQdxBayerPatternNone,
|
||||
IMAQdxBayerPatternGB,
|
||||
IMAQdxBayerPatternGR,
|
||||
IMAQdxBayerPatternBG,
|
||||
IMAQdxBayerPatternRG,
|
||||
IMAQdxBayerPatternHardware,
|
||||
IMAQdxBayerPatternGuard = 0xFFFFFFFF,
|
||||
} IMAQdxBayerPattern;
|
||||
|
||||
//==============================================================================
|
||||
// Bayer Decode Algorithm Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxBayerAlgorithm_enum {
|
||||
IMAQdxBayerAlgorithmBilinear,
|
||||
IMAQdxBayerAlgorithmVNG,
|
||||
IMAQdxBayerAlgorithmGuard = 0xFFFFFFFF,
|
||||
} IMAQdxBayerAlgorithm;
|
||||
|
||||
//==============================================================================
|
||||
// Output Image Types -- Values match Vision Development Module image types
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxOutputImageType_enum {
|
||||
IMAQdxOutputImageTypeU8 = 0,
|
||||
IMAQdxOutputImageTypeI16 = 1,
|
||||
IMAQdxOutputImageTypeU16 = 7,
|
||||
IMAQdxOutputImageTypeRGB32 = 4,
|
||||
IMAQdxOutputImageTypeRGB64 = 6,
|
||||
IMAQdxOutputImageTypeAuto = 0x7FFFFFFF,
|
||||
IMAQdxOutputImageTypeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxOutputImageType;
|
||||
|
||||
//==============================================================================
|
||||
// Controller Destination Mode Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxDestinationMode_enum {
|
||||
IMAQdxDestinationModeUnicast,
|
||||
IMAQdxDestinationModeBroadcast,
|
||||
IMAQdxDestinationModeMulticast,
|
||||
IMAQdxDestinationModeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxDestinationMode;
|
||||
|
||||
//==============================================================================
|
||||
// Attribute Type Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxAttributeType_enum {
|
||||
IMAQdxAttributeTypeU32,
|
||||
IMAQdxAttributeTypeI64,
|
||||
IMAQdxAttributeTypeF64,
|
||||
IMAQdxAttributeTypeString,
|
||||
IMAQdxAttributeTypeEnum,
|
||||
IMAQdxAttributeTypeBool,
|
||||
IMAQdxAttributeTypeCommand,
|
||||
IMAQdxAttributeTypeBlob,
|
||||
IMAQdxAttributeTypeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxAttributeType;
|
||||
|
||||
//==============================================================================
|
||||
// Value Type Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxValueType_enum {
|
||||
IMAQdxValueTypeU32,
|
||||
IMAQdxValueTypeI64,
|
||||
IMAQdxValueTypeF64,
|
||||
IMAQdxValueTypeString,
|
||||
IMAQdxValueTypeEnumItem,
|
||||
IMAQdxValueTypeBool,
|
||||
IMAQdxValueTypeDisposableString,
|
||||
IMAQdxValueTypeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxValueType;
|
||||
|
||||
//==============================================================================
|
||||
// Interface File Flags Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxInterfaceFileFlags_enum {
|
||||
IMAQdxInterfaceFileFlagsConnected = 0x1,
|
||||
IMAQdxInterfaceFileFlagsDirty = 0x2,
|
||||
IMAQdxInterfaceFileFlagsGuard = 0xFFFFFFFF,
|
||||
} IMAQdxInterfaceFileFlags;
|
||||
|
||||
//==============================================================================
|
||||
// Overwrite Mode Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxOverwriteMode_enum {
|
||||
IMAQdxOverwriteModeGetOldest = 0x0,
|
||||
IMAQdxOverwriteModeFail = 0x2,
|
||||
IMAQdxOverwriteModeGetNewest = 0x3,
|
||||
IMAQdxOverwriteModeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxOverwriteMode;
|
||||
|
||||
//==============================================================================
|
||||
// Incomplete Buffer Mode Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxIncompleteBufferMode_enum {
|
||||
IMAQdxIncompleteBufferModeIgnore,
|
||||
IMAQdxIncompleteBufferModeFail,
|
||||
IMAQdxIncompleteBufferModeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxIncompleteBufferMode;
|
||||
|
||||
//==============================================================================
|
||||
// Lost Packet Mode Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxLostPacketMode_enum {
|
||||
IMAQdxLostPacketModeIgnore,
|
||||
IMAQdxLostPacketModeFail,
|
||||
IMAQdxLostPacketModeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxLostPacketMode;
|
||||
|
||||
//==============================================================================
|
||||
// Attribute Visibility Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxAttributeVisibility_enum {
|
||||
IMAQdxAttributeVisibilitySimple = 0x00001000,
|
||||
IMAQdxAttributeVisibilityIntermediate = 0x00002000,
|
||||
IMAQdxAttributeVisibilityAdvanced = 0x00004000,
|
||||
IMAQdxAttributeVisibilityGuard = 0xFFFFFFFF,
|
||||
} IMAQdxAttributeVisibility;
|
||||
|
||||
//==============================================================================
|
||||
// Stream Channel Mode Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxStreamChannelMode_enum {
|
||||
IMAQdxStreamChannelModeAutomatic,
|
||||
IMAQdxStreamChannelModeManual,
|
||||
IMAQdxStreamChannelModeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxStreamChannelMode;
|
||||
|
||||
//==============================================================================
|
||||
// Pixel Signedness Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxPixelSignedness_enum {
|
||||
IMAQdxPixelSignednessUnsigned,
|
||||
IMAQdxPixelSignednessSigned,
|
||||
IMAQdxPixelSignednessHardware,
|
||||
IMAQdxPixelSignednessGuard = 0xFFFFFFFF,
|
||||
} IMAQdxPixelSignedness;
|
||||
|
||||
//==============================================================================
|
||||
// USB Connection Speed Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxUSBConnectionSpeed_enum {
|
||||
IMAQdxUSBConnectionSpeedLow = 1,
|
||||
IMAQdxUSBConnectionSpeedFull = 2,
|
||||
IMAQdxUSBConnectionSpeedHigh = 4,
|
||||
IMAQdxUSBConnectionSpeedSuper = 8,
|
||||
IMAQdxUSBConnectionSpeedGuard = 0xFFFFFFFF,
|
||||
} IMAQdxUSBConnectionSpeed;
|
||||
|
||||
//==============================================================================
|
||||
// CVI Structures
|
||||
//==============================================================================
|
||||
#pragma pack(push, 4)
|
||||
|
||||
//==============================================================================
|
||||
// Camera Information Structure
|
||||
//==============================================================================
|
||||
typedef struct IMAQdxCameraInformation_struct {
|
||||
uInt32 Type;
|
||||
uInt32 Version;
|
||||
uInt32 Flags;
|
||||
uInt32 SerialNumberHi;
|
||||
uInt32 SerialNumberLo;
|
||||
IMAQdxBusType BusType;
|
||||
char InterfaceName[IMAQDX_MAX_API_STRING_LENGTH];
|
||||
char VendorName[IMAQDX_MAX_API_STRING_LENGTH];
|
||||
char ModelName[IMAQDX_MAX_API_STRING_LENGTH];
|
||||
char CameraFileName[IMAQDX_MAX_API_STRING_LENGTH];
|
||||
char CameraAttributeURL[IMAQDX_MAX_API_STRING_LENGTH];
|
||||
} IMAQdxCameraInformation;
|
||||
|
||||
//==============================================================================
|
||||
// Camera File Structure
|
||||
//==============================================================================
|
||||
typedef struct IMAQdxCameraFile_struct {
|
||||
uInt32 Type;
|
||||
uInt32 Version;
|
||||
char FileName[IMAQDX_MAX_API_STRING_LENGTH];
|
||||
} IMAQdxCameraFile;
|
||||
|
||||
//==============================================================================
|
||||
// Attribute Information Structure
|
||||
//==============================================================================
|
||||
typedef struct IMAQdxAttributeInformation_struct {
|
||||
IMAQdxAttributeType Type;
|
||||
bool32 Readable;
|
||||
bool32 Writable;
|
||||
char Name[IMAQDX_MAX_API_STRING_LENGTH];
|
||||
} IMAQdxAttributeInformation;
|
||||
|
||||
//==============================================================================
|
||||
// Enumeration Item Structure
|
||||
//==============================================================================
|
||||
typedef struct IMAQdxEnumItem_struct {
|
||||
uInt32 Value;
|
||||
uInt32 Reserved;
|
||||
char Name[IMAQDX_MAX_API_STRING_LENGTH];
|
||||
} IMAQdxEnumItem;
|
||||
|
||||
//==============================================================================
|
||||
// Camera Information Structure
|
||||
//==============================================================================
|
||||
typedef IMAQdxEnumItem IMAQdxVideoMode;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
//==============================================================================
|
||||
// Callbacks
|
||||
//==============================================================================
|
||||
typedef uInt32(NI_FUNC* FrameDoneEventCallbackPtr)(IMAQdxSession id,
|
||||
uInt32 bufferNumber,
|
||||
void* callbackData);
|
||||
typedef uInt32(NI_FUNC* PnpEventCallbackPtr)(IMAQdxSession id,
|
||||
IMAQdxPnpEvent pnpEvent,
|
||||
void* callbackData);
|
||||
typedef void(NI_FUNC* AttributeUpdatedEventCallbackPtr)(IMAQdxSession id,
|
||||
const char* name,
|
||||
void* callbackData);
|
||||
|
||||
#endif // niimaqdx_types
|
||||
//==============================================================================
|
||||
// Attributes
|
||||
//==============================================================================
|
||||
#define IMAQdxAttributeBaseAddress \
|
||||
"CameraInformation::BaseAddress" // Read only. Gets the base address of the
|
||||
// camera registers.
|
||||
#define IMAQdxAttributeBusType \
|
||||
"CameraInformation::BusType" // Read only. Gets the bus type of the camera.
|
||||
#define IMAQdxAttributeModelName \
|
||||
"CameraInformation::ModelName" // Read only. Returns the model name.
|
||||
#define IMAQdxAttributeSerialNumberHigh \
|
||||
"CameraInformation::SerialNumberHigh" // Read only. Gets the upper 32-bits of
|
||||
// the camera 64-bit serial number.
|
||||
#define IMAQdxAttributeSerialNumberLow \
|
||||
"CameraInformation::SerialNumberLow" // Read only. Gets the lower 32-bits of
|
||||
// the camera 64-bit serial number.
|
||||
#define IMAQdxAttributeVendorName \
|
||||
"CameraInformation::VendorName" // Read only. Returns the vendor name.
|
||||
#define IMAQdxAttributeHostIPAddress \
|
||||
"CameraInformation::HostIPAddress" // Read only. Returns the host adapter IP
|
||||
// address.
|
||||
#define IMAQdxAttributeIPAddress \
|
||||
"CameraInformation::IPAddress" // Read only. Returns the IP address.
|
||||
#define IMAQdxAttributePrimaryURLString \
|
||||
"CameraInformation::PrimaryURLString" // Read only. Gets the camera's primary
|
||||
// URL string.
|
||||
#define IMAQdxAttributeSecondaryURLString \
|
||||
"CameraInformation::SecondaryURLString" // Read only. Gets the camera's
|
||||
// secondary URL string.
|
||||
#define IMAQdxAttributeAcqInProgress \
|
||||
"StatusInformation::AcqInProgress" // Read only. Gets the current state of
|
||||
// the acquisition. TRUE if acquiring;
|
||||
// otherwise FALSE.
|
||||
#define IMAQdxAttributeLastBufferCount \
|
||||
"StatusInformation::LastBufferCount" // Read only. Gets the number of
|
||||
// transferred buffers.
|
||||
#define IMAQdxAttributeLastBufferNumber \
|
||||
"StatusInformation::LastBufferNumber" // Read only. Gets the last cumulative
|
||||
// buffer number transferred.
|
||||
#define IMAQdxAttributeLostBufferCount \
|
||||
"StatusInformation::LostBufferCount" // Read only. Gets the number of lost
|
||||
// buffers during an acquisition
|
||||
// session.
|
||||
#define IMAQdxAttributeLostPacketCount \
|
||||
"StatusInformation::LostPacketCount" // Read only. Gets the number of lost
|
||||
// packets during an acquisition
|
||||
// session.
|
||||
#define IMAQdxAttributeRequestedResendPackets \
|
||||
"StatusInformation::RequestedResendPacketCount" // Read only. Gets the number
|
||||
// of packets requested to be
|
||||
// resent during an
|
||||
// acquisition session.
|
||||
#define IMAQdxAttributeReceivedResendPackets \
|
||||
"StatusInformation::ReceivedResendPackets" // Read only. Gets the number of
|
||||
// packets that were requested to
|
||||
// be resent during an acquisition
|
||||
// session and were completed.
|
||||
#define IMAQdxAttributeHandledEventCount \
|
||||
"StatusInformation::HandledEventCount" // Read only. Gets the number of
|
||||
// handled events during an
|
||||
// acquisition session.
|
||||
#define IMAQdxAttributeLostEventCount \
|
||||
"StatusInformation::LostEventCount" // Read only. Gets the number of lost
|
||||
// events during an acquisition session.
|
||||
#define IMAQdxAttributeBayerGainB \
|
||||
"AcquisitionAttributes::Bayer::GainB" // Sets/gets the white balance gain for
|
||||
// the blue component of the Bayer
|
||||
// conversion.
|
||||
#define IMAQdxAttributeBayerGainG \
|
||||
"AcquisitionAttributes::Bayer::GainG" // Sets/gets the white balance gain for
|
||||
// the green component of the Bayer
|
||||
// conversion.
|
||||
#define IMAQdxAttributeBayerGainR \
|
||||
"AcquisitionAttributes::Bayer::GainR" // Sets/gets the white balance gain for
|
||||
// the red component of the Bayer
|
||||
// conversion.
|
||||
#define IMAQdxAttributeBayerPattern \
|
||||
"AcquisitionAttributes::Bayer::Pattern" // Sets/gets the Bayer pattern to
|
||||
// use.
|
||||
#define IMAQdxAttributeStreamChannelMode \
|
||||
"AcquisitionAttributes::Controller::StreamChannelMode" // Gets/sets the mode
|
||||
// for allocating a
|
||||
// FireWire stream
|
||||
// channel.
|
||||
#define IMAQdxAttributeDesiredStreamChannel \
|
||||
"AcquisitionAttributes::Controller::DesiredStreamChannel" // Gets/sets the
|
||||
// stream channel
|
||||
// to manually
|
||||
// allocate.
|
||||
#define IMAQdxAttributeFrameInterval \
|
||||
"AcquisitionAttributes::FrameInterval" // Read only. Gets the duration in
|
||||
// milliseconds between successive
|
||||
// frames.
|
||||
#define IMAQdxAttributeIgnoreFirstFrame \
|
||||
"AcquisitionAttributes::IgnoreFirstFrame" // Gets/sets the video delay of one
|
||||
// frame between starting the
|
||||
// camera and receiving the video
|
||||
// feed.
|
||||
#define IMAQdxAttributeOffsetX \
|
||||
"OffsetX" // Gets/sets the left offset of the image.
|
||||
#define IMAQdxAttributeOffsetY \
|
||||
"OffsetY" // Gets/sets the top offset of the image.
|
||||
#define IMAQdxAttributeWidth "Width" // Gets/sets the width of the image.
|
||||
#define IMAQdxAttributeHeight "Height" // Gets/sets the height of the image.
|
||||
#define IMAQdxAttributePixelFormat \
|
||||
"PixelFormat" // Gets/sets the pixel format of the source sensor.
|
||||
#define IMAQdxAttributePacketSize \
|
||||
"PacketSize" // Gets/sets the packet size in bytes.
|
||||
#define IMAQdxAttributePayloadSize \
|
||||
"PayloadSize" // Gets/sets the frame size in bytes.
|
||||
#define IMAQdxAttributeSpeed \
|
||||
"AcquisitionAttributes::Speed" // Gets/sets the transfer speed in Mbps for a
|
||||
// FireWire packet.
|
||||
#define IMAQdxAttributeShiftPixelBits \
|
||||
"AcquisitionAttributes::ShiftPixelBits" // Gets/sets the alignment of 16-bit
|
||||
// cameras. Downshift the pixel bits
|
||||
// if the camera returns most
|
||||
// significant bit-aligned data.
|
||||
#define IMAQdxAttributeSwapPixelBytes \
|
||||
"AcquisitionAttributes::SwapPixelBytes" // Gets/sets the endianness of 16-bit
|
||||
// cameras. Swap the pixel bytes if
|
||||
// the camera returns little endian
|
||||
// data.
|
||||
#define IMAQdxAttributeOverwriteMode \
|
||||
"AcquisitionAttributes::OverwriteMode" // Gets/sets the overwrite mode, used
|
||||
// to determine acquisition when an
|
||||
// image transfer cannot be completed
|
||||
// due to an overwritten internal
|
||||
// buffer.
|
||||
#define IMAQdxAttributeTimeout \
|
||||
"AcquisitionAttributes::Timeout" // Gets/sets the timeout value in
|
||||
// milliseconds, used to abort an
|
||||
// acquisition when the image transfer
|
||||
// cannot be completed within the delay.
|
||||
#define IMAQdxAttributeVideoMode \
|
||||
"AcquisitionAttributes::VideoMode" // Gets/sets the video mode for a camera.
|
||||
#define IMAQdxAttributeBitsPerPixel \
|
||||
"AcquisitionAttributes::BitsPerPixel" // Gets/sets the actual bits per pixel.
|
||||
// For 16-bit components, this
|
||||
// represents the actual bit depth
|
||||
// (10-, 12-, 14-, or 16-bit).
|
||||
#define IMAQdxAttributePixelSignedness \
|
||||
"AcquisitionAttributes::PixelSignedness" // Gets/sets the signedness of the
|
||||
// pixel. For 16-bit components,
|
||||
// this represents the actual pixel
|
||||
// signedness (Signed, or Unsigned).
|
||||
#define IMAQdxAttributeReserveDualPackets \
|
||||
"AcquisitionAttributes::ReserveDualPackets" // Gets/sets if dual packets will
|
||||
// be reserved for a very large
|
||||
// FireWire packet.
|
||||
#define IMAQdxAttributeReceiveTimestampMode \
|
||||
"AcquisitionAttributes::ReceiveTimestampMode" // Gets/sets the mode for
|
||||
// timestamping images received
|
||||
// by the driver.
|
||||
#define IMAQdxAttributeActualPeakBandwidth \
|
||||
"AcquisitionAttributes::AdvancedEthernet::BandwidthControl::" \
|
||||
"ActualPeakBandwidth" // Read only. Returns the actual maximum peak bandwidth
|
||||
// the camera will be configured to use.
|
||||
#define IMAQdxAttributeDesiredPeakBandwidth \
|
||||
"AcquisitionAttributes::AdvancedEthernet::BandwidthControl::" \
|
||||
"DesiredPeakBandwidth" // Gets/sets the desired maximum peak bandwidth the
|
||||
// camera should use.
|
||||
#define IMAQdxAttributeDestinationMode \
|
||||
"AcquisitionAttributes::AdvancedEthernet::Controller::DestinationMode" // Gets/Sets
|
||||
// where
|
||||
// the
|
||||
// camera
|
||||
// is
|
||||
// instructed
|
||||
// to
|
||||
// send
|
||||
// the
|
||||
// image
|
||||
// stream.
|
||||
#define IMAQdxAttributeDestinationMulticastAddress \
|
||||
"AcquisitionAttributes::AdvancedEthernet::Controller::" \
|
||||
"DestinationMulticastAddress" // Gets/Sets the multicast address the camera
|
||||
// should send data in multicast mode.
|
||||
#define IMAQdxAttributeEventsEnabled \
|
||||
"AcquisitionAttributes::AdvancedEthernet::EventParameters::EventsEnabled" // Gets/Sets if events will be handled.
|
||||
#define IMAQdxAttributeMaxOutstandingEvents \
|
||||
"AcquisitionAttributes::AdvancedEthernet::EventParameters::" \
|
||||
"MaxOutstandingEvents" // Gets/Sets the maximum number of outstanding events
|
||||
// to queue.
|
||||
#define IMAQdxAttributeTestPacketEnabled \
|
||||
"AcquisitionAttributes::AdvancedEthernet::TestPacketParameters::" \
|
||||
"TestPacketEnabled" // Gets/Sets whether the driver will validate the image
|
||||
// streaming settings using test packets prior to an
|
||||
// acquisition
|
||||
#define IMAQdxAttributeTestPacketTimeout \
|
||||
"AcquisitionAttributes::AdvancedEthernet::TestPacketParameters::" \
|
||||
"TestPacketTimeout" // Gets/Sets the timeout for validating test packet
|
||||
// reception (if enabled)
|
||||
#define IMAQdxAttributeMaxTestPacketRetries \
|
||||
"AcquisitionAttributes::AdvancedEthernet::TestPacketParameters::" \
|
||||
"MaxTestPacketRetries" // Gets/Sets the number of retries for validating test
|
||||
// packet reception (if enabled)
|
||||
#define IMAQdxAttributeChunkDataDecodingEnabled \
|
||||
"AcquisitionAttributes::ChunkDataDecoding::ChunkDataDecodingEnabled" // Gets/Sets
|
||||
// whether
|
||||
// the
|
||||
// driver
|
||||
// will
|
||||
// decode
|
||||
// any
|
||||
// chunk
|
||||
// data
|
||||
// in
|
||||
// the
|
||||
// image
|
||||
// stream
|
||||
#define IMAQdxAttributeChunkDataDecodingMaxElementSize \
|
||||
"AcquisitionAttributes::ChunkDataDecoding::MaximumChunkCopySize" // Gets/Sets
|
||||
// the
|
||||
// maximum
|
||||
// size of
|
||||
// any
|
||||
// single
|
||||
// chunk
|
||||
// data
|
||||
// element
|
||||
// that will
|
||||
// be made
|
||||
// available
|
||||
#define IMAQdxAttributeLostPacketMode \
|
||||
"AcquisitionAttributes::AdvancedEthernet::LostPacketMode" // Gets/sets the
|
||||
// behavior when
|
||||
// the user
|
||||
// extracts a
|
||||
// buffer that has
|
||||
// missing packets.
|
||||
#define IMAQdxAttributeMemoryWindowSize \
|
||||
"AcquisitionAttributes::AdvancedEthernet::ResendParameters::" \
|
||||
"MemoryWindowSize" // Gets/sets the size of the memory window of the camera
|
||||
// in kilobytes. Should match the camera's internal buffer
|
||||
// size.
|
||||
#define IMAQdxAttributeResendsEnabled \
|
||||
"AcquisitionAttributes::AdvancedEthernet::ResendParameters::ResendsEnabled" // Gets/sets if resends will be issued for missing packets.
|
||||
#define IMAQdxAttributeResendThresholdPercentage \
|
||||
"AcquisitionAttributes::AdvancedEthernet::ResendParameters::" \
|
||||
"ResendThresholdPercentage" // Gets/sets the threshold of the packet
|
||||
// processing window that will trigger packets to
|
||||
// be resent.
|
||||
#define IMAQdxAttributeResendBatchingPercentage \
|
||||
"AcquisitionAttributes::AdvancedEthernet::ResendParameters::" \
|
||||
"ResendBatchingPercentage" // Gets/sets the percent of the packet resend
|
||||
// threshold that will be issued as one group past
|
||||
// the initial threshold sent in a single request.
|
||||
#define IMAQdxAttributeMaxResendsPerPacket \
|
||||
"AcquisitionAttributes::AdvancedEthernet::ResendParameters::" \
|
||||
"MaxResendsPerPacket" // Gets/sets the maximum number of resend requests that
|
||||
// will be issued for a missing packet.
|
||||
#define IMAQdxAttributeResendResponseTimeout \
|
||||
"AcquisitionAttributes::AdvancedEthernet::ResendParameters::" \
|
||||
"ResendResponseTimeout" // Gets/sets the time to wait for a resend request to
|
||||
// be satisfied before sending another.
|
||||
#define IMAQdxAttributeNewPacketTimeout \
|
||||
"AcquisitionAttributes::AdvancedEthernet::ResendParameters::" \
|
||||
"NewPacketTimeout" // Gets/sets the time to wait for new packets to arrive in
|
||||
// a partially completed image before assuming the rest of
|
||||
// the image was lost.
|
||||
#define IMAQdxAttributeMissingPacketTimeout \
|
||||
"AcquisitionAttributes::AdvancedEthernet::ResendParameters::" \
|
||||
"MissingPacketTimeout" // Gets/sets the time to wait for a missing packet
|
||||
// before issuing a resend.
|
||||
#define IMAQdxAttributeResendTimerResolution \
|
||||
"AcquisitionAttributes::AdvancedEthernet::ResendParameters::" \
|
||||
"ResendTimerResolution" // Gets/sets the resolution of the packet processing
|
||||
// system that is used for all packet-related
|
||||
// timeouts.
|
||||
|
||||
//==============================================================================
|
||||
// Functions
|
||||
//==============================================================================
|
||||
IMAQdxError NI_FUNC IMAQdxSnap(IMAQdxSession id, Image* image);
|
||||
IMAQdxError NI_FUNC IMAQdxConfigureGrab(IMAQdxSession id);
|
||||
IMAQdxError NI_FUNC IMAQdxGrab(IMAQdxSession id, Image* image,
|
||||
bool32 waitForNextBuffer,
|
||||
uInt32* actualBufferNumber);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxSequence(IMAQdxSession id, Image* images[], uInt32 count);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxDiscoverEthernetCameras(const char* address, uInt32 timeout);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxEnumerateCameras(IMAQdxCameraInformation cameraInformationArray[],
|
||||
uInt32* count, bool32 connectedOnly);
|
||||
IMAQdxError NI_FUNC IMAQdxResetCamera(const char* name, bool32 resetAll);
|
||||
IMAQdxError NI_FUNC IMAQdxOpenCamera(const char* name,
|
||||
IMAQdxCameraControlMode mode,
|
||||
IMAQdxSession* id);
|
||||
IMAQdxError NI_FUNC IMAQdxCloseCamera(IMAQdxSession id);
|
||||
IMAQdxError NI_FUNC IMAQdxConfigureAcquisition(IMAQdxSession id,
|
||||
bool32 continuous,
|
||||
uInt32 bufferCount);
|
||||
IMAQdxError NI_FUNC IMAQdxStartAcquisition(IMAQdxSession id);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxGetImage(IMAQdxSession id, Image* image, IMAQdxBufferNumberMode mode,
|
||||
uInt32 desiredBufferNumber, uInt32* actualBufferNumber);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxGetImageData(IMAQdxSession id, void* buffer, uInt32 bufferSize,
|
||||
IMAQdxBufferNumberMode mode, uInt32 desiredBufferNumber,
|
||||
uInt32* actualBufferNumber);
|
||||
IMAQdxError NI_FUNC IMAQdxStopAcquisition(IMAQdxSession id);
|
||||
IMAQdxError NI_FUNC IMAQdxUnconfigureAcquisition(IMAQdxSession id);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxEnumerateVideoModes(IMAQdxSession id, IMAQdxVideoMode videoModeArray[],
|
||||
uInt32* count, uInt32* currentMode);
|
||||
IMAQdxError NI_FUNC IMAQdxEnumerateAttributes(
|
||||
IMAQdxSession id, IMAQdxAttributeInformation attributeInformationArray[],
|
||||
uInt32* count, const char* root);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttribute(IMAQdxSession id, const char* name,
|
||||
IMAQdxValueType type, void* value);
|
||||
IMAQdxError NI_FUNCC IMAQdxSetAttribute(IMAQdxSession id, const char* name,
|
||||
IMAQdxValueType type, ...);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxGetAttributeMinimum(IMAQdxSession id, const char* name,
|
||||
IMAQdxValueType type, void* value);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxGetAttributeMaximum(IMAQdxSession id, const char* name,
|
||||
IMAQdxValueType type, void* value);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxGetAttributeIncrement(IMAQdxSession id, const char* name,
|
||||
IMAQdxValueType type, void* value);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeType(IMAQdxSession id, const char* name,
|
||||
IMAQdxAttributeType* type);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxIsAttributeReadable(IMAQdxSession id, const char* name, bool32* readable);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxIsAttributeWritable(IMAQdxSession id, const char* name, bool32* writable);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxEnumerateAttributeValues(IMAQdxSession id, const char* name,
|
||||
IMAQdxEnumItem list[], uInt32* size);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeTooltip(IMAQdxSession id,
|
||||
const char* name, char* tooltip,
|
||||
uInt32 length);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeUnits(IMAQdxSession id, const char* name,
|
||||
char* units, uInt32 length);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxRegisterFrameDoneEvent(IMAQdxSession id, uInt32 bufferInterval,
|
||||
FrameDoneEventCallbackPtr callbackFunction,
|
||||
void* callbackData);
|
||||
IMAQdxError NI_FUNC IMAQdxRegisterPnpEvent(IMAQdxSession id,
|
||||
IMAQdxPnpEvent event,
|
||||
PnpEventCallbackPtr callbackFunction,
|
||||
void* callbackData);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxWriteRegister(IMAQdxSession id, uInt32 offset, uInt32 value);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxReadRegister(IMAQdxSession id, uInt32 offset, uInt32* value);
|
||||
IMAQdxError NI_FUNC IMAQdxWriteMemory(IMAQdxSession id, uInt32 offset,
|
||||
const char* values, uInt32 count);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxReadMemory(IMAQdxSession id, uInt32 offset, char* values, uInt32 count);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxGetErrorString(IMAQdxError error, char* message, uInt32 messageLength);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxWriteAttributes(IMAQdxSession id, const char* filename);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxReadAttributes(IMAQdxSession id, const char* filename);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxResetEthernetCameraAddress(const char* name, const char* address,
|
||||
const char* subnet, const char* gateway,
|
||||
uInt32 timeout);
|
||||
IMAQdxError NI_FUNC IMAQdxEnumerateAttributes2(
|
||||
IMAQdxSession id, IMAQdxAttributeInformation attributeInformationArray[],
|
||||
uInt32* count, const char* root, IMAQdxAttributeVisibility visibility);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxGetAttributeVisibility(IMAQdxSession id, const char* name,
|
||||
IMAQdxAttributeVisibility* visibility);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxGetAttributeDescription(IMAQdxSession id, const char* name,
|
||||
char* description, uInt32 length);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxGetAttributeDisplayName(IMAQdxSession id, const char* name,
|
||||
char* displayName, uInt32 length);
|
||||
IMAQdxError NI_FUNC IMAQdxDispose(void* buffer);
|
||||
IMAQdxError NI_FUNC IMAQdxRegisterAttributeUpdatedEvent(
|
||||
IMAQdxSession id, const char* name,
|
||||
AttributeUpdatedEventCallbackPtr callbackFunction, void* callbackData);
|
||||
IMAQdxError NI_FUNC IMAQdxEnumerateAttributes3(
|
||||
IMAQdxSession id, IMAQdxAttributeInformation attributeInformationArray[],
|
||||
uInt32* count, const char* root, IMAQdxAttributeVisibility visibility);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ___niimaqdx_h___
|
||||
@@ -1,126 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ErrorBase.h"
|
||||
#include "HAL/cpp/priority_mutex.h"
|
||||
#include "NIIMAQdx.h"
|
||||
#include "nivision.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
typedef enum whiteBalance_enum {
|
||||
kFixedIndoor = 3000,
|
||||
kFixedOutdoor1 = 4000,
|
||||
kFixedOutdoor2 = 5000,
|
||||
kFixedFluorescent1 = 5100,
|
||||
kFixedFlourescent2 = 5200
|
||||
} whiteBalance;
|
||||
|
||||
class USBCamera : public ErrorBase {
|
||||
private:
|
||||
static constexpr char const* ATTR_WB_MODE =
|
||||
"CameraAttributes::WhiteBalance::Mode";
|
||||
static constexpr char const* ATTR_WB_VALUE =
|
||||
"CameraAttributes::WhiteBalance::Value";
|
||||
static constexpr char const* ATTR_EX_MODE =
|
||||
"CameraAttributes::Exposure::Mode";
|
||||
static constexpr char const* ATTR_EX_VALUE =
|
||||
"CameraAttributes::Exposure::Value";
|
||||
static constexpr char const* ATTR_BR_MODE =
|
||||
"CameraAttributes::Brightness::Mode";
|
||||
static constexpr char const* ATTR_BR_VALUE =
|
||||
"CameraAttributes::Brightness::Value";
|
||||
|
||||
// Constants for the manual and auto types
|
||||
static constexpr char const* AUTO = "Auto";
|
||||
static constexpr char const* MANUAL = "Manual";
|
||||
|
||||
protected:
|
||||
IMAQdxSession m_id = 0;
|
||||
std::string m_name;
|
||||
bool m_useJpeg;
|
||||
bool m_active = false;
|
||||
bool m_open = false;
|
||||
|
||||
priority_recursive_mutex m_mutex;
|
||||
|
||||
int m_width = 320;
|
||||
int m_height = 240;
|
||||
double m_fps = 30;
|
||||
std::string m_whiteBalance = AUTO;
|
||||
int m_whiteBalanceValue = 0;
|
||||
bool m_whiteBalanceValuePresent = false;
|
||||
std::string m_exposure = MANUAL;
|
||||
int m_exposureValue = 50;
|
||||
bool m_exposureValuePresent = false;
|
||||
int m_brightness = 80;
|
||||
bool m_needSettingsUpdate = true;
|
||||
|
||||
int GetJpegSize(void* buffer, int buffSize);
|
||||
|
||||
public:
|
||||
static constexpr char const* kDefaultCameraName = "cam0";
|
||||
|
||||
USBCamera(std::string name, bool useJpeg);
|
||||
|
||||
void OpenCamera();
|
||||
void CloseCamera();
|
||||
void StartCapture();
|
||||
void StopCapture();
|
||||
void SetFPS(double fps);
|
||||
void SetSize(int width, int height);
|
||||
|
||||
void UpdateSettings();
|
||||
/**
|
||||
* Set the brightness, as a percentage (0-100).
|
||||
*/
|
||||
void SetBrightness(int brightness);
|
||||
|
||||
/**
|
||||
* Get the brightness, as a percentage (0-100).
|
||||
*/
|
||||
int GetBrightness();
|
||||
|
||||
/**
|
||||
* Set the white balance to auto
|
||||
*/
|
||||
void SetWhiteBalanceAuto();
|
||||
|
||||
/**
|
||||
* Set the white balance to hold current
|
||||
*/
|
||||
void SetWhiteBalanceHoldCurrent();
|
||||
|
||||
/**
|
||||
* Set the white balance to manual, with specified color temperature
|
||||
*/
|
||||
void SetWhiteBalanceManual(int wbValue);
|
||||
|
||||
/**
|
||||
* Set the exposure to auto exposure
|
||||
*/
|
||||
void SetExposureAuto();
|
||||
|
||||
/**
|
||||
* Set the exposure to hold current
|
||||
*/
|
||||
void SetExposureHoldCurrent();
|
||||
|
||||
/**
|
||||
* Set the exposure to manual, with a given percentage (0-100)
|
||||
*/
|
||||
void SetExposureManual(int expValue);
|
||||
|
||||
void GetImage(Image* image);
|
||||
int GetImageData(void* buffer, int bufferSize);
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
@@ -1,127 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "ErrorBase.h"
|
||||
#include "HAL/cpp/priority_mutex.h"
|
||||
#include "Vision/ColorImage.h"
|
||||
#include "Vision/HSLImage.h"
|
||||
#include "nivision.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
/**
|
||||
* Axis M1011 network camera
|
||||
*/
|
||||
class AxisCamera : public ErrorBase {
|
||||
public:
|
||||
enum WhiteBalance {
|
||||
kWhiteBalance_Automatic,
|
||||
kWhiteBalance_Hold,
|
||||
kWhiteBalance_FixedOutdoor1,
|
||||
kWhiteBalance_FixedOutdoor2,
|
||||
kWhiteBalance_FixedIndoor,
|
||||
kWhiteBalance_FixedFluorescent1,
|
||||
kWhiteBalance_FixedFluorescent2
|
||||
};
|
||||
|
||||
enum ExposureControl {
|
||||
kExposureControl_Automatic,
|
||||
kExposureControl_Hold,
|
||||
kExposureControl_FlickerFree50Hz,
|
||||
kExposureControl_FlickerFree60Hz
|
||||
};
|
||||
|
||||
enum Resolution {
|
||||
kResolution_640x480,
|
||||
kResolution_480x360,
|
||||
kResolution_320x240,
|
||||
kResolution_240x180,
|
||||
kResolution_176x144,
|
||||
kResolution_160x120,
|
||||
};
|
||||
|
||||
enum Rotation { kRotation_0, kRotation_180 };
|
||||
|
||||
explicit AxisCamera(std::string const& cameraHost);
|
||||
virtual ~AxisCamera();
|
||||
|
||||
AxisCamera(const AxisCamera&) = delete;
|
||||
AxisCamera& operator=(const AxisCamera&) = delete;
|
||||
|
||||
bool IsFreshImage() const;
|
||||
|
||||
int GetImage(Image* image);
|
||||
int GetImage(ColorImage* image);
|
||||
HSLImage* GetImage();
|
||||
int CopyJPEG(char** destImage, int& destImageSize, int& destImageBufferSize);
|
||||
|
||||
void WriteBrightness(int brightness);
|
||||
int GetBrightness();
|
||||
|
||||
void WriteWhiteBalance(WhiteBalance whiteBalance);
|
||||
WhiteBalance GetWhiteBalance();
|
||||
|
||||
void WriteColorLevel(int colorLevel);
|
||||
int GetColorLevel();
|
||||
|
||||
void WriteExposureControl(ExposureControl exposureControl);
|
||||
ExposureControl GetExposureControl();
|
||||
|
||||
void WriteExposurePriority(int exposurePriority);
|
||||
int GetExposurePriority();
|
||||
|
||||
void WriteMaxFPS(int maxFPS);
|
||||
int GetMaxFPS();
|
||||
|
||||
void WriteResolution(Resolution resolution);
|
||||
Resolution GetResolution();
|
||||
|
||||
void WriteCompression(int compression);
|
||||
int GetCompression();
|
||||
|
||||
void WriteRotation(Rotation rotation);
|
||||
Rotation GetRotation();
|
||||
|
||||
private:
|
||||
std::thread m_captureThread;
|
||||
std::string m_cameraHost;
|
||||
int m_cameraSocket = -1;
|
||||
priority_mutex m_captureMutex;
|
||||
|
||||
priority_mutex m_imageDataMutex;
|
||||
std::vector<uint8_t> m_imageData;
|
||||
bool m_freshImage = false;
|
||||
|
||||
int m_brightness = 50;
|
||||
WhiteBalance m_whiteBalance = kWhiteBalance_Automatic;
|
||||
int m_colorLevel = 50;
|
||||
ExposureControl m_exposureControl = kExposureControl_Automatic;
|
||||
int m_exposurePriority = 50;
|
||||
int m_maxFPS = 0;
|
||||
Resolution m_resolution = kResolution_640x480;
|
||||
int m_compression = 50;
|
||||
Rotation m_rotation = kRotation_0;
|
||||
bool m_parametersDirty = true;
|
||||
bool m_streamDirty = true;
|
||||
priority_mutex m_parametersMutex;
|
||||
|
||||
bool m_done = false;
|
||||
|
||||
void Capture();
|
||||
void ReadImagesFromCamera();
|
||||
bool WriteParameters();
|
||||
|
||||
int CreateCameraSocket(std::string const& requestString, bool setError);
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
@@ -1,75 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
/* Constants */
|
||||
#define LOG_DEBUG __FILE__, __FUNCTION__, __LINE__, DEBUG_TYPE
|
||||
#define LOG_INFO __FILE__, __FUNCTION__, __LINE__, INFO_TYPE
|
||||
#define LOG_ERROR __FILE__, __FUNCTION__, __LINE__, ERROR_TYPE
|
||||
#define LOG_CRITICAL __FILE__, __FUNCTION__, __LINE__, CRITICAL_TYPE
|
||||
#define LOG_FATAL __FILE__, __FUNCTION__, __LINE__, FATAL_TYPE
|
||||
#define LOG_DEBUG __FILE__, __FUNCTION__, __LINE__, DEBUG_TYPE
|
||||
|
||||
namespace frc {
|
||||
|
||||
/* Enumerated Types */
|
||||
|
||||
/** debug levels */
|
||||
enum dprint_type {
|
||||
DEBUG_TYPE,
|
||||
INFO_TYPE,
|
||||
ERROR_TYPE,
|
||||
CRITICAL_TYPE,
|
||||
FATAL_TYPE
|
||||
};
|
||||
|
||||
/** debug output setting */
|
||||
typedef enum DebugOutputType_enum {
|
||||
DEBUG_OFF,
|
||||
DEBUG_MOSTLY_OFF,
|
||||
DEBUG_SCREEN_ONLY,
|
||||
DEBUG_FILE_ONLY,
|
||||
DEBUG_SCREEN_AND_FILE
|
||||
} DebugOutputType;
|
||||
|
||||
/* Enumerated Types */
|
||||
|
||||
/* Utility functions */
|
||||
|
||||
/* debug */
|
||||
void SetDebugFlag(DebugOutputType flag);
|
||||
void dprintf(const char* tempString, ...); /* Variable argument list */
|
||||
|
||||
/* set FRC ranges for drive */
|
||||
double RangeToNormalized(double pixel, int range);
|
||||
/* change normalized value to any range - used for servo */
|
||||
float NormalizeToRange(float normalizedValue, float minRange, float maxRange);
|
||||
float NormalizeToRange(float normalizedValue);
|
||||
|
||||
/* system utilities */
|
||||
void ShowActivity(char* fmt, ...);
|
||||
double ElapsedTime(double startTime);
|
||||
|
||||
/* servo panning utilities */
|
||||
class Servo;
|
||||
double SinPosition(double* period, double sinStart);
|
||||
void panInit();
|
||||
void panInit(double period);
|
||||
void panForTarget(Servo* panServo);
|
||||
void panForTarget(Servo* panServo, double sinStart);
|
||||
|
||||
/* config file read utilities */
|
||||
int processFile(char* inputFile, char* outputString, int lineNumber);
|
||||
int emptyString(char* string);
|
||||
void stripString(char* string);
|
||||
|
||||
} // namespace frc
|
||||
@@ -1,48 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "MonoImage.h"
|
||||
|
||||
/**
|
||||
* Included for ParticleAnalysisReport definition
|
||||
* TODO: Eliminate this dependency!
|
||||
*/
|
||||
#include "Vision/VisionAPI.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
class BinaryImage : public MonoImage {
|
||||
public:
|
||||
virtual ~BinaryImage() = default;
|
||||
int GetNumberParticles();
|
||||
ParticleAnalysisReport GetParticleAnalysisReport(int particleNumber);
|
||||
void GetParticleAnalysisReport(int particleNumber,
|
||||
ParticleAnalysisReport* par);
|
||||
std::vector<ParticleAnalysisReport>* GetOrderedParticleAnalysisReports();
|
||||
BinaryImage* RemoveSmallObjects(bool connectivity8, int erosions);
|
||||
BinaryImage* RemoveLargeObjects(bool connectivity8, int erosions);
|
||||
BinaryImage* ConvexHull(bool connectivity8);
|
||||
BinaryImage* ParticleFilter(ParticleFilterCriteria2* criteria,
|
||||
int criteriaCount);
|
||||
virtual void Write(const char* fileName);
|
||||
|
||||
private:
|
||||
bool ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure,
|
||||
int* result);
|
||||
bool ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure,
|
||||
double* result);
|
||||
static double NormalizeFromRange(double position, int range);
|
||||
static bool CompareParticleSizes(ParticleAnalysisReport particle1,
|
||||
ParticleAnalysisReport particle2);
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
@@ -1,75 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BinaryImage.h"
|
||||
#include "ImageBase.h"
|
||||
#include "Threshold.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
class ColorImage : public ImageBase {
|
||||
public:
|
||||
explicit ColorImage(ImageType type);
|
||||
virtual ~ColorImage() = default;
|
||||
BinaryImage* ThresholdRGB(int redLow, int redHigh, int greenLow,
|
||||
int greenHigh, int blueLow, int blueHigh);
|
||||
BinaryImage* ThresholdHSL(int hueLow, int hueHigh, int saturationLow,
|
||||
int saturationHigh, int luminenceLow,
|
||||
int luminenceHigh);
|
||||
BinaryImage* ThresholdHSV(int hueLow, int hueHigh, int saturationLow,
|
||||
int saturationHigh, int valueHigh, int valueLow);
|
||||
BinaryImage* ThresholdHSI(int hueLow, int hueHigh, int saturationLow,
|
||||
int saturationHigh, int intensityLow,
|
||||
int intensityHigh);
|
||||
BinaryImage* ThresholdRGB(Threshold& threshold);
|
||||
BinaryImage* ThresholdHSL(Threshold& threshold);
|
||||
BinaryImage* ThresholdHSV(Threshold& threshold);
|
||||
BinaryImage* ThresholdHSI(Threshold& threshold);
|
||||
MonoImage* GetRedPlane();
|
||||
MonoImage* GetGreenPlane();
|
||||
MonoImage* GetBluePlane();
|
||||
MonoImage* GetHSLHuePlane();
|
||||
MonoImage* GetHSVHuePlane();
|
||||
MonoImage* GetHSIHuePlane();
|
||||
MonoImage* GetHSLSaturationPlane();
|
||||
MonoImage* GetHSVSaturationPlane();
|
||||
MonoImage* GetHSISaturationPlane();
|
||||
MonoImage* GetLuminancePlane();
|
||||
MonoImage* GetValuePlane();
|
||||
MonoImage* GetIntensityPlane();
|
||||
void ReplaceRedPlane(MonoImage* plane);
|
||||
void ReplaceGreenPlane(MonoImage* plane);
|
||||
void ReplaceBluePlane(MonoImage* plane);
|
||||
void ReplaceHSLHuePlane(MonoImage* plane);
|
||||
void ReplaceHSVHuePlane(MonoImage* plane);
|
||||
void ReplaceHSIHuePlane(MonoImage* plane);
|
||||
void ReplaceHSLSaturationPlane(MonoImage* plane);
|
||||
void ReplaceHSVSaturationPlane(MonoImage* plane);
|
||||
void ReplaceHSISaturationPlane(MonoImage* plane);
|
||||
void ReplaceLuminancePlane(MonoImage* plane);
|
||||
void ReplaceValuePlane(MonoImage* plane);
|
||||
void ReplaceIntensityPlane(MonoImage* plane);
|
||||
void ColorEqualize();
|
||||
void LuminanceEqualize();
|
||||
|
||||
private:
|
||||
BinaryImage* ComputeThreshold(ColorMode colorMode, int low1, int high1,
|
||||
int low2, int high2, int low3, int high3);
|
||||
void Equalize(bool allPlanes);
|
||||
MonoImage* ExtractColorPlane(ColorMode mode, int planeNumber);
|
||||
MonoImage* ExtractFirstColorPlane(ColorMode mode);
|
||||
MonoImage* ExtractSecondColorPlane(ColorMode mode);
|
||||
MonoImage* ExtractThirdColorPlane(ColorMode mode);
|
||||
void ReplacePlane(ColorMode mode, MonoImage* plane, int planeNumber);
|
||||
void ReplaceFirstColorPlane(ColorMode mode, MonoImage* plane);
|
||||
void ReplaceSecondColorPlane(ColorMode mode, MonoImage* plane);
|
||||
void ReplaceThirdColorPlane(ColorMode mode, MonoImage* plane);
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
@@ -1,36 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Error Codes */
|
||||
#define ERR_VISION_GENERAL_ERROR 166000 //
|
||||
#define ERR_COLOR_NOT_FOUND 166100 // TrackAPI.cpp
|
||||
#define ERR_PARTICLE_TOO_SMALL 166101 // TrackAPI.cpp
|
||||
|
||||
#define ERR_CAMERA_FAILURE 166200 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_SOCKET_CREATE_FAILED 166201 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_CONNECT_FAILED 166202 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_STALE_IMAGE 166203 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_NOT_INITIALIZED 166204 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_NO_BUFFER_AVAILABLE 166205 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_HEADER_ERROR 166206 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_BLOCKING_TIMEOUT 166207 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_AUTHORIZATION_FAILED 166208 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_TASK_SPAWN_FAILED 166209 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_TASK_INPUT_OUT_OF_RANGE 166210 // AxisCamera.cpp
|
||||
#define ERR_CAMERA_COMMAND_FAILURE 166211 // AxisCamera.cpp
|
||||
|
||||
namespace frc {
|
||||
|
||||
/* error handling functions */
|
||||
int GetLastVisionError();
|
||||
const char* GetVisionErrorText(int errorCode);
|
||||
|
||||
} // namespace frc
|
||||
@@ -1,24 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ColorImage.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
/**
|
||||
* A color image represented in HSL color space at 3 bytes per pixel.
|
||||
*/
|
||||
class HSLImage : public ColorImage {
|
||||
public:
|
||||
HSLImage();
|
||||
explicit HSLImage(const char* fileName);
|
||||
virtual ~HSLImage() = default;
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
@@ -1,30 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ErrorBase.h"
|
||||
#include "nivision.h"
|
||||
|
||||
#define DEFAULT_BORDER_SIZE 3
|
||||
|
||||
namespace frc {
|
||||
|
||||
class ImageBase : public ErrorBase {
|
||||
public:
|
||||
explicit ImageBase(ImageType type);
|
||||
virtual ~ImageBase();
|
||||
virtual void Write(const char* fileName);
|
||||
int GetHeight();
|
||||
int GetWidth();
|
||||
Image* GetImaqImage();
|
||||
|
||||
protected:
|
||||
Image* m_imaqImage;
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
@@ -1,28 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "ImageBase.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
class MonoImage : public ImageBase {
|
||||
public:
|
||||
MonoImage();
|
||||
virtual ~MonoImage() = default;
|
||||
|
||||
std::vector<EllipseMatch>* DetectEllipses(
|
||||
EllipseDescriptor* ellipseDescriptor, CurveOptions* curveOptions,
|
||||
ShapeDetectionOptions* shapeDetectionOptions, ROI* roi);
|
||||
std::vector<EllipseMatch>* DetectEllipses(
|
||||
EllipseDescriptor* ellipseDescriptor);
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
@@ -1,24 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ColorImage.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
/**
|
||||
* A color image represented in RGB color space at 3 bytes per pixel.
|
||||
*/
|
||||
class RGBImage : public ColorImage {
|
||||
public:
|
||||
RGBImage();
|
||||
explicit RGBImage(const char* fileName);
|
||||
virtual ~RGBImage() = default;
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
@@ -1,32 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace frc {
|
||||
|
||||
/**
|
||||
* Color threshold values.
|
||||
* This object represnts the threshold values for any type of color object
|
||||
* that is used in a threshhold operation. It simplifies passing values
|
||||
* around in a program for color detection.
|
||||
*/
|
||||
class Threshold {
|
||||
public:
|
||||
int plane1Low;
|
||||
int plane1High;
|
||||
int plane2Low;
|
||||
int plane2High;
|
||||
int plane3Low;
|
||||
int plane3High;
|
||||
Threshold(int plane1Low, int plane1High, int plane2Low, int plane2High,
|
||||
int plane3Low, int plane3High);
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
@@ -1,180 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "nivision.h"
|
||||
|
||||
/* Constants */
|
||||
|
||||
#define DEFAULT_BORDER_SIZE 3 // VisionAPI.frcCreateImage
|
||||
#define DEFAULT_SATURATION_THRESHOLD 40 // TrackAPI.FindColor
|
||||
|
||||
namespace frc {
|
||||
|
||||
/* Forward Declare Data Structures */
|
||||
typedef struct FindEdgeOptions_struct FindEdgeOptions;
|
||||
typedef struct CircularEdgeReport_struct CircularEdgeReport;
|
||||
|
||||
/* Data Structures */
|
||||
|
||||
/** frcParticleAnalysis returns this structure */
|
||||
typedef struct ParticleAnalysisReport_struct {
|
||||
int imageHeight;
|
||||
int imageWidth;
|
||||
double imageTimestamp;
|
||||
int particleIndex; // the particle index analyzed
|
||||
/* X-coordinate of the point representing the average position of the
|
||||
* total particle mass, assuming every point in the particle has a constant
|
||||
* density
|
||||
*/
|
||||
int center_mass_x; // MeasurementType: IMAQ_MT_CENTER_OF_MASS_X
|
||||
/* Y-coordinate of the point representing the average position of the
|
||||
* total particle mass, assuming every point in the particle has a constant
|
||||
* density
|
||||
*/
|
||||
int center_mass_y; // MeasurementType: IMAQ_MT_CENTER_OF_MASS_Y
|
||||
double center_mass_x_normalized; // Center of mass x value normalized to -1.0
|
||||
// to +1.0 range
|
||||
double center_mass_y_normalized; // Center of mass y value normalized to -1.0
|
||||
// to +1.0 range
|
||||
/* Area of the particle */
|
||||
double particleArea; // MeasurementType: IMAQ_MT_AREA
|
||||
/* Bounding Rectangle */
|
||||
Rect boundingRect; // left/top/width/height
|
||||
/* Percentage of the particle Area covering the Image Area. */
|
||||
double particleToImagePercent; // MeasurementType: IMAQ_MT_AREA_BY_IMAGE_AREA
|
||||
/* Percentage of the particle Area in relation to its Particle and Holes Area
|
||||
*/
|
||||
double particleQuality; // MeasurementType:
|
||||
// IMAQ_MT_AREA_BY_PARTICLE_AND_HOLES_AREA
|
||||
} ParticleAnalysisReport;
|
||||
|
||||
/** Tracking functions return this structure */
|
||||
typedef struct ColorReport_struct {
|
||||
int numberParticlesFound; // Number of particles found for this color
|
||||
int largestParticleNumber; // The particle index of the largest particle
|
||||
/* Color information */
|
||||
float particleHueMax; // HistogramReport: hue max
|
||||
float particleHueMin; // HistogramReport: hue max
|
||||
float particleHueMean; // HistogramReport: hue mean
|
||||
float particleSatMax; // HistogramReport: saturation max
|
||||
float particleSatMin; // HistogramReport: saturation max
|
||||
float particleSatMean; // HistogramReport: saturation mean
|
||||
float particleLumMax; // HistogramReport: luminance max
|
||||
float particleLumMin; // HistogramReport: luminance max
|
||||
float particleLumMean; // HistogramReport: luminance mean
|
||||
} ColorReport;
|
||||
|
||||
/* Image Management functions */
|
||||
|
||||
/* Create: calls imaqCreateImage. Border size is set to some default value */
|
||||
Image* frcCreateImage(ImageType type);
|
||||
|
||||
/* Dispose: calls imaqDispose */
|
||||
int frcDispose(void* object);
|
||||
int frcDispose(const char* filename, ...);
|
||||
|
||||
/* Copy: calls imaqDuplicateImage */
|
||||
int frcCopyImage(Image* dest, const Image* source);
|
||||
|
||||
/* Image Extraction: Crop: calls imaqScale */
|
||||
int frcCrop(Image* dest, const Image* source, Rect rect);
|
||||
|
||||
/* Image Extraction: Scale: calls imaqScale. Scales entire image */
|
||||
int frcScale(Image* dest, const Image* source, int xScale, int yScale,
|
||||
ScalingMode scaleMode);
|
||||
|
||||
/* Read Image : calls imaqReadFile */
|
||||
int frcReadImage(Image* image, const char* fileName);
|
||||
/* Write Image : calls imaqWriteFile */
|
||||
int frcWriteImage(const Image* image, const char* fileName);
|
||||
|
||||
/* Measure Intensity functions */
|
||||
|
||||
/* Histogram: calls imaqHistogram */
|
||||
HistogramReport* frcHistogram(const Image* image, int numClasses, float min,
|
||||
float max, Rect rect);
|
||||
/* Color Histogram: calls imaqColorHistogram2 */
|
||||
ColorHistogramReport* frcColorHistogram(const Image* image, int numClasses,
|
||||
ColorMode mode, Image* mask);
|
||||
|
||||
/* Get Pixel Value: calls imaqGetPixel */
|
||||
int frcGetPixelValue(const Image* image, Point pixel, PixelValue* value);
|
||||
|
||||
/* Particle Analysis functions */
|
||||
|
||||
/* Particle Filter: calls imaqParticleFilter3 */
|
||||
int frcParticleFilter(Image* dest, Image* source,
|
||||
const ParticleFilterCriteria2* criteria,
|
||||
int criteriaCount, const ParticleFilterOptions* options,
|
||||
Rect rect, int* numParticles);
|
||||
int frcParticleFilter(Image* dest, Image* source,
|
||||
const ParticleFilterCriteria2* criteria,
|
||||
int criteriaCount, const ParticleFilterOptions* options,
|
||||
int* numParticles);
|
||||
/* Morphology: calls imaqMorphology */
|
||||
int frcMorphology(Image* dest, Image* source, MorphologyMethod method);
|
||||
int frcMorphology(Image* dest, Image* source, MorphologyMethod method,
|
||||
const StructuringElement* structuringElement);
|
||||
/* Reject Border: calls imaqRejectBorder */
|
||||
int frcRejectBorder(Image* dest, Image* source);
|
||||
int frcRejectBorder(Image* dest, Image* source, int connectivity8);
|
||||
/* Count Particles: calls imaqCountParticles */
|
||||
int frcCountParticles(Image* image, int* numParticles);
|
||||
/* Particle Analysis Report: calls imaqMeasureParticle */
|
||||
int frcParticleAnalysis(Image* image, int particleNumber,
|
||||
ParticleAnalysisReport* par);
|
||||
|
||||
/* Image Enhancement functions */
|
||||
|
||||
/* Equalize: calls imaqEqualize */
|
||||
int frcEqualize(Image* dest, const Image* source, float min, float max);
|
||||
int frcEqualize(Image* dest, const Image* source, float min, float max,
|
||||
const Image* mask);
|
||||
|
||||
/* Color Equalize: calls imaqColorEqualize */
|
||||
int frcColorEqualize(Image* dest, const Image* source);
|
||||
int frcColorEqualize(Image* dest, const Image* source, int colorEqualization);
|
||||
|
||||
/* Image Thresholding & Conversion functions */
|
||||
|
||||
/* Smart Threshold: calls imaqLocalThreshold */
|
||||
int frcSmartThreshold(Image* dest, const Image* source, int windowWidth,
|
||||
int windowHeight, LocalThresholdMethod method,
|
||||
double deviationWeight, ObjectType type);
|
||||
int frcSmartThreshold(Image* dest, const Image* source, int windowWidth,
|
||||
int windowHeight, LocalThresholdMethod method,
|
||||
double deviationWeight, ObjectType type,
|
||||
float replaceValue);
|
||||
|
||||
/* Simple Threshold: calls imaqThreshold */
|
||||
int frcSimpleThreshold(Image* dest, const Image* source, float rangeMin,
|
||||
float rangeMax, float newValue);
|
||||
int frcSimpleThreshold(Image* dest, const Image* source, float rangeMin,
|
||||
float rangeMax);
|
||||
|
||||
/* Color/Hue Threshold: calls imaqColorThreshold */
|
||||
int frcColorThreshold(Image* dest, const Image* source, ColorMode mode,
|
||||
const Range* plane1Range, const Range* plane2Range,
|
||||
const Range* plane3Range);
|
||||
int frcColorThreshold(Image* dest, const Image* source, int replaceValue,
|
||||
ColorMode mode, const Range* plane1Range,
|
||||
const Range* plane2Range, const Range* plane3Range);
|
||||
int frcHueThreshold(Image* dest, const Image* source, const Range* hueRange);
|
||||
int frcHueThreshold(Image* dest, const Image* source, const Range* hueRange,
|
||||
int minSaturation);
|
||||
|
||||
/* Extract ColorHue Plane: calls imaqExtractColorPlanes */
|
||||
int frcExtractColorPlanes(const Image* image, ColorMode mode, Image* plane1,
|
||||
Image* plane2, Image* plane3);
|
||||
int frcExtractHuePlane(const Image* image, Image* huePlane);
|
||||
int frcExtractHuePlane(const Image* image, Image* huePlane, int minSaturation);
|
||||
|
||||
} // namespace frc
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "Buttons/InternalButton.h"
|
||||
#include "Buttons/JoystickButton.h"
|
||||
#include "Buttons/NetworkButton.h"
|
||||
#include "CameraServer.h"
|
||||
#include "Commands/Command.h"
|
||||
#include "Commands/CommandGroup.h"
|
||||
#include "Commands/PIDCommand.h"
|
||||
@@ -81,14 +80,6 @@
|
||||
#include "Utility.h"
|
||||
#include "Victor.h"
|
||||
#include "VictorSP.h"
|
||||
#include "Vision/AxisCamera.h"
|
||||
#include "Vision/BinaryImage.h"
|
||||
#include "Vision/ColorImage.h"
|
||||
#include "Vision/HSLImage.h"
|
||||
#include "Vision/ImageBase.h"
|
||||
#include "Vision/MonoImage.h"
|
||||
#include "Vision/RGBImage.h"
|
||||
#include "Vision/Threshold.h"
|
||||
#include "WPIErrors.h"
|
||||
#include "interfaces/Accelerometer.h"
|
||||
#include "interfaces/Gyro.h"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,280 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "CameraServer.h"
|
||||
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
#include "Utility.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
constexpr uint8_t CameraServer::kMagicNumber[];
|
||||
|
||||
CameraServer* CameraServer::GetInstance() {
|
||||
static CameraServer instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
CameraServer::CameraServer()
|
||||
: m_camera(),
|
||||
m_serverThread(&CameraServer::Serve, this),
|
||||
m_captureThread(),
|
||||
m_imageMutex(),
|
||||
m_newImageVariable(),
|
||||
m_dataPool(3),
|
||||
m_quality(50),
|
||||
m_autoCaptureStarted(false),
|
||||
m_hwClient(true),
|
||||
m_imageData(nullptr, 0, 0, false) {
|
||||
for (int i = 0; i < 3; i++) m_dataPool.push_back(new uint8_t[kMaxImageSize]);
|
||||
}
|
||||
|
||||
void CameraServer::FreeImageData(
|
||||
std::tuple<uint8_t*, int, int, bool> imageData) {
|
||||
if (std::get<3>(imageData)) {
|
||||
imaqDispose(std::get<0>(imageData));
|
||||
} else if (std::get<0>(imageData) != nullptr) {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_imageMutex);
|
||||
m_dataPool.push_back(std::get<0>(imageData));
|
||||
}
|
||||
}
|
||||
|
||||
void CameraServer::SetImageData(uint8_t* data, int size, int start,
|
||||
bool imaqData) {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_imageMutex);
|
||||
FreeImageData(m_imageData);
|
||||
m_imageData = std::make_tuple(data, size, start, imaqData);
|
||||
m_newImageVariable.notify_all();
|
||||
}
|
||||
|
||||
void CameraServer::SetImage(Image const* image) {
|
||||
uint32_t dataSize = 0;
|
||||
uint8_t* data = reinterpret_cast<uint8_t*>(
|
||||
imaqFlatten(image, IMAQ_FLATTEN_IMAGE, IMAQ_COMPRESSION_JPEG,
|
||||
10 * m_quality, &dataSize));
|
||||
|
||||
// If we're using a HW camera, then find the start of the data
|
||||
bool hwClient;
|
||||
{
|
||||
// Make a local copy of the hwClient variable so that we can safely use it.
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_imageMutex);
|
||||
hwClient = m_hwClient;
|
||||
}
|
||||
uint32_t start = 0;
|
||||
if (hwClient) {
|
||||
while (start < dataSize - 1) {
|
||||
if (data[start] == 0xFF && data[start + 1] == 0xD8)
|
||||
break;
|
||||
else
|
||||
start++;
|
||||
}
|
||||
}
|
||||
dataSize -= start;
|
||||
|
||||
wpi_assert(dataSize > 2);
|
||||
SetImageData(data, dataSize, start, true);
|
||||
}
|
||||
|
||||
void CameraServer::AutoCapture() {
|
||||
Image* frame = imaqCreateImage(IMAQ_IMAGE_RGB, 0);
|
||||
|
||||
while (true) {
|
||||
bool hwClient;
|
||||
uint8_t* data = nullptr;
|
||||
{
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_imageMutex);
|
||||
hwClient = m_hwClient;
|
||||
if (hwClient) {
|
||||
data = m_dataPool.back();
|
||||
m_dataPool.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
if (hwClient) {
|
||||
int size = m_camera->GetImageData(data, kMaxImageSize);
|
||||
SetImageData(data, size);
|
||||
} else {
|
||||
m_camera->GetImage(frame);
|
||||
SetImage(frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CameraServer::StartAutomaticCapture(char const* cameraName) {
|
||||
std::shared_ptr<USBCamera> camera =
|
||||
std::make_shared<USBCamera>(cameraName, true);
|
||||
camera->OpenCamera();
|
||||
StartAutomaticCapture(camera);
|
||||
}
|
||||
|
||||
void CameraServer::StartAutomaticCapture(std::shared_ptr<USBCamera> camera) {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_imageMutex);
|
||||
if (m_autoCaptureStarted) return;
|
||||
|
||||
m_camera = camera;
|
||||
m_camera->StartCapture();
|
||||
|
||||
m_captureThread = std::thread(&CameraServer::AutoCapture, this);
|
||||
m_captureThread.detach();
|
||||
m_autoCaptureStarted = true;
|
||||
}
|
||||
|
||||
bool CameraServer::IsAutoCaptureStarted() {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_imageMutex);
|
||||
return m_autoCaptureStarted;
|
||||
}
|
||||
|
||||
void CameraServer::SetSize(int size) {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_imageMutex);
|
||||
if (!m_camera) return;
|
||||
if (size == kSize160x120)
|
||||
m_camera->SetSize(160, 120);
|
||||
else if (size == kSize320x240)
|
||||
m_camera->SetSize(320, 240);
|
||||
else if (size == kSize640x480)
|
||||
m_camera->SetSize(640, 480);
|
||||
}
|
||||
|
||||
void CameraServer::SetQuality(int quality) {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_imageMutex);
|
||||
m_quality = quality > 100 ? 100 : quality;
|
||||
}
|
||||
|
||||
int CameraServer::GetQuality() {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_imageMutex);
|
||||
return m_quality;
|
||||
}
|
||||
|
||||
void CameraServer::Serve() {
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (sock == -1) {
|
||||
wpi_setErrnoError();
|
||||
return;
|
||||
}
|
||||
|
||||
int reuseAddr = 1;
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseAddr,
|
||||
sizeof(reuseAddr)) == -1)
|
||||
wpi_setErrnoError();
|
||||
|
||||
sockaddr_in address, clientAddress;
|
||||
|
||||
std::memset(&address, 0, sizeof(address));
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
address.sin_port = htons(kPort);
|
||||
|
||||
if (bind(sock, reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
||||
wpi_setErrnoError();
|
||||
|
||||
if (listen(sock, 10) == -1) wpi_setErrnoError();
|
||||
|
||||
while (true) {
|
||||
socklen_t clientAddressLen = sizeof(clientAddress);
|
||||
|
||||
int conn = accept(sock, reinterpret_cast<sockaddr*>(&clientAddress),
|
||||
&clientAddressLen);
|
||||
if (conn == -1) {
|
||||
wpi_setErrnoError();
|
||||
continue;
|
||||
}
|
||||
|
||||
Request req;
|
||||
char reqBuf[sizeof(req)];
|
||||
size_t reqPos = 0;
|
||||
|
||||
while (reqPos < sizeof(req)) {
|
||||
ssize_t sizeRead = read(conn, &reqBuf[reqPos], sizeof(req) - reqPos);
|
||||
if (sizeRead < 0) break;
|
||||
reqPos += sizeRead;
|
||||
}
|
||||
|
||||
if (reqPos < sizeof(req)) {
|
||||
wpi_setErrnoError();
|
||||
close(conn);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::memcpy(&req, reqBuf, sizeof(req));
|
||||
req.fps = ntohl(req.fps);
|
||||
req.compression = ntohl(req.compression);
|
||||
req.size = ntohl(req.size);
|
||||
|
||||
// TODO: Support the SW Compression. The rest of the code below will work as
|
||||
// though this check isn't here
|
||||
if (req.compression != kHardwareCompression) {
|
||||
wpi_setWPIErrorWithContext(IncompatibleState,
|
||||
"Choose \"USB Camera HW\" on the dashboard");
|
||||
close(conn);
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
// Wait for the camera to be setw
|
||||
std::unique_lock<priority_recursive_mutex> lock(m_imageMutex);
|
||||
if (!m_camera) {
|
||||
std::cout << "Camera not yet ready, awaiting first image" << std::endl;
|
||||
m_newImageVariable.wait(lock);
|
||||
}
|
||||
m_hwClient = req.compression == kHardwareCompression;
|
||||
if (!m_hwClient)
|
||||
SetQuality(100 - req.compression);
|
||||
else if (m_camera)
|
||||
m_camera->SetFPS(req.fps);
|
||||
SetSize(req.size);
|
||||
}
|
||||
|
||||
auto period = std::chrono::microseconds(1000000) / req.fps;
|
||||
while (true) {
|
||||
auto startTime = std::chrono::steady_clock::now();
|
||||
std::tuple<uint8_t*, int, int, bool> imageData;
|
||||
{
|
||||
std::unique_lock<priority_recursive_mutex> lock(m_imageMutex);
|
||||
m_newImageVariable.wait(lock);
|
||||
imageData = m_imageData;
|
||||
m_imageData = std::make_tuple<uint8_t*>(nullptr, 0, 0, false);
|
||||
}
|
||||
|
||||
int size = std::get<1>(imageData);
|
||||
int netSize = htonl(size);
|
||||
int start = std::get<2>(imageData);
|
||||
uint8_t* data = std::get<0>(imageData);
|
||||
|
||||
if (data == nullptr) continue;
|
||||
|
||||
if (write(conn, kMagicNumber, sizeof(kMagicNumber)) == -1) {
|
||||
wpi_setErrnoErrorWithContext(
|
||||
"[CameraServer] Error sending magic number");
|
||||
FreeImageData(imageData);
|
||||
break;
|
||||
}
|
||||
if (write(conn, &netSize, sizeof(netSize)) == -1) {
|
||||
wpi_setErrnoErrorWithContext("[CameraServer] Error sending image size");
|
||||
FreeImageData(imageData);
|
||||
break;
|
||||
}
|
||||
if (write(conn, &data[start], sizeof(uint8_t) * size) == -1) {
|
||||
wpi_setErrnoErrorWithContext("[CameraServer] Error sending image data");
|
||||
FreeImageData(imageData);
|
||||
break;
|
||||
}
|
||||
FreeImageData(imageData);
|
||||
std::this_thread::sleep_until(startTime + period);
|
||||
}
|
||||
close(conn);
|
||||
}
|
||||
close(sock);
|
||||
}
|
||||
@@ -1,336 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "USBCamera.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <regex>
|
||||
#include <thread>
|
||||
|
||||
#include "Utility.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
// This macro expands the given imaq function to ensure that it is called and
|
||||
// properly checked for an error, calling the wpi_setImaqErrorWithContext
|
||||
// macro
|
||||
// To call it, just give the name of the function and the arguments
|
||||
#define SAFE_IMAQ_CALL(funName, ...) \
|
||||
{ \
|
||||
int error = funName(__VA_ARGS__); \
|
||||
if (error != IMAQdxErrorSuccess) \
|
||||
wpi_setImaqErrorWithContext(error, #funName); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to determine the size of a jpeg. The general structure of
|
||||
* how to parse a jpeg for length can be found in this stackoverflow article:
|
||||
* http://stackoverflow.com/a/1602428. Be sure to also read the comments for
|
||||
* the SOS flag explanation.
|
||||
*/
|
||||
int USBCamera::GetJpegSize(void* buffer, int buffSize) {
|
||||
uint8_t* data = static_cast<uint8_t*>(buffer);
|
||||
if (!wpi_assert(data[0] == 0xff && data[1] == 0xd8)) return 0;
|
||||
int pos = 2;
|
||||
while (pos < buffSize) {
|
||||
// All control markers start with 0xff, so if this isn't present,
|
||||
// the JPEG is not valid
|
||||
if (!wpi_assert(data[pos] == 0xff)) return 0;
|
||||
int t = data[pos + 1];
|
||||
// These are RST markers. We just skip them and move onto the next marker
|
||||
if (t == 0x01 || (t >= 0xd0 && t <= 0xd7)) {
|
||||
pos += 2;
|
||||
} else if (t == 0xd9) {
|
||||
// End of Image, add 2 for this and 0-indexed
|
||||
return pos + 2;
|
||||
} else if (!wpi_assert(t != 0xd8)) {
|
||||
// Another start of image, invalid image
|
||||
return 0;
|
||||
} else if (t == 0xda) {
|
||||
// SOS marker. The next two bytes are a 16-bit big-endian int that is
|
||||
// the length of the SOS header, skip that
|
||||
int len = (static_cast<int>(data[pos + 2]) & 0xff) << 8 |
|
||||
(static_cast<int>(data[pos + 3]) & 0xff);
|
||||
pos += len + 2;
|
||||
// The next marker is the first marker that is 0xff followed by a non-RST
|
||||
// element. 0xff followed by 0x00 is an escaped 0xff. 0xd0-0xd7 are RST
|
||||
// markers
|
||||
while (data[pos] != 0xff || data[pos + 1] == 0x00 ||
|
||||
(data[pos + 1] >= 0xd0 && data[pos + 1] <= 0xd7)) {
|
||||
pos += 1;
|
||||
if (pos >= buffSize) return 0;
|
||||
}
|
||||
} else {
|
||||
// This is one of several possible markers. The next two bytes are a
|
||||
// 16-bit
|
||||
// big-endian int with the length of the marker header, skip that then
|
||||
// continue searching
|
||||
int len = (static_cast<int>(data[pos + 2]) & 0xff) << 8 |
|
||||
(static_cast<int>(data[pos + 3]) & 0xff);
|
||||
pos += len + 2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
USBCamera::USBCamera(std::string name, bool useJpeg)
|
||||
: m_name(name), m_useJpeg(useJpeg) {}
|
||||
|
||||
void USBCamera::OpenCamera() {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_mutex);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
uInt32 id = 0;
|
||||
// Can't use SAFE_IMAQ_CALL here because we only error on the third time
|
||||
IMAQdxError error = IMAQdxOpenCamera(
|
||||
m_name.c_str(), IMAQdxCameraControlModeController, &id);
|
||||
if (error != IMAQdxErrorSuccess) {
|
||||
// Only error on the 3rd try
|
||||
if (i >= 2) wpi_setImaqErrorWithContext(error, "IMAQdxOpenCamera");
|
||||
// Sleep for a few seconds to ensure the error has been dealt with
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
|
||||
} else {
|
||||
m_id = id;
|
||||
m_open = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void USBCamera::CloseCamera() {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_mutex);
|
||||
if (!m_open) return;
|
||||
SAFE_IMAQ_CALL(IMAQdxCloseCamera, m_id);
|
||||
m_id = 0;
|
||||
m_open = false;
|
||||
}
|
||||
|
||||
void USBCamera::StartCapture() {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_mutex);
|
||||
if (!m_open || m_active) return;
|
||||
SAFE_IMAQ_CALL(IMAQdxConfigureGrab, m_id);
|
||||
SAFE_IMAQ_CALL(IMAQdxStartAcquisition, m_id);
|
||||
m_active = true;
|
||||
}
|
||||
|
||||
void USBCamera::StopCapture() {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_mutex);
|
||||
if (!m_open || !m_active) return;
|
||||
SAFE_IMAQ_CALL(IMAQdxStopAcquisition, m_id);
|
||||
SAFE_IMAQ_CALL(IMAQdxUnconfigureAcquisition, m_id);
|
||||
m_active = false;
|
||||
}
|
||||
|
||||
void USBCamera::UpdateSettings() {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_mutex);
|
||||
bool wasActive = m_active;
|
||||
|
||||
if (wasActive) StopCapture();
|
||||
if (m_open) CloseCamera();
|
||||
OpenCamera();
|
||||
|
||||
uInt32 count = 0;
|
||||
uInt32 currentMode = 0;
|
||||
SAFE_IMAQ_CALL(IMAQdxEnumerateVideoModes, m_id, nullptr, &count,
|
||||
¤tMode);
|
||||
auto modes = std::make_unique<IMAQdxVideoMode[]>(count);
|
||||
SAFE_IMAQ_CALL(IMAQdxEnumerateVideoModes, m_id, modes.get(), &count,
|
||||
¤tMode);
|
||||
|
||||
// Groups are:
|
||||
// 0 - width
|
||||
// 1 - height
|
||||
// 2 - format
|
||||
// 3 - fps
|
||||
std::regex reMode("([0-9]+)\\s*x\\s*([0-9]+)\\s+(.*?)\\s+([0-9.]+)\\s*fps");
|
||||
IMAQdxVideoMode* foundMode = nullptr;
|
||||
IMAQdxVideoMode* currentModePtr = &modes[currentMode];
|
||||
double foundFps = 1000.0;
|
||||
|
||||
// Loop through the modes, and find the match with the lowest fps
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
std::cmatch m;
|
||||
if (!std::regex_match(modes[i].Name, m, reMode)) continue;
|
||||
int width = static_cast<int>(std::stoul(m[1].str()));
|
||||
int height = static_cast<int>(std::stoul(m[2].str()));
|
||||
if (width != m_width) continue;
|
||||
if (height != m_height) continue;
|
||||
double fps = std::atof(m[4].str().c_str());
|
||||
if (fps < m_fps) continue;
|
||||
if (fps > foundFps) continue;
|
||||
bool isJpeg =
|
||||
m[3].str().compare("jpeg") == 0 || m[3].str().compare("JPEG") == 0;
|
||||
if ((m_useJpeg && !isJpeg) || (!m_useJpeg && isJpeg)) continue;
|
||||
foundMode = &modes[i];
|
||||
foundFps = fps;
|
||||
}
|
||||
if (foundMode != nullptr) {
|
||||
if (foundMode->Value != currentModePtr->Value) {
|
||||
SAFE_IMAQ_CALL(IMAQdxSetAttribute, m_id, IMAQdxAttributeVideoMode,
|
||||
IMAQdxValueTypeU32, foundMode->Value);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_whiteBalance.compare(AUTO) == 0) {
|
||||
SAFE_IMAQ_CALL(IMAQdxSetAttribute, m_id, ATTR_WB_MODE,
|
||||
IMAQdxValueTypeString, AUTO);
|
||||
} else {
|
||||
SAFE_IMAQ_CALL(IMAQdxSetAttribute, m_id, ATTR_WB_MODE,
|
||||
IMAQdxValueTypeString, MANUAL);
|
||||
if (m_whiteBalanceValuePresent)
|
||||
SAFE_IMAQ_CALL(IMAQdxSetAttribute, m_id, ATTR_WB_VALUE,
|
||||
IMAQdxValueTypeU32, m_whiteBalanceValue);
|
||||
}
|
||||
|
||||
if (m_exposure.compare(AUTO) == 0) {
|
||||
SAFE_IMAQ_CALL(IMAQdxSetAttribute, m_id, ATTR_EX_MODE,
|
||||
IMAQdxValueTypeString,
|
||||
std::string("AutoAperaturePriority").c_str());
|
||||
} else {
|
||||
SAFE_IMAQ_CALL(IMAQdxSetAttribute, m_id, ATTR_EX_MODE,
|
||||
IMAQdxValueTypeString, MANUAL);
|
||||
if (m_exposureValuePresent) {
|
||||
double minv = 0.0;
|
||||
double maxv = 0.0;
|
||||
SAFE_IMAQ_CALL(IMAQdxGetAttributeMinimum, m_id, ATTR_EX_VALUE,
|
||||
IMAQdxValueTypeF64, &minv);
|
||||
SAFE_IMAQ_CALL(IMAQdxGetAttributeMaximum, m_id, ATTR_EX_VALUE,
|
||||
IMAQdxValueTypeF64, &maxv);
|
||||
double val =
|
||||
minv + (maxv - minv) * (static_cast<double>(m_exposureValue) / 100.0);
|
||||
SAFE_IMAQ_CALL(IMAQdxSetAttribute, m_id, ATTR_EX_VALUE,
|
||||
IMAQdxValueTypeF64, val);
|
||||
}
|
||||
}
|
||||
|
||||
SAFE_IMAQ_CALL(IMAQdxSetAttribute, m_id, ATTR_BR_MODE, IMAQdxValueTypeString,
|
||||
MANUAL);
|
||||
double minv = 0.0;
|
||||
double maxv = 0.0;
|
||||
SAFE_IMAQ_CALL(IMAQdxGetAttributeMinimum, m_id, ATTR_BR_VALUE,
|
||||
IMAQdxValueTypeF64, &minv);
|
||||
SAFE_IMAQ_CALL(IMAQdxGetAttributeMaximum, m_id, ATTR_BR_VALUE,
|
||||
IMAQdxValueTypeF64, &maxv);
|
||||
double val =
|
||||
minv + (maxv - minv) * (static_cast<double>(m_brightness) / 100.0);
|
||||
SAFE_IMAQ_CALL(IMAQdxSetAttribute, m_id, ATTR_BR_VALUE, IMAQdxValueTypeF64,
|
||||
val);
|
||||
|
||||
if (wasActive) StartCapture();
|
||||
}
|
||||
|
||||
void USBCamera::SetFPS(double fps) {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_mutex);
|
||||
if (m_fps != fps) {
|
||||
m_needSettingsUpdate = true;
|
||||
m_fps = fps;
|
||||
}
|
||||
}
|
||||
|
||||
void USBCamera::SetSize(int width, int height) {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_mutex);
|
||||
if (m_width != width || m_height != height) {
|
||||
m_needSettingsUpdate = true;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
}
|
||||
}
|
||||
|
||||
void USBCamera::SetBrightness(int brightness) {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_mutex);
|
||||
if (m_brightness != brightness) {
|
||||
m_needSettingsUpdate = true;
|
||||
m_brightness = brightness;
|
||||
}
|
||||
}
|
||||
|
||||
int USBCamera::GetBrightness() {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_mutex);
|
||||
return m_brightness;
|
||||
}
|
||||
|
||||
void USBCamera::SetWhiteBalanceAuto() {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_mutex);
|
||||
m_whiteBalance = AUTO;
|
||||
m_whiteBalanceValue = 0;
|
||||
m_whiteBalanceValuePresent = false;
|
||||
m_needSettingsUpdate = true;
|
||||
}
|
||||
|
||||
void USBCamera::SetWhiteBalanceHoldCurrent() {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_mutex);
|
||||
m_whiteBalance = MANUAL;
|
||||
m_whiteBalanceValue = 0;
|
||||
m_whiteBalanceValuePresent = false;
|
||||
m_needSettingsUpdate = true;
|
||||
}
|
||||
|
||||
void USBCamera::SetWhiteBalanceManual(int whiteBalance) {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_mutex);
|
||||
m_whiteBalance = MANUAL;
|
||||
m_whiteBalanceValue = whiteBalance;
|
||||
m_whiteBalanceValuePresent = true;
|
||||
m_needSettingsUpdate = true;
|
||||
}
|
||||
|
||||
void USBCamera::SetExposureAuto() {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_mutex);
|
||||
m_exposure = AUTO;
|
||||
m_exposureValue = 0;
|
||||
m_exposureValuePresent = false;
|
||||
m_needSettingsUpdate = true;
|
||||
}
|
||||
|
||||
void USBCamera::SetExposureHoldCurrent() {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_mutex);
|
||||
m_exposure = MANUAL;
|
||||
m_exposureValue = 0;
|
||||
m_exposureValuePresent = false;
|
||||
m_needSettingsUpdate = true;
|
||||
}
|
||||
|
||||
void USBCamera::SetExposureManual(int level) {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_mutex);
|
||||
m_exposure = MANUAL;
|
||||
if (level > 100)
|
||||
m_exposureValue = 100;
|
||||
else
|
||||
m_exposureValue = level;
|
||||
m_exposureValuePresent = true;
|
||||
m_needSettingsUpdate = true;
|
||||
}
|
||||
|
||||
void USBCamera::GetImage(Image* image) {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_mutex);
|
||||
if (m_needSettingsUpdate || m_useJpeg) {
|
||||
m_needSettingsUpdate = false;
|
||||
m_useJpeg = false;
|
||||
UpdateSettings();
|
||||
}
|
||||
// BufNum is not actually used for anything at our level, since we are
|
||||
// waiting until the next image is ready anyway
|
||||
uInt32 bufNum;
|
||||
SAFE_IMAQ_CALL(IMAQdxGrab, m_id, image, 1, &bufNum);
|
||||
}
|
||||
|
||||
int USBCamera::GetImageData(void* buffer, int bufferSize) {
|
||||
std::lock_guard<priority_recursive_mutex> lock(m_mutex);
|
||||
if (m_needSettingsUpdate || !m_useJpeg) {
|
||||
m_needSettingsUpdate = false;
|
||||
m_useJpeg = true;
|
||||
UpdateSettings();
|
||||
}
|
||||
// BufNum is not actually used for anything at our level
|
||||
uInt32 bufNum;
|
||||
SAFE_IMAQ_CALL(IMAQdxGetImageData, m_id, buffer, bufferSize,
|
||||
IMAQdxBufferNumberModeLast, 0, &bufNum);
|
||||
return GetJpegSize(buffer, bufferSize);
|
||||
}
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
#include "ErrorBase.h"
|
||||
#include "HAL/HAL.h"
|
||||
#include "nivision.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
|
||||
@@ -1,620 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "Vision/AxisCamera.h"
|
||||
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "Timer.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
static const int kMaxPacketSize = 1536;
|
||||
static const int kImageBufferAllocationIncrement = 1000;
|
||||
|
||||
static const std::string kWhiteBalanceStrings[] = {
|
||||
"auto", "hold", "fixed_outdoor1", "fixed_outdoor2",
|
||||
"fixed_indoor", "fixed_fluor1", "fixed_fluor2",
|
||||
};
|
||||
|
||||
static const std::string kExposureControlStrings[] = {
|
||||
"auto", "hold", "flickerfree50", "flickerfree60",
|
||||
};
|
||||
|
||||
static const std::string kResolutionStrings[] = {
|
||||
"640x480", "480x360", "320x240", "240x180", "176x144", "160x120",
|
||||
};
|
||||
|
||||
static const std::string kRotationStrings[] = {
|
||||
"0", "180",
|
||||
};
|
||||
|
||||
/**
|
||||
* AxisCamera constructor.
|
||||
*
|
||||
* @param cameraHost The host to find the camera at, typically an IP address
|
||||
*/
|
||||
AxisCamera::AxisCamera(std::string const& cameraHost)
|
||||
: m_cameraHost(cameraHost) {
|
||||
m_captureThread = std::thread(&AxisCamera::Capture, this);
|
||||
}
|
||||
|
||||
AxisCamera::~AxisCamera() {
|
||||
m_done = true;
|
||||
m_captureThread.join();
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if the latest image from the camera has not been retrieved by
|
||||
* calling GetImage() yet.
|
||||
*
|
||||
* @return true if the image has not been retrieved yet.
|
||||
*/
|
||||
bool AxisCamera::IsFreshImage() const { return m_freshImage; }
|
||||
|
||||
/**
|
||||
* Get an image from the camera and store it in the provided image.
|
||||
*
|
||||
* @param image The imaq image to store the result in. This must be an HSL or
|
||||
* RGB image.
|
||||
* @return 1 upon success, zero on a failure
|
||||
*/
|
||||
int AxisCamera::GetImage(Image* image) {
|
||||
if (m_imageData.size() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::lock_guard<priority_mutex> lock(m_imageDataMutex);
|
||||
|
||||
Priv_ReadJPEGString_C(image, m_imageData.data(), m_imageData.size());
|
||||
|
||||
m_freshImage = false;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an image from the camera and store it in the provided image.
|
||||
*
|
||||
* @param image The image to store the result in. This must be an HSL or RGB
|
||||
* image
|
||||
* @return 1 upon success, zero on a failure
|
||||
*/
|
||||
int AxisCamera::GetImage(ColorImage* image) {
|
||||
return GetImage(image->GetImaqImage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a new image object and fill it with the latest image from the
|
||||
* camera.
|
||||
*
|
||||
* The returned pointer is owned by the caller and is their responsibility to
|
||||
* delete.
|
||||
*
|
||||
* @return a pointer to an HSLImage object
|
||||
*/
|
||||
HSLImage* AxisCamera::GetImage() {
|
||||
auto image = new HSLImage();
|
||||
GetImage(image);
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy an image into an existing buffer.
|
||||
*
|
||||
* This copies an image into an existing buffer rather than creating a new image
|
||||
* in memory. That way a new image is only allocated when the image being copied
|
||||
* is larger than the destination.
|
||||
*
|
||||
* This method is called by the PCVideoServer class.
|
||||
*
|
||||
* @param imageData The destination image.
|
||||
* @param numBytes The size of the destination image.
|
||||
* @return 0 if failed (no source image or no memory), 1 if success.
|
||||
*/
|
||||
int AxisCamera::CopyJPEG(char** destImage, int& destImageSize,
|
||||
int& destImageBufferSize) {
|
||||
std::lock_guard<priority_mutex> lock(m_imageDataMutex);
|
||||
if (destImage == nullptr) {
|
||||
wpi_setWPIErrorWithContext(NullParameter, "destImage must not be nullptr");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (m_imageData.size() == 0) return 0; // if no source image
|
||||
|
||||
// if current destination buffer too small
|
||||
if (static_cast<uint32_t>(destImageBufferSize) < m_imageData.size()) {
|
||||
if (*destImage != nullptr) delete[] * destImage;
|
||||
destImageBufferSize = m_imageData.size() + kImageBufferAllocationIncrement;
|
||||
*destImage = new char[destImageBufferSize];
|
||||
if (*destImage == nullptr) return 0;
|
||||
}
|
||||
// copy this image into destination buffer
|
||||
if (*destImage == nullptr) {
|
||||
wpi_setWPIErrorWithContext(NullParameter, "*destImage must not be nullptr");
|
||||
}
|
||||
|
||||
std::copy(m_imageData.begin(), m_imageData.end(), *destImage);
|
||||
destImageSize = m_imageData.size();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a change in the brightness of the camera images.
|
||||
*
|
||||
* @param brightness valid values 0 .. 100
|
||||
*/
|
||||
void AxisCamera::WriteBrightness(int brightness) {
|
||||
if (brightness < 0 || brightness > 100) {
|
||||
wpi_setWPIErrorWithContext(ParameterOutOfRange,
|
||||
"Brightness must be from 0 to 100");
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<priority_mutex> lock(m_parametersMutex);
|
||||
|
||||
if (m_brightness != brightness) {
|
||||
m_brightness = brightness;
|
||||
m_parametersDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured brightness of the camera images
|
||||
*/
|
||||
int AxisCamera::GetBrightness() {
|
||||
std::lock_guard<priority_mutex> lock(m_parametersMutex);
|
||||
return m_brightness;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a change in the white balance on the camera.
|
||||
*
|
||||
* @param whiteBalance Valid values from the <code>WhiteBalance</code> enum.
|
||||
*/
|
||||
void AxisCamera::WriteWhiteBalance(AxisCamera::WhiteBalance whiteBalance) {
|
||||
std::lock_guard<priority_mutex> lock(m_parametersMutex);
|
||||
|
||||
if (m_whiteBalance != whiteBalance) {
|
||||
m_whiteBalance = whiteBalance;
|
||||
m_parametersDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured white balances of the camera images
|
||||
*/
|
||||
AxisCamera::WhiteBalance AxisCamera::GetWhiteBalance() {
|
||||
std::lock_guard<priority_mutex> lock(m_parametersMutex);
|
||||
return m_whiteBalance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a change in the color level of the camera images.
|
||||
*
|
||||
* @param colorLevel valid values are 0 .. 100
|
||||
*/
|
||||
void AxisCamera::WriteColorLevel(int colorLevel) {
|
||||
if (colorLevel < 0 || colorLevel > 100) {
|
||||
wpi_setWPIErrorWithContext(ParameterOutOfRange,
|
||||
"Color level must be from 0 to 100");
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<priority_mutex> lock(m_parametersMutex);
|
||||
|
||||
if (m_colorLevel != colorLevel) {
|
||||
m_colorLevel = colorLevel;
|
||||
m_parametersDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured color level of the camera images
|
||||
*/
|
||||
int AxisCamera::GetColorLevel() {
|
||||
std::lock_guard<priority_mutex> lock(m_parametersMutex);
|
||||
return m_colorLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a change in the camera's exposure mode.
|
||||
*
|
||||
* @param exposureControl A mode to write in the <code>Exposure</code> enum.
|
||||
*/
|
||||
void AxisCamera::WriteExposureControl(
|
||||
AxisCamera::ExposureControl exposureControl) {
|
||||
std::lock_guard<priority_mutex> lock(m_parametersMutex);
|
||||
|
||||
if (m_exposureControl != exposureControl) {
|
||||
m_exposureControl = exposureControl;
|
||||
m_parametersDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured exposure control mode of the camera
|
||||
*/
|
||||
AxisCamera::ExposureControl AxisCamera::GetExposureControl() {
|
||||
std::lock_guard<priority_mutex> lock(m_parametersMutex);
|
||||
return m_exposureControl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a change in the exposure priority of the camera.
|
||||
*
|
||||
* @param exposurePriority Valid values are 0, 50, 100.
|
||||
* 0 = Prioritize image quality
|
||||
* 50 = None
|
||||
* 100 = Prioritize frame rate
|
||||
*/
|
||||
void AxisCamera::WriteExposurePriority(int exposurePriority) {
|
||||
if (exposurePriority != 0 && exposurePriority != 50 &&
|
||||
exposurePriority != 100) {
|
||||
wpi_setWPIErrorWithContext(ParameterOutOfRange,
|
||||
"Exposure priority must be from 0, 50, or 100");
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<priority_mutex> lock(m_parametersMutex);
|
||||
|
||||
if (m_exposurePriority != exposurePriority) {
|
||||
m_exposurePriority = exposurePriority;
|
||||
m_parametersDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured exposure priority of the camera
|
||||
*/
|
||||
int AxisCamera::GetExposurePriority() {
|
||||
std::lock_guard<priority_mutex> lock(m_parametersMutex);
|
||||
return m_exposurePriority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the maximum frames per second that the camera should send
|
||||
* Write 0 to send as many as possible.
|
||||
*
|
||||
* @param maxFPS The number of frames the camera should send in a second,
|
||||
* exposure permitting.
|
||||
*/
|
||||
void AxisCamera::WriteMaxFPS(int maxFPS) {
|
||||
std::lock_guard<priority_mutex> lock(m_parametersMutex);
|
||||
|
||||
if (m_maxFPS != maxFPS) {
|
||||
m_maxFPS = maxFPS;
|
||||
m_parametersDirty = true;
|
||||
m_streamDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured maximum FPS of the camera
|
||||
*/
|
||||
int AxisCamera::GetMaxFPS() {
|
||||
std::lock_guard<priority_mutex> lock(m_parametersMutex);
|
||||
return m_maxFPS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write resolution value to camera.
|
||||
*
|
||||
* @param resolution The camera resolution value to write to the camera.
|
||||
*/
|
||||
void AxisCamera::WriteResolution(AxisCamera::Resolution resolution) {
|
||||
std::lock_guard<priority_mutex> lock(m_parametersMutex);
|
||||
|
||||
if (m_resolution != resolution) {
|
||||
m_resolution = resolution;
|
||||
m_parametersDirty = true;
|
||||
m_streamDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured resolution of the camera (not necessarily the same
|
||||
* resolution as the most recent image, if it was changed recently.)
|
||||
*/
|
||||
AxisCamera::Resolution AxisCamera::GetResolution() {
|
||||
std::lock_guard<priority_mutex> lock(m_parametersMutex);
|
||||
return m_resolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the rotation value to the camera.
|
||||
*
|
||||
* If you mount your camera upside down, use this to adjust the image for you.
|
||||
*
|
||||
* @param rotation The angle to rotate the camera
|
||||
* (<code>AxisCamera::Rotation::k0</code>
|
||||
* or <code>AxisCamera::Rotation::k180</code>)
|
||||
*/
|
||||
void AxisCamera::WriteRotation(AxisCamera::Rotation rotation) {
|
||||
std::lock_guard<priority_mutex> lock(m_parametersMutex);
|
||||
|
||||
if (m_rotation != rotation) {
|
||||
m_rotation = rotation;
|
||||
m_parametersDirty = true;
|
||||
m_streamDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured rotation mode of the camera
|
||||
*/
|
||||
AxisCamera::Rotation AxisCamera::GetRotation() {
|
||||
std::lock_guard<priority_mutex> lock(m_parametersMutex);
|
||||
return m_rotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the compression value to the camera.
|
||||
*
|
||||
* @param compression Values between 0 and 100.
|
||||
*/
|
||||
void AxisCamera::WriteCompression(int compression) {
|
||||
if (compression < 0 || compression > 100) {
|
||||
wpi_setWPIErrorWithContext(ParameterOutOfRange,
|
||||
"Compression must be from 0 to 100");
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<priority_mutex> lock(m_parametersMutex);
|
||||
|
||||
if (m_compression != compression) {
|
||||
m_compression = compression;
|
||||
m_parametersDirty = true;
|
||||
m_streamDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured compression level of the camera
|
||||
*/
|
||||
int AxisCamera::GetCompression() {
|
||||
std::lock_guard<priority_mutex> lock(m_parametersMutex);
|
||||
return m_compression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called in the capture thread to receive images from the camera
|
||||
*/
|
||||
void AxisCamera::Capture() {
|
||||
int consecutiveErrors = 0;
|
||||
|
||||
// Loop on trying to setup the camera connection. This happens in a background
|
||||
// thread so it shouldn't effect the operation of user programs.
|
||||
while (!m_done) {
|
||||
std::string requestString =
|
||||
"GET /mjpg/video.mjpg HTTP/1.1\n"
|
||||
"User-Agent: HTTPStreamClient\n"
|
||||
"Connection: Keep-Alive\n"
|
||||
"Cache-Control: no-cache\n"
|
||||
"Authorization: Basic RlJDOkZSQw==\n\n";
|
||||
m_captureMutex.lock();
|
||||
m_cameraSocket = CreateCameraSocket(requestString, consecutiveErrors > 5);
|
||||
if (m_cameraSocket != -1) {
|
||||
ReadImagesFromCamera();
|
||||
consecutiveErrors = 0;
|
||||
} else {
|
||||
consecutiveErrors++;
|
||||
}
|
||||
m_captureMutex.unlock();
|
||||
Wait(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function actually reads the images from the camera.
|
||||
*/
|
||||
void AxisCamera::ReadImagesFromCamera() {
|
||||
char* imgBuffer = nullptr;
|
||||
int imgBufferLength = 0;
|
||||
|
||||
// TODO: these recv calls must be non-blocking. Otherwise if the camera
|
||||
// fails during a read, the code hangs and never retries when the camera comes
|
||||
// back up.
|
||||
|
||||
int counter = 2;
|
||||
while (!m_done) {
|
||||
char initialReadBuffer[kMaxPacketSize] = "";
|
||||
char intermediateBuffer[1];
|
||||
char* trailingPtr = initialReadBuffer;
|
||||
int trailingCounter = 0;
|
||||
while (counter) {
|
||||
// TODO: fix me... this cannot be the most efficient way to approach this,
|
||||
// reading one byte at a time.
|
||||
if (recv(m_cameraSocket, intermediateBuffer, 1, 0) == -1) {
|
||||
wpi_setErrnoErrorWithContext("Failed to read image header");
|
||||
close(m_cameraSocket);
|
||||
return;
|
||||
}
|
||||
std::strncat(initialReadBuffer, intermediateBuffer, 1);
|
||||
// trailingCounter ensures that we start looking for the 4 byte string
|
||||
// after
|
||||
// there is at least 4 bytes total. Kind of obscure.
|
||||
// look for 2 blank lines (\r\n)
|
||||
if (nullptr != std::strstr(trailingPtr, "\r\n\r\n")) {
|
||||
--counter;
|
||||
}
|
||||
if (++trailingCounter >= 4) {
|
||||
trailingPtr++;
|
||||
}
|
||||
}
|
||||
counter = 1;
|
||||
char* contentLength = std::strstr(initialReadBuffer, "Content-Length: ");
|
||||
if (contentLength == nullptr) {
|
||||
wpi_setWPIErrorWithContext(IncompatibleMode,
|
||||
"No content-length token found in packet");
|
||||
close(m_cameraSocket);
|
||||
if (imgBuffer) delete[] imgBuffer;
|
||||
return;
|
||||
}
|
||||
contentLength = contentLength + 16; // skip past "content length"
|
||||
int readLength = std::atol(contentLength); // get the image byte count
|
||||
|
||||
// Make sure buffer is large enough
|
||||
if (imgBufferLength < readLength) {
|
||||
if (imgBuffer) delete[] imgBuffer;
|
||||
imgBufferLength = readLength + kImageBufferAllocationIncrement;
|
||||
imgBuffer = new char[imgBufferLength];
|
||||
if (imgBuffer == nullptr) {
|
||||
imgBufferLength = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the image data for "Content-Length" bytes
|
||||
int bytesRead = 0;
|
||||
int remaining = readLength;
|
||||
while (bytesRead < readLength) {
|
||||
int bytesThisRecv =
|
||||
recv(m_cameraSocket, &imgBuffer[bytesRead], remaining, 0);
|
||||
bytesRead += bytesThisRecv;
|
||||
remaining -= bytesThisRecv;
|
||||
}
|
||||
|
||||
// Update image
|
||||
{
|
||||
std::lock_guard<priority_mutex> lock(m_imageDataMutex);
|
||||
|
||||
m_imageData.assign(imgBuffer, imgBuffer + imgBufferLength);
|
||||
m_freshImage = true;
|
||||
}
|
||||
|
||||
if (WriteParameters()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
close(m_cameraSocket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a request to the camera to set all of the parameters. This is called
|
||||
* in the capture thread between each frame. This strategy avoids making lots
|
||||
* of redundant HTTP requests, accounts for failed initial requests, and
|
||||
* avoids blocking calls in the main thread unless necessary.
|
||||
*
|
||||
* This method does nothing if no parameters have been modified since it last
|
||||
* completely successfully.
|
||||
*
|
||||
* @return <code>true</code> if the stream should be restarted due to a
|
||||
* parameter changing.
|
||||
*/
|
||||
bool AxisCamera::WriteParameters() {
|
||||
if (m_parametersDirty) {
|
||||
std::stringstream request;
|
||||
request << "GET /axis-cgi/admin/param.cgi?action=update";
|
||||
|
||||
m_parametersMutex.lock();
|
||||
request << "&ImageSource.I0.Sensor.Brightness=" << m_brightness;
|
||||
request << "&ImageSource.I0.Sensor.WhiteBalance="
|
||||
<< kWhiteBalanceStrings[m_whiteBalance];
|
||||
request << "&ImageSource.I0.Sensor.ColorLevel=" << m_colorLevel;
|
||||
request << "&ImageSource.I0.Sensor.Exposure="
|
||||
<< kExposureControlStrings[m_exposureControl];
|
||||
request << "&ImageSource.I0.Sensor.ExposurePriority=" << m_exposurePriority;
|
||||
request << "&Image.I0.Stream.FPS=" << m_maxFPS;
|
||||
request << "&Image.I0.Appearance.Resolution="
|
||||
<< kResolutionStrings[m_resolution];
|
||||
request << "&Image.I0.Appearance.Compression=" << m_compression;
|
||||
request << "&Image.I0.Appearance.Rotation=" << kRotationStrings[m_rotation];
|
||||
m_parametersMutex.unlock();
|
||||
|
||||
request << " HTTP/1.1" << std::endl;
|
||||
request << "User-Agent: HTTPStreamClient" << std::endl;
|
||||
request << "Connection: Keep-Alive" << std::endl;
|
||||
request << "Cache-Control: no-cache" << std::endl;
|
||||
request << "Authorization: Basic RlJDOkZSQw==" << std::endl;
|
||||
request << std::endl;
|
||||
|
||||
int socket = CreateCameraSocket(request.str(), false);
|
||||
if (socket == -1) {
|
||||
wpi_setErrnoErrorWithContext("Error setting camera parameters");
|
||||
} else {
|
||||
close(socket);
|
||||
m_parametersDirty = false;
|
||||
|
||||
if (m_streamDirty) {
|
||||
m_streamDirty = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a socket connected to camera.
|
||||
*
|
||||
* Used to create a connection to the camera for both capturing images and
|
||||
* setting parameters.
|
||||
*
|
||||
* @param requestString The initial request string to send upon successful
|
||||
* connection.
|
||||
* @param setError If true, rais an error if there's a problem creating the
|
||||
* connection. This is only enabled after several
|
||||
* unsucessful connections, so a single one doesn't cause
|
||||
* an error message to be printed if it immediately
|
||||
* recovers.
|
||||
* @return -1 if failed, socket handle if successful.
|
||||
*/
|
||||
int AxisCamera::CreateCameraSocket(std::string const& requestString,
|
||||
bool setError) {
|
||||
struct addrinfo* address = nullptr;
|
||||
int camSocket;
|
||||
|
||||
/* create socket */
|
||||
if ((camSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
|
||||
if (setError)
|
||||
wpi_setErrnoErrorWithContext("Failed to create the camera socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (getaddrinfo(m_cameraHost.c_str(), "80", nullptr, &address) == -1) {
|
||||
if (setError) {
|
||||
wpi_setErrnoErrorWithContext("Failed to create the camera socket");
|
||||
close(camSocket);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* connect to server */
|
||||
if (connect(camSocket, address->ai_addr, address->ai_addrlen) == -1) {
|
||||
if (setError)
|
||||
wpi_setErrnoErrorWithContext("Failed to connect to the camera");
|
||||
freeaddrinfo(address);
|
||||
close(camSocket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
freeaddrinfo(address);
|
||||
|
||||
int sent = send(camSocket, requestString.c_str(), requestString.size(), 0);
|
||||
if (sent == -1) {
|
||||
if (setError)
|
||||
wpi_setErrnoErrorWithContext("Failed to send a request to the camera");
|
||||
close(camSocket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return camSocket;
|
||||
}
|
||||
@@ -1,384 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "Vision/BaeUtilities.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
#include "Servo.h"
|
||||
#include "Timer.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
/** @file
|
||||
* Utility functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* debug output flag options:
|
||||
* DEBUG_OFF, DEBUG_MOSTLY_OFF, DEBUG_SCREEN_ONLY, DEBUG_FILE_ONLY,
|
||||
* DEBUG_SCREEN_AND_FILE
|
||||
*/
|
||||
static DebugOutputType dprintfFlag = DEBUG_OFF;
|
||||
|
||||
/**
|
||||
* Set the debug flag to print to screen, file on cRIO, both or neither.
|
||||
*
|
||||
* @param tempString The format string.
|
||||
*/
|
||||
void SetDebugFlag(DebugOutputType flag) { dprintfFlag = flag; }
|
||||
|
||||
/**
|
||||
* Debug print to a file and/or a terminal window.
|
||||
*
|
||||
* Call like you would call printf.
|
||||
* Set functionName in the function if you want the correct function name to
|
||||
* print out.
|
||||
* The file line number will also be printed.
|
||||
*
|
||||
* @param tempString The format string.
|
||||
*/
|
||||
void dprintf(const char* tempString, ...) {
|
||||
va_list args; /* Input argument list */
|
||||
int line_number; /* Line number passed in argument */
|
||||
int type;
|
||||
const char* functionName; /* Format passed in argument */
|
||||
const char* fmt; /* Format passed in argument */
|
||||
char text[512]; /* Text string */
|
||||
std::FILE* outfile_fd; /* Output file pointer */
|
||||
char filepath[128]; /* Text string */
|
||||
int fatalFlag = 0;
|
||||
const char* filename;
|
||||
int index;
|
||||
int tempStringLen;
|
||||
|
||||
if (dprintfFlag == DEBUG_OFF) {
|
||||
return;
|
||||
}
|
||||
|
||||
va_start(args, tempString);
|
||||
|
||||
tempStringLen = std::strlen(tempString);
|
||||
filename = tempString;
|
||||
for (index = 0; index < tempStringLen; index++) {
|
||||
if (tempString[index] == ' ') {
|
||||
std::printf("ERROR in dprintf: malformed calling sequence (%s)\n",
|
||||
tempString);
|
||||
va_end(args);
|
||||
return;
|
||||
}
|
||||
if (tempString[index] == '\\' || tempString[index] == '/')
|
||||
filename = tempString + index + 1;
|
||||
}
|
||||
|
||||
/* Extract function name */
|
||||
functionName = va_arg(args, const char*);
|
||||
|
||||
/* Extract line number from argument list */
|
||||
line_number = va_arg(args, int);
|
||||
|
||||
/* Extract information type from argument list */
|
||||
type = va_arg(args, int);
|
||||
|
||||
/* Extract format from argument list */
|
||||
fmt = va_arg(args, const char*);
|
||||
|
||||
std::vsprintf(text, fmt, args);
|
||||
|
||||
va_end(args);
|
||||
|
||||
/* Format output statement */
|
||||
std::stringstream ss;
|
||||
ss << std::setfill('0') << std::setw(4);
|
||||
ss << "[" << filename << ":" << functionName << "@" << line_number << "] ";
|
||||
switch (type) {
|
||||
case DEBUG_TYPE:
|
||||
ss << "DEBUG";
|
||||
break;
|
||||
case INFO_TYPE:
|
||||
ss << "INFO";
|
||||
break;
|
||||
case ERROR_TYPE:
|
||||
ss << "ERROR";
|
||||
break;
|
||||
case CRITICAL_TYPE:
|
||||
ss << "CRITICAL";
|
||||
break;
|
||||
case FATAL_TYPE:
|
||||
fatalFlag = 1;
|
||||
ss << "FATAL";
|
||||
break;
|
||||
default:
|
||||
std::printf("ERROR in dprintf: malformed calling sequence\n");
|
||||
return;
|
||||
break;
|
||||
}
|
||||
ss << " " << text << "\n";
|
||||
|
||||
std::snprintf(filepath, sizeof(filepath), "%s.debug", filename);
|
||||
|
||||
/* Write output statement */
|
||||
switch (dprintfFlag) {
|
||||
default:
|
||||
case DEBUG_OFF:
|
||||
break;
|
||||
case DEBUG_MOSTLY_OFF:
|
||||
if (fatalFlag) {
|
||||
if ((outfile_fd = std::fopen(filepath, "a+")) != nullptr) {
|
||||
std::fwrite(ss.str().c_str(), sizeof(char), ss.str().length(),
|
||||
outfile_fd);
|
||||
std::fclose(outfile_fd);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DEBUG_SCREEN_ONLY:
|
||||
std::printf("%s", ss.str().c_str());
|
||||
break;
|
||||
case DEBUG_FILE_ONLY:
|
||||
if ((outfile_fd = std::fopen(filepath, "a+")) != nullptr) {
|
||||
std::fwrite(ss.str().c_str(), sizeof(char), ss.str().length(),
|
||||
outfile_fd);
|
||||
std::fclose(outfile_fd);
|
||||
}
|
||||
break;
|
||||
case DEBUG_SCREEN_AND_FILE: // BOTH
|
||||
std::printf("%s", ss.str().c_str());
|
||||
if ((outfile_fd = std::fopen(filepath, "a+")) != nullptr) {
|
||||
std::fwrite(ss.str().c_str(), sizeof(char), ss.str().length(),
|
||||
outfile_fd);
|
||||
std::fclose(outfile_fd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Normalizes a value in a range, used for drive input.
|
||||
* @param position The position in the range, starting at 0
|
||||
* @param range The size of the range that position is in
|
||||
* @return The normalized position from -1 to +1
|
||||
*/
|
||||
double RangeToNormalized(double position, int range) {
|
||||
return position * 2.0 / static_cast<double>(range) - 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a normalized value to the corresponding value in a range.
|
||||
* This is used to convert normalized values to the servo command range.
|
||||
* @param normalizedValue The normalized value (in the -1 to +1 range)
|
||||
* @param minRange The minimum of the range (0 is default)
|
||||
* @param maxRange The maximum of the range (1 is default)
|
||||
* @return The value in the range corresponding to the input normalized value
|
||||
*/
|
||||
float NormalizeToRange(float normalizedValue, float minRange, float maxRange) {
|
||||
float range = maxRange - minRange;
|
||||
float temp = static_cast<float>(normalizedValue / 2.0 + 0.5) * range;
|
||||
return (temp + minRange);
|
||||
}
|
||||
float NormalizeToRange(float normalizedValue) {
|
||||
return static_cast<float>(normalizedValue / 2.0 + 0.5);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Displays an activity indicator to console.
|
||||
* Call this function like you would call std::printf.
|
||||
* @param fmt The format string
|
||||
*/
|
||||
void ShowActivity(char* fmt, ...) {
|
||||
static char activity_indication_string[] = "|/-\\";
|
||||
static int ai = 3;
|
||||
va_list args;
|
||||
char text[1024];
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
std::vsprintf(text, fmt, args);
|
||||
|
||||
ai = ai == 3 ? 0 : ai + 1;
|
||||
|
||||
std::printf("%c %s \r", activity_indication_string[ai], text);
|
||||
std::fflush(stdout);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
#define PI 3.14159265358979
|
||||
/**
|
||||
* @brief Calculate sine wave increments (-1.0 to 1.0).
|
||||
* The first time this is called, it sets up the time increment. Subsequent
|
||||
* calls will give values along the sine wave depending on current time. If
|
||||
* the wave is stopped and restarted, it must be reinitialized with a new
|
||||
* "first call".
|
||||
*
|
||||
* @param period length of time to complete a complete wave
|
||||
* @param sinStart Where to start the sine wave (0.0 = 2 pi, pi/2 = 1.0, etc.)
|
||||
*/
|
||||
double SinPosition(double* period, double sinStart) {
|
||||
double rtnVal;
|
||||
static double sinePeriod = 0.0;
|
||||
static double timestamp;
|
||||
double sinArg;
|
||||
|
||||
// 1st call
|
||||
if (period != nullptr) {
|
||||
sinePeriod = *period;
|
||||
timestamp = GetTime();
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// Multiplying by 2*pi to the time difference makes sinePeriod work if it's
|
||||
// measured in seconds.
|
||||
// Adding sinStart to the part multiplied by PI, but not by 2, allows it to
|
||||
// work as described in the comments.
|
||||
sinArg = PI * ((2.0 * (GetTime() - timestamp)) + sinStart) / sinePeriod;
|
||||
rtnVal = std::sin(sinArg);
|
||||
return (rtnVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find the elapsed time since a specified time.
|
||||
* @param startTime The starting time
|
||||
* @return How long it has been since the starting time
|
||||
*/
|
||||
double ElapsedTime(double startTime) {
|
||||
double realTime = GetTime();
|
||||
return (realTime - startTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize pan parameters
|
||||
* @param period The number of seconds to complete one pan
|
||||
*/
|
||||
void panInit() {
|
||||
double period = 3.0; // number of seconds for one complete pan
|
||||
SinPosition(&period, 0.0); // initial call to set up time
|
||||
}
|
||||
|
||||
void panInit(double period) {
|
||||
if (period < 0.0) period = 3.0;
|
||||
SinPosition(&period, 0.0); // initial call to set up time
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move the horizontal servo back and forth.
|
||||
* @param panServo The servo object to move
|
||||
* @param sinStart The position on the sine wave to begin the pan
|
||||
*/
|
||||
void panForTarget(Servo* panServo) { panForTarget(panServo, 0.0); }
|
||||
|
||||
void panForTarget(Servo* panServo, double sinStart) {
|
||||
float normalizedSinPosition =
|
||||
static_cast<float>(SinPosition(nullptr, sinStart));
|
||||
float newServoPosition = NormalizeToRange(normalizedSinPosition);
|
||||
panServo->Set(newServoPosition);
|
||||
// ShowActivity ("pan x: normalized %f newServoPosition = %f" ,
|
||||
// normalizedSinPosition, newServoPosition );
|
||||
}
|
||||
|
||||
/** @brief Read a file and return non-comment output string
|
||||
*
|
||||
* Call the first time with 0 lineNumber to get the number of lines to read
|
||||
* Then call with each lineNumber to get one camera parameter. There should
|
||||
* be one property=value entry on each line, i.e. "exposure=auto"
|
||||
*
|
||||
* @param inputFile filename to read
|
||||
* @param outputString one string
|
||||
* @param lineNumber if 0, return number of lines; else return that line
|
||||
* number
|
||||
* @return int number of lines or -1 if error
|
||||
**/
|
||||
int processFile(char* inputFile, char* outputString, int lineNumber) {
|
||||
std::FILE* infile;
|
||||
const int kStringSize = 80; // max size of one line in file
|
||||
char inputStr[kStringSize];
|
||||
inputStr[0] = '\0';
|
||||
int lineCount = 0;
|
||||
|
||||
if (lineNumber < 0) return (-1);
|
||||
|
||||
if ((infile = std::fopen(inputFile, "r")) == nullptr) {
|
||||
std::printf("Fatal error opening file %s\n", inputFile);
|
||||
return (0);
|
||||
}
|
||||
|
||||
while (!std::feof(infile)) {
|
||||
if (std::fgets(inputStr, kStringSize, infile) != nullptr) {
|
||||
// Skip empty lines
|
||||
if (emptyString(inputStr)) continue;
|
||||
// Skip comment lines
|
||||
if (inputStr[0] == '#' || inputStr[0] == '!') continue;
|
||||
|
||||
lineCount++;
|
||||
if (lineNumber == 0) {
|
||||
continue;
|
||||
} else {
|
||||
if (lineCount == lineNumber) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// close file
|
||||
std::fclose(infile);
|
||||
// if number lines requested return the count
|
||||
if (lineNumber == 0) return (lineCount);
|
||||
// check for input out of range
|
||||
if (lineNumber > lineCount) return (-1);
|
||||
// return the line selected; lineCount guaranteed to be greater than zero
|
||||
stripString(inputStr);
|
||||
std::strncpy(outputString, inputStr, kStringSize);
|
||||
return (lineCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ignore empty string.
|
||||
* @param string to check if empty
|
||||
**/
|
||||
int emptyString(char* string) {
|
||||
int i, len;
|
||||
|
||||
if (string == nullptr) return (1);
|
||||
|
||||
len = std::strlen(string);
|
||||
for (i = 0; i < len; i++) {
|
||||
// Ignore the following characters
|
||||
if (string[i] == '\n' || string[i] == '\r' || string[i] == '\t' ||
|
||||
string[i] == ' ')
|
||||
continue;
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove special characters from string.
|
||||
* @param string to process
|
||||
**/
|
||||
void stripString(char* string) {
|
||||
int i, j, len;
|
||||
|
||||
if (string == nullptr) return;
|
||||
|
||||
len = std::strlen(string);
|
||||
for (i = 0, j = 0; i < len; i++) {
|
||||
// Remove the following characters from the string
|
||||
if (string[i] == '\n' || string[i] == '\r' || string[i] == '\"') continue;
|
||||
// Copy anything else
|
||||
string[j++] = string[i];
|
||||
}
|
||||
string[j] = '\0';
|
||||
}
|
||||
|
||||
} // namespace frc
|
||||
@@ -1,244 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "Vision/BinaryImage.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
/**
|
||||
* Get then number of particles for the image.
|
||||
*
|
||||
* @return the number of particles found for the image.
|
||||
*/
|
||||
int BinaryImage::GetNumberParticles() {
|
||||
int numParticles = 0;
|
||||
int success = imaqCountParticles(m_imaqImage, 1, &numParticles);
|
||||
wpi_setImaqErrorWithContext(success, "Error counting particles");
|
||||
return numParticles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single particle analysis report.
|
||||
*
|
||||
* Get one (of possibly many) particle analysis reports for an image.
|
||||
*
|
||||
* @param particleNumber Which particle analysis report to return.
|
||||
* @return the selected particle analysis report
|
||||
*/
|
||||
ParticleAnalysisReport BinaryImage::GetParticleAnalysisReport(
|
||||
int particleNumber) {
|
||||
ParticleAnalysisReport par;
|
||||
GetParticleAnalysisReport(particleNumber, &par);
|
||||
return par;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single particle analysis report.
|
||||
*
|
||||
* Get one (of possibly many) particle analysis reports for an image.
|
||||
* This version could be more efficient when copying many reports.
|
||||
*
|
||||
* @param particleNumber Which particle analysis report to return.
|
||||
* @param par the selected particle analysis report
|
||||
*/
|
||||
void BinaryImage::GetParticleAnalysisReport(int particleNumber,
|
||||
ParticleAnalysisReport* par) {
|
||||
int success;
|
||||
int numParticles = 0;
|
||||
|
||||
success = imaqGetImageSize(m_imaqImage, &par->imageWidth, &par->imageHeight);
|
||||
wpi_setImaqErrorWithContext(success, "Error getting image size");
|
||||
if (StatusIsFatal()) return;
|
||||
|
||||
success = imaqCountParticles(m_imaqImage, 1, &numParticles);
|
||||
wpi_setImaqErrorWithContext(success, "Error counting particles");
|
||||
if (StatusIsFatal()) return;
|
||||
|
||||
if (particleNumber >= numParticles) {
|
||||
wpi_setWPIErrorWithContext(ParameterOutOfRange, "particleNumber");
|
||||
return;
|
||||
}
|
||||
|
||||
par->particleIndex = particleNumber;
|
||||
// Don't bother measuring the rest of the particle if one fails
|
||||
bool good = ParticleMeasurement(particleNumber, IMAQ_MT_CENTER_OF_MASS_X,
|
||||
&par->center_mass_x);
|
||||
good = good && ParticleMeasurement(particleNumber, IMAQ_MT_CENTER_OF_MASS_Y,
|
||||
&par->center_mass_y);
|
||||
good = good &&
|
||||
ParticleMeasurement(particleNumber, IMAQ_MT_AREA, &par->particleArea);
|
||||
good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_TOP,
|
||||
&par->boundingRect.top);
|
||||
good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_LEFT,
|
||||
&par->boundingRect.left);
|
||||
good =
|
||||
good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_HEIGHT,
|
||||
&par->boundingRect.height);
|
||||
good =
|
||||
good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_WIDTH,
|
||||
&par->boundingRect.width);
|
||||
good = good && ParticleMeasurement(particleNumber, IMAQ_MT_AREA_BY_IMAGE_AREA,
|
||||
&par->particleToImagePercent);
|
||||
good = good && ParticleMeasurement(particleNumber,
|
||||
IMAQ_MT_AREA_BY_PARTICLE_AND_HOLES_AREA,
|
||||
&par->particleQuality);
|
||||
|
||||
if (good) {
|
||||
/* normalized position (-1 to 1) */
|
||||
par->center_mass_x_normalized =
|
||||
NormalizeFromRange(par->center_mass_x, par->imageWidth);
|
||||
par->center_mass_y_normalized =
|
||||
NormalizeFromRange(par->center_mass_y, par->imageHeight);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an ordered vector of particles for the image.
|
||||
*
|
||||
* Create a vector of particle analysis reports sorted by size for an image.
|
||||
* The vector contains the actual report structures.
|
||||
*
|
||||
* @return a pointer to the vector of particle analysis reports. The caller
|
||||
* must delete the vector when finished using it.
|
||||
*/
|
||||
std::vector<ParticleAnalysisReport>*
|
||||
BinaryImage::GetOrderedParticleAnalysisReports() {
|
||||
auto particles = new std::vector<ParticleAnalysisReport>;
|
||||
int particleCount = GetNumberParticles();
|
||||
for (int particleIndex = 0; particleIndex < particleCount; particleIndex++) {
|
||||
particles->push_back(GetParticleAnalysisReport(particleIndex));
|
||||
}
|
||||
// TODO: This is pretty inefficient since each compare in the sort copies
|
||||
// both reports being compared... do it manually instead... while we're
|
||||
// at it, we should provide a version that allows a preallocated buffer of
|
||||
// ParticleAnalysisReport structures
|
||||
std::sort(particles->begin(), particles->end(), CompareParticleSizes);
|
||||
return particles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a binary image to flash.
|
||||
*
|
||||
* Writes the binary image to flash on the cRIO for later inspection.
|
||||
*
|
||||
* @param fileName the name of the image file written to the flash.
|
||||
*/
|
||||
void BinaryImage::Write(const char* fileName) {
|
||||
RGBValue colorTable[256];
|
||||
std::memset(colorTable, 0, sizeof(colorTable));
|
||||
colorTable[0].R = 0;
|
||||
colorTable[1].R = 255;
|
||||
colorTable[0].G = colorTable[1].G = 0;
|
||||
colorTable[0].B = colorTable[1].B = 0;
|
||||
colorTable[0].alpha = colorTable[1].alpha = 0;
|
||||
imaqWriteFile(m_imaqImage, fileName, colorTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Measure a single parameter for an image.
|
||||
*
|
||||
* Get the measurement for a single parameter about an image by calling the
|
||||
* imaqMeasureParticle function for the selected parameter.
|
||||
*
|
||||
* @param particleNumber which particle in the set of particles
|
||||
* @param whatToMeasure the imaq MeasurementType (what to measure)
|
||||
* @param result the value of the measurement
|
||||
* @return false on failure, true on success
|
||||
*/
|
||||
bool BinaryImage::ParticleMeasurement(int particleNumber,
|
||||
MeasurementType whatToMeasure,
|
||||
int* result) {
|
||||
double resultDouble;
|
||||
bool success =
|
||||
ParticleMeasurement(particleNumber, whatToMeasure, &resultDouble);
|
||||
*result = static_cast<int>(resultDouble);
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Measure a single parameter for an image.
|
||||
*
|
||||
* Get the measurement for a single parameter about an image by calling the
|
||||
* imaqMeasureParticle function for the selected parameter.
|
||||
*
|
||||
* @param particleNumber which particle in the set of particles
|
||||
* @param whatToMeasure the imaq MeasurementType (what to measure)
|
||||
* @param result the value of the measurement
|
||||
* @returns true on failure, false on success
|
||||
*/
|
||||
bool BinaryImage::ParticleMeasurement(int particleNumber,
|
||||
MeasurementType whatToMeasure,
|
||||
double* result) {
|
||||
int success;
|
||||
success = imaqMeasureParticle(m_imaqImage, particleNumber, 0, whatToMeasure,
|
||||
result);
|
||||
wpi_setImaqErrorWithContext(success, "Error measuring particle");
|
||||
return !StatusIsFatal();
|
||||
}
|
||||
|
||||
// Normalizes to [-1,1]
|
||||
double BinaryImage::NormalizeFromRange(double position, int range) {
|
||||
return position * 2.0 / static_cast<double>(range) - 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The compare helper function for sort.
|
||||
*
|
||||
* This function compares two particle analysis reports as a helper for the sort
|
||||
* function.
|
||||
*
|
||||
* @param particle1 The first particle to compare
|
||||
* @param particle2 the second particle to compare
|
||||
* @returns true if particle1 is greater than particle2
|
||||
*/
|
||||
bool BinaryImage::CompareParticleSizes(ParticleAnalysisReport particle1,
|
||||
ParticleAnalysisReport particle2) {
|
||||
// we want descending sort order
|
||||
return particle1.particleToImagePercent > particle2.particleToImagePercent;
|
||||
}
|
||||
|
||||
BinaryImage* BinaryImage::RemoveSmallObjects(bool connectivity8, int erosions) {
|
||||
auto result = new BinaryImage();
|
||||
int success =
|
||||
imaqSizeFilter(result->GetImaqImage(), m_imaqImage, connectivity8,
|
||||
erosions, IMAQ_KEEP_LARGE, nullptr);
|
||||
wpi_setImaqErrorWithContext(success, "Error in RemoveSmallObjects");
|
||||
return result;
|
||||
}
|
||||
|
||||
BinaryImage* BinaryImage::RemoveLargeObjects(bool connectivity8, int erosions) {
|
||||
auto result = new BinaryImage();
|
||||
int success =
|
||||
imaqSizeFilter(result->GetImaqImage(), m_imaqImage, connectivity8,
|
||||
erosions, IMAQ_KEEP_SMALL, nullptr);
|
||||
wpi_setImaqErrorWithContext(success, "Error in RemoveLargeObjects");
|
||||
return result;
|
||||
}
|
||||
|
||||
BinaryImage* BinaryImage::ConvexHull(bool connectivity8) {
|
||||
auto result = new BinaryImage();
|
||||
int success =
|
||||
imaqConvexHull(result->GetImaqImage(), m_imaqImage, connectivity8);
|
||||
wpi_setImaqErrorWithContext(success, "Error in convex hull operation");
|
||||
return result;
|
||||
}
|
||||
|
||||
BinaryImage* BinaryImage::ParticleFilter(ParticleFilterCriteria2* criteria,
|
||||
int criteriaCount) {
|
||||
auto result = new BinaryImage();
|
||||
int numParticles;
|
||||
ParticleFilterOptions2 filterOptions = {0, 0, 0, 1};
|
||||
int success = imaqParticleFilter4(result->GetImaqImage(), m_imaqImage,
|
||||
criteria, criteriaCount, &filterOptions,
|
||||
nullptr, &numParticles);
|
||||
wpi_setImaqErrorWithContext(success, "Error in particle filter operation");
|
||||
return result;
|
||||
}
|
||||
@@ -1,488 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "Vision/ColorImage.h"
|
||||
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
ColorImage::ColorImage(ImageType type) : ImageBase(type) {}
|
||||
|
||||
/**
|
||||
* Perform a threshold operation on a ColorImage.
|
||||
*
|
||||
* Perform a threshold operation on a ColorImage using the ColorMode supplied
|
||||
* as a parameter.
|
||||
*
|
||||
* @param colorMode The type of colorspace this operation should be performed in
|
||||
* @return a pointer to a binary image
|
||||
*/
|
||||
BinaryImage* ColorImage::ComputeThreshold(ColorMode colorMode, int low1,
|
||||
int high1, int low2, int high2,
|
||||
int low3, int high3) {
|
||||
auto result = new BinaryImage();
|
||||
Range range1 = {low1, high1}, range2 = {low2, high2}, range3 = {low3, high3};
|
||||
|
||||
int success = imaqColorThreshold(result->GetImaqImage(), m_imaqImage, 1,
|
||||
colorMode, &range1, &range2, &range3);
|
||||
wpi_setImaqErrorWithContext(success, "ImaqThreshold error");
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a threshold in RGB space.
|
||||
*
|
||||
* @param redLow Red low value
|
||||
* @param redHigh Red high value
|
||||
* @param greenLow Green low value
|
||||
* @param greenHigh Green high value
|
||||
* @param blueLow Blue low value
|
||||
* @param blueHigh Blue high value
|
||||
* @return A pointer to a BinaryImage that represents the result of the
|
||||
* threshold operation.
|
||||
*/
|
||||
BinaryImage* ColorImage::ThresholdRGB(int redLow, int redHigh, int greenLow,
|
||||
int greenHigh, int blueLow,
|
||||
int blueHigh) {
|
||||
return ComputeThreshold(IMAQ_RGB, redLow, redHigh, greenLow, greenHigh,
|
||||
blueLow, blueHigh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a threshold in RGB space.
|
||||
*
|
||||
* @param threshold a reference to the Threshold object to use.
|
||||
* @return A pointer to a BinaryImage that represents the result of the
|
||||
* threshold operation.
|
||||
*/
|
||||
BinaryImage* ColorImage::ThresholdRGB(Threshold& t) {
|
||||
return ComputeThreshold(IMAQ_RGB, t.plane1Low, t.plane1High, t.plane2Low,
|
||||
t.plane2High, t.plane3Low, t.plane3High);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a threshold in HSL space.
|
||||
*
|
||||
* @param hueLow Low value for hue
|
||||
* @param hueHigh High value for hue
|
||||
* @param saturationLow Low value for saturation
|
||||
* @param saturationHigh High value for saturation
|
||||
* @param luminenceLow Low value for luminence
|
||||
* @param luminenceHigh High value for luminence
|
||||
* @return a pointer to a BinaryImage that represents the result of the
|
||||
* threshold operation.
|
||||
*/
|
||||
BinaryImage* ColorImage::ThresholdHSL(int hueLow, int hueHigh,
|
||||
int saturationLow, int saturationHigh,
|
||||
int luminenceLow, int luminenceHigh) {
|
||||
return ComputeThreshold(IMAQ_HSL, hueLow, hueHigh, saturationLow,
|
||||
saturationHigh, luminenceLow, luminenceHigh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a threshold in HSL space.
|
||||
*
|
||||
* @param threshold a reference to the Threshold object to use.
|
||||
* @return A pointer to a BinaryImage that represents the result of the
|
||||
* threshold operation.
|
||||
*/
|
||||
BinaryImage* ColorImage::ThresholdHSL(Threshold& t) {
|
||||
return ComputeThreshold(IMAQ_HSL, t.plane1Low, t.plane1High, t.plane2Low,
|
||||
t.plane2High, t.plane3Low, t.plane3High);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a threshold in HSV space.
|
||||
*
|
||||
* @param hueLow Low value for hue
|
||||
* @param hueHigh High value for hue
|
||||
* @param saturationLow Low value for saturation
|
||||
* @param saturationHigh High value for saturation
|
||||
* @param valueLow Low value
|
||||
* @param valueHigh High value
|
||||
* @return a pointer to a BinaryImage that represents the result of the
|
||||
* threshold operation.
|
||||
*/
|
||||
BinaryImage* ColorImage::ThresholdHSV(int hueLow, int hueHigh,
|
||||
int saturationLow, int saturationHigh,
|
||||
int valueLow, int valueHigh) {
|
||||
return ComputeThreshold(IMAQ_HSV, hueLow, hueHigh, saturationLow,
|
||||
saturationHigh, valueLow, valueHigh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a threshold in HSV space.
|
||||
*
|
||||
* @param threshold a reference to the Threshold object to use.
|
||||
* @return A pointer to a BinaryImage that represents the result of the
|
||||
* threshold operation.
|
||||
*/
|
||||
BinaryImage* ColorImage::ThresholdHSV(Threshold& t) {
|
||||
return ComputeThreshold(IMAQ_HSV, t.plane1Low, t.plane1High, t.plane2Low,
|
||||
t.plane2High, t.plane3Low, t.plane3High);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a threshold in HSI space.
|
||||
*
|
||||
* @param hueLow Low value for hue
|
||||
* @param hueHigh High value for hue
|
||||
* @param saturationLow Low value for saturation
|
||||
* @param saturationHigh High value for saturation
|
||||
* @param valueLow Low intensity
|
||||
* @param valueHigh High intensity
|
||||
* @return a pointer to a BinaryImage that represents the result of the
|
||||
* threshold operation.
|
||||
*/
|
||||
BinaryImage* ColorImage::ThresholdHSI(int hueLow, int hueHigh,
|
||||
int saturationLow, int saturationHigh,
|
||||
int intensityLow, int intensityHigh) {
|
||||
return ComputeThreshold(IMAQ_HSI, hueLow, hueHigh, saturationLow,
|
||||
saturationHigh, intensityLow, intensityHigh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a threshold in HSI space.
|
||||
*
|
||||
* @param threshold a reference to the Threshold object to use.
|
||||
* @return A pointer to a BinaryImage that represents the result of the
|
||||
* threshold operation.
|
||||
*/
|
||||
BinaryImage* ColorImage::ThresholdHSI(Threshold& t) {
|
||||
return ComputeThreshold(IMAQ_HSI, t.plane1Low, t.plane1High, t.plane2Low,
|
||||
t.plane2High, t.plane3Low, t.plane3High);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a color plane from the image.
|
||||
*
|
||||
* @param mode The ColorMode to use for the plane extraction
|
||||
* @param planeNumber Which plane is to be extracted
|
||||
* @return A pointer to a MonoImage that represents the extracted plane.
|
||||
*/
|
||||
MonoImage* ColorImage::ExtractColorPlane(ColorMode mode, int planeNumber) {
|
||||
auto result = new MonoImage();
|
||||
if (m_imaqImage == nullptr) wpi_setWPIError(NullParameter);
|
||||
int success = imaqExtractColorPlanes(
|
||||
m_imaqImage, mode, (planeNumber == 1) ? result->GetImaqImage() : nullptr,
|
||||
(planeNumber == 2) ? result->GetImaqImage() : nullptr,
|
||||
(planeNumber == 3) ? result->GetImaqImage() : nullptr);
|
||||
wpi_setImaqErrorWithContext(success, "Imaq ExtractColorPlanes failed");
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the first color plane for an image.
|
||||
*
|
||||
* @param mode The color mode in which to operate
|
||||
* @return a pointer to a MonoImage that is the extracted plane.
|
||||
*/
|
||||
MonoImage* ColorImage::ExtractFirstColorPlane(ColorMode mode) {
|
||||
return ExtractColorPlane(mode, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the second color plane for an image.
|
||||
*
|
||||
* @param mode The color mode in which to operate
|
||||
* @return a pointer to a MonoImage that is the extracted plane.
|
||||
*/
|
||||
MonoImage* ColorImage::ExtractSecondColorPlane(ColorMode mode) {
|
||||
return ExtractColorPlane(mode, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the third color plane for an image.
|
||||
*
|
||||
* @param mode The color mode in which to operate
|
||||
* @return a pointer to a MonoImage that is the extracted plane.
|
||||
*/
|
||||
MonoImage* ColorImage::ExtractThirdColorPlane(ColorMode mode) {
|
||||
return ExtractColorPlane(mode, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the red plane from an RGB image.
|
||||
*
|
||||
* @return a pointer to a MonoImage that is the extraced plane.
|
||||
*/
|
||||
MonoImage* ColorImage::GetRedPlane() {
|
||||
return ExtractFirstColorPlane(IMAQ_RGB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the green plane from an RGB image.
|
||||
*
|
||||
* @return a pointer to a MonoImage that is the extraced plane.
|
||||
*/
|
||||
MonoImage* ColorImage::GetGreenPlane() {
|
||||
return ExtractSecondColorPlane(IMAQ_RGB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the blue plane from an RGB image.
|
||||
*
|
||||
* @return a pointer to a MonoImage that is the extraced plane.
|
||||
*/
|
||||
MonoImage* ColorImage::GetBluePlane() {
|
||||
return ExtractThirdColorPlane(IMAQ_RGB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the Hue plane from an HSL image.
|
||||
*
|
||||
* @return a pointer to a MonoImage that is the extraced plane.
|
||||
*/
|
||||
MonoImage* ColorImage::GetHSLHuePlane() {
|
||||
return ExtractFirstColorPlane(IMAQ_HSL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the Hue plane from an HSV image.
|
||||
*
|
||||
* @return a pointer to a MonoImage that is the extraced plane.
|
||||
*/
|
||||
MonoImage* ColorImage::GetHSVHuePlane() {
|
||||
return ExtractFirstColorPlane(IMAQ_HSV);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the Hue plane from an HSI image.
|
||||
*
|
||||
* @return a pointer to a MonoImage that is the extraced plane.
|
||||
*/
|
||||
MonoImage* ColorImage::GetHSIHuePlane() {
|
||||
return ExtractFirstColorPlane(IMAQ_HSI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the Luminance plane from an HSL image.
|
||||
*
|
||||
* @return a pointer to a MonoImage that is the extraced plane.
|
||||
*/
|
||||
MonoImage* ColorImage::GetLuminancePlane() {
|
||||
return ExtractThirdColorPlane(IMAQ_HSL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the Value plane from an HSV image.
|
||||
*
|
||||
* @return a pointer to a MonoImage that is the extraced plane.
|
||||
*/
|
||||
MonoImage* ColorImage::GetValuePlane() {
|
||||
return ExtractThirdColorPlane(IMAQ_HSV);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the Intensity plane from an HSI image.
|
||||
*
|
||||
* @return a pointer to a MonoImage that is the extraced plane.
|
||||
*/
|
||||
MonoImage* ColorImage::GetIntensityPlane() {
|
||||
return ExtractThirdColorPlane(IMAQ_HSI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace a plane in the ColorImage with a MonoImage.
|
||||
*
|
||||
* Replaces a single plane in the image with a MonoImage.
|
||||
*
|
||||
* @param mode The ColorMode in which to operate
|
||||
* @param plane The pointer to the replacement plane as a MonoImage
|
||||
* @param planeNumber The plane number (1, 2, 3) to replace
|
||||
*/
|
||||
void ColorImage::ReplacePlane(ColorMode mode, MonoImage* plane,
|
||||
int planeNumber) {
|
||||
int success = imaqReplaceColorPlanes(
|
||||
m_imaqImage, reinterpret_cast<const Image*>(m_imaqImage), mode,
|
||||
(planeNumber == 1) ? plane->GetImaqImage() : nullptr,
|
||||
(planeNumber == 2) ? plane->GetImaqImage() : nullptr,
|
||||
(planeNumber == 3) ? plane->GetImaqImage() : nullptr);
|
||||
wpi_setImaqErrorWithContext(success, "Imaq ReplaceColorPlanes failed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the first color plane with a MonoImage.
|
||||
*
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color
|
||||
* plane.
|
||||
*/
|
||||
void ColorImage::ReplaceFirstColorPlane(ColorMode mode, MonoImage* plane) {
|
||||
ReplacePlane(mode, plane, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the second color plane with a MonoImage.
|
||||
*
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color
|
||||
* plane.
|
||||
*/
|
||||
void ColorImage::ReplaceSecondColorPlane(ColorMode mode, MonoImage* plane) {
|
||||
ReplacePlane(mode, plane, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the third color plane with a MonoImage.
|
||||
*
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color
|
||||
* plane.
|
||||
*/
|
||||
void ColorImage::ReplaceThirdColorPlane(ColorMode mode, MonoImage* plane) {
|
||||
ReplacePlane(mode, plane, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the red color plane with a MonoImage.
|
||||
*
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color
|
||||
* plane.
|
||||
*/
|
||||
void ColorImage::ReplaceRedPlane(MonoImage* plane) {
|
||||
ReplaceFirstColorPlane(IMAQ_RGB, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the green color plane with a MonoImage.
|
||||
*
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color
|
||||
* plane.
|
||||
*/
|
||||
void ColorImage::ReplaceGreenPlane(MonoImage* plane) {
|
||||
ReplaceSecondColorPlane(IMAQ_RGB, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the blue color plane with a MonoImage.
|
||||
*
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color
|
||||
* plane.
|
||||
*/
|
||||
void ColorImage::ReplaceBluePlane(MonoImage* plane) {
|
||||
ReplaceThirdColorPlane(IMAQ_RGB, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the Hue color plane in a HSL image with a MonoImage.
|
||||
*
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color
|
||||
* plane.
|
||||
*/
|
||||
void ColorImage::ReplaceHSLHuePlane(MonoImage* plane) {
|
||||
return ReplaceFirstColorPlane(IMAQ_HSL, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the Hue color plane in a HSV image with a MonoImage.
|
||||
*
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color
|
||||
* plane.
|
||||
*/
|
||||
void ColorImage::ReplaceHSVHuePlane(MonoImage* plane) {
|
||||
return ReplaceFirstColorPlane(IMAQ_HSV, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the first Hue plane in a HSI image with a MonoImage.
|
||||
*
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color
|
||||
* plane.
|
||||
*/
|
||||
void ColorImage::ReplaceHSIHuePlane(MonoImage* plane) {
|
||||
return ReplaceFirstColorPlane(IMAQ_HSI, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the Saturation color plane in an HSL image with a MonoImage.
|
||||
*
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color
|
||||
* plane.
|
||||
*/
|
||||
void ColorImage::ReplaceHSLSaturationPlane(MonoImage* plane) {
|
||||
return ReplaceSecondColorPlane(IMAQ_HSL, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the Saturation color plane in a HSV image with a MonoImage.
|
||||
*
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color
|
||||
* plane.
|
||||
*/
|
||||
void ColorImage::ReplaceHSVSaturationPlane(MonoImage* plane) {
|
||||
return ReplaceSecondColorPlane(IMAQ_HSV, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the Saturation color plane in a HSI image with a MonoImage.
|
||||
*
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color
|
||||
* plane.
|
||||
*/
|
||||
void ColorImage::ReplaceHSISaturationPlane(MonoImage* plane) {
|
||||
return ReplaceSecondColorPlane(IMAQ_HSI, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the Luminance color plane in an HSL image with a MonoImage.
|
||||
*
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color
|
||||
* plane.
|
||||
*/
|
||||
void ColorImage::ReplaceLuminancePlane(MonoImage* plane) {
|
||||
return ReplaceThirdColorPlane(IMAQ_HSL, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the Value color plane in an HSV with a MonoImage.
|
||||
*
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color
|
||||
* plane.
|
||||
*/
|
||||
void ColorImage::ReplaceValuePlane(MonoImage* plane) {
|
||||
return ReplaceThirdColorPlane(IMAQ_HSV, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the Intensity color plane in a HSI image with a MonoImage.
|
||||
*
|
||||
* @param mode The color mode in which to operate.
|
||||
* @param plane A pointer to a MonoImage that will replace the specified color
|
||||
* plane.
|
||||
*/
|
||||
void ColorImage::ReplaceIntensityPlane(MonoImage* plane) {
|
||||
return ReplaceThirdColorPlane(IMAQ_HSI, plane);
|
||||
}
|
||||
|
||||
// TODO: frcColorEqualize(Image* dest, const Image* source, int
|
||||
// colorEqualization) needs to be modified
|
||||
// The colorEqualization parameter is discarded and is set to TRUE in the call
|
||||
// to imaqColorEqualize.
|
||||
void ColorImage::Equalize(bool allPlanes) {
|
||||
// Note that this call uses NI-defined TRUE and FALSE
|
||||
int success = imaqColorEqualize(m_imaqImage,
|
||||
reinterpret_cast<const Image*>(m_imaqImage),
|
||||
(allPlanes) ? TRUE : FALSE);
|
||||
wpi_setImaqErrorWithContext(success, "Imaq ColorEqualize error");
|
||||
}
|
||||
|
||||
void ColorImage::ColorEqualize() { Equalize(true); }
|
||||
|
||||
void ColorImage::LuminanceEqualize() { Equalize(false); }
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,25 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "Vision/HSLImage.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
/**
|
||||
* Create a new image that uses the Hue, Saturation, and Luminance planes.
|
||||
*/
|
||||
HSLImage::HSLImage() : ColorImage(IMAQ_IMAGE_HSL) {}
|
||||
|
||||
/**
|
||||
* Create a new image by loading a file.
|
||||
*
|
||||
* @param fileName The path of the file to load.
|
||||
*/
|
||||
HSLImage::HSLImage(const char* fileName) : ColorImage(IMAQ_IMAGE_HSL) {
|
||||
int success = imaqReadFile(m_imaqImage, fileName, nullptr, nullptr);
|
||||
wpi_setImaqErrorWithContext(success, "Imaq ReadFile error");
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "Vision/ImageBase.h"
|
||||
|
||||
#include "nivision.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
/**
|
||||
* Create a new instance of an ImageBase.
|
||||
*
|
||||
* ImageBase is the base of all the other image classes. The constructor
|
||||
* creates any type of image and stores the pointer to it in the class.
|
||||
*
|
||||
* @param type The type of image to create
|
||||
*/
|
||||
ImageBase::ImageBase(ImageType type) {
|
||||
m_imaqImage = imaqCreateImage(type, DEFAULT_BORDER_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees memory associated with an ImageBase.
|
||||
*
|
||||
* Destructor frees the imaq image allocated with the class.
|
||||
*/
|
||||
ImageBase::~ImageBase() {
|
||||
if (m_imaqImage) imaqDispose(m_imaqImage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes an image to a file with the given filename.
|
||||
*
|
||||
* @param fileName The name of the file to write
|
||||
*/
|
||||
void ImageBase::Write(const char* fileName) {
|
||||
int success = imaqWriteFile(m_imaqImage, fileName, nullptr);
|
||||
wpi_setImaqErrorWithContext(success, "Imaq Image writeFile error");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the height of an image.
|
||||
*
|
||||
* @return The height of the image in pixels.
|
||||
*/
|
||||
int ImageBase::GetHeight() {
|
||||
int height;
|
||||
imaqGetImageSize(m_imaqImage, nullptr, &height);
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the width of an image.
|
||||
*
|
||||
* @return The width of the image in pixels.
|
||||
*/
|
||||
int ImageBase::GetWidth() {
|
||||
int width;
|
||||
imaqGetImageSize(m_imaqImage, &width, nullptr);
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the internal IMAQ Image data structure.
|
||||
*
|
||||
* @return A pointer to the internal IMAQ Image data structure.
|
||||
*/
|
||||
Image* ImageBase::GetImaqImage() { return m_imaqImage; }
|
||||
@@ -1,50 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "Vision/MonoImage.h"
|
||||
|
||||
#include "nivision.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
MonoImage::MonoImage() : ImageBase(IMAQ_IMAGE_U8) {}
|
||||
|
||||
/**
|
||||
* Look for ellipses in an image.
|
||||
*
|
||||
* Given some input parameters, look for any number of ellipses in an image.
|
||||
*
|
||||
* @param ellipseDescriptor Ellipse descriptor
|
||||
* @param curveOptions Curve options
|
||||
* @param shapeDetectionOptions Shape detection options
|
||||
* @param roi Region of Interest
|
||||
* @returns a vector of EllipseMatch structures (0 length vector on no match)
|
||||
*/
|
||||
std::vector<EllipseMatch>* MonoImage::DetectEllipses(
|
||||
EllipseDescriptor* ellipseDescriptor, CurveOptions* curveOptions,
|
||||
ShapeDetectionOptions* shapeDetectionOptions, ROI* roi) {
|
||||
int numberOfMatches;
|
||||
EllipseMatch* e =
|
||||
imaqDetectEllipses(m_imaqImage, ellipseDescriptor, curveOptions,
|
||||
shapeDetectionOptions, roi, &numberOfMatches);
|
||||
auto ellipses = new std::vector<EllipseMatch>;
|
||||
if (e == nullptr) {
|
||||
return ellipses;
|
||||
}
|
||||
for (int i = 0; i < numberOfMatches; i++) {
|
||||
ellipses->push_back(e[i]);
|
||||
}
|
||||
imaqDispose(e);
|
||||
return ellipses;
|
||||
}
|
||||
|
||||
std::vector<EllipseMatch>* MonoImage::DetectEllipses(
|
||||
EllipseDescriptor* ellipseDescriptor) {
|
||||
std::vector<EllipseMatch>* ellipses =
|
||||
DetectEllipses(ellipseDescriptor, nullptr, nullptr, nullptr);
|
||||
return ellipses;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "Vision/RGBImage.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
/**
|
||||
* Create a new image that uses Red, Green, and Blue planes.
|
||||
*/
|
||||
RGBImage::RGBImage() : ColorImage(IMAQ_IMAGE_RGB) {}
|
||||
|
||||
/**
|
||||
* Create a new image by loading a file.
|
||||
*
|
||||
* @param fileName The path of the file to load.
|
||||
*/
|
||||
RGBImage::RGBImage(const char* fileName) : ColorImage(IMAQ_IMAGE_RGB) {
|
||||
int success = imaqReadFile(m_imaqImage, fileName, nullptr, nullptr);
|
||||
wpi_setImaqErrorWithContext(success, "Imaq ReadFile error");
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "Vision/Threshold.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
Threshold::Threshold(int new_plane1Low, int new_plane1High, int new_plane2Low,
|
||||
int new_plane2High, int new_plane3Low,
|
||||
int new_plane3High) {
|
||||
plane1Low = new_plane1Low;
|
||||
plane1High = new_plane1High;
|
||||
plane2Low = new_plane2Low;
|
||||
plane2High = new_plane2High;
|
||||
plane3Low = new_plane3Low;
|
||||
plane3High = new_plane3High;
|
||||
}
|
||||
@@ -1,833 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "Vision/VisionAPI.h"
|
||||
|
||||
#include <cstdarg>
|
||||
|
||||
#include "Vision/BaeUtilities.h"
|
||||
#include "Vision/FrcError.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
int VisionAPI_debugFlag = 1;
|
||||
#define DPRINTF \
|
||||
if (VisionAPI_debugFlag) dprintf
|
||||
|
||||
/** @file
|
||||
* Image Management functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Create an image object
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_COMPLEX,
|
||||
* IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64
|
||||
* The border size is defaulted to 3 so that convolutional algorithms work at
|
||||
* the edges.
|
||||
* When you are finished with the created image, dispose of it by calling
|
||||
* frcDispose().
|
||||
* To get extended error information, call GetLastError().
|
||||
*
|
||||
* @param type Type of image to create
|
||||
* @return Image* On success, this function returns the created image. On
|
||||
* failure, it returns nullptr.
|
||||
*/
|
||||
Image* frcCreateImage(ImageType type) {
|
||||
return imaqCreateImage(type, DEFAULT_BORDER_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Dispose of one object. Supports any object created on the heap.
|
||||
*
|
||||
* @param object object to dispose of
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcDispose(void* object) { return imaqDispose(object); }
|
||||
|
||||
/**
|
||||
* @brief Dispose of a list of objects. Supports any object created on the heap.
|
||||
*
|
||||
* @param functionName The name of the function
|
||||
* @param ... A list of pointers to structures that need to be
|
||||
* disposed of. The last pointer in the list should always
|
||||
* be set to nullptr.
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcDispose(const char* functionName, ...) {
|
||||
va_list disposalPtrList; /* Input argument list */
|
||||
void* disposalPtr; /* For iteration */
|
||||
int success, returnValue = 1;
|
||||
|
||||
va_start(disposalPtrList, functionName); /* start of variable list */
|
||||
disposalPtr = va_arg(disposalPtrList, void*);
|
||||
while (disposalPtr != nullptr) {
|
||||
success = imaqDispose(disposalPtr);
|
||||
if (!success) {
|
||||
returnValue = 0;
|
||||
}
|
||||
disposalPtr = va_arg(disposalPtrList, void*);
|
||||
}
|
||||
va_end(disposalPtrList);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy an image object.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_RGB,
|
||||
* IMAQ_IMAGE_HSL.
|
||||
*
|
||||
* @param dest Copy of image. On failure, dest is nullptr. Must have already
|
||||
* been created using frcCreateImage(). When you are finished with
|
||||
* the created image, dispose of it by calling frcDispose().
|
||||
* @param source Image to copy
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcCopyImage(Image* dest, const Image* source) {
|
||||
return imaqDuplicate(dest, source);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Crop image without changing the scale.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_RGB,
|
||||
* IMAQ_IMAGE_HSL.
|
||||
*
|
||||
* @param dest Modified image
|
||||
* @param source Image to crop
|
||||
* @param rect region to process, or IMAQ_NO_RECT
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcCrop(Image* dest, const Image* source, Rect rect) {
|
||||
return imaqScale(dest, source, 1, 1, IMAQ_SCALE_LARGER, rect);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Scales the entire image larger or smaller.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_RGB,
|
||||
* IMAQ_IMAGE_HSL.
|
||||
*
|
||||
* @param dest Modified image
|
||||
* @param source Image to scale
|
||||
* @param xScale the horizontal reduction ratio
|
||||
* @param yScale the vertical reduction ratio
|
||||
* @param scaleMode IMAQ_SCALE_LARGER or IMAQ_SCALE_SMALLER
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcScale(Image* dest, const Image* source, int xScale, int yScale,
|
||||
ScalingMode scaleMode) {
|
||||
Rect rect = IMAQ_NO_RECT;
|
||||
return imaqScale(dest, source, xScale, yScale, scaleMode, rect);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates image object from the information in a file. The file can be
|
||||
* in one of the following formats:
|
||||
* PNG, JPEG, JPEG2000, TIFF, AIPD, or BMP.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_COMPLEX,
|
||||
* IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64.
|
||||
*
|
||||
* @param image Image read in
|
||||
* @param fileName File to read. Cannot be nullptr
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcReadImage(Image* image, const char* fileName) {
|
||||
return imaqReadFile(image, fileName, nullptr, nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write image to a file.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_COMPLEX,
|
||||
* IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64.
|
||||
*
|
||||
* The file type is determined by the extension, as follows:
|
||||
*
|
||||
* Extension File Type
|
||||
* aipd or .apd AIPD
|
||||
* .bmp BMP
|
||||
* .jpg or .jpeg JPEG
|
||||
* .jp2 JPEG2000
|
||||
* .png PNG
|
||||
* .tif or .tiff TIFF
|
||||
*
|
||||
*
|
||||
* The following are the supported image types for each file type:
|
||||
*
|
||||
* File Types Image Types
|
||||
* AIPD all image types
|
||||
* BMP, JPEG 8-bit, RGB
|
||||
* PNG, TIFF, JPEG2000 8-bit, 16-bit, RGB, RGBU64
|
||||
*
|
||||
* @param image Image to write
|
||||
* @param fileName File to read. Cannot be nullptr. The extension determines the
|
||||
* file format that is written.
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcWriteImage(const Image* image, const char* fileName) {
|
||||
RGBValue* colorTable = nullptr;
|
||||
return imaqWriteFile(image, fileName, colorTable);
|
||||
}
|
||||
|
||||
/* Measure Intensity functions */
|
||||
|
||||
/**
|
||||
* @brief Measures the pixel intensities in a rectangle of an image.
|
||||
* Outputs intensity based statistics about an image such as Max, Min, Mean and
|
||||
* Std Dev of pixel value.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL.
|
||||
*
|
||||
* Parameter Discussion:
|
||||
* Relevant parameters of the HistogramReport include:
|
||||
* min, max, mean and stdDev
|
||||
*
|
||||
* min/max: Setting both min and max to 0 causes the function to set min to 0
|
||||
* and the max to 255 for 8-bit images and to the actual minimum value and
|
||||
* maximum value of the image for all other image types.
|
||||
*
|
||||
* @param image Image whose histogram the function calculates.
|
||||
* @param numClasses The number of classes into which the function separates the
|
||||
* pixels. Determines the number of elements in the histogram
|
||||
* array returned
|
||||
* @param min The minimum pixel value to consider for the histogram. The
|
||||
* function does not count pixels with values less than min.
|
||||
* @param max The maximum pixel value to consider for the histogram. The
|
||||
* function does not count pixels with values greater than
|
||||
* max.
|
||||
* @param rect Region of interest in the image. If not included, the
|
||||
* entire image is used.
|
||||
* @return On success, this function returns a report describing the pixel value
|
||||
* classification. When you are finished with the report, dispose of it
|
||||
* by calling frcDispose(). On failure, this function returns nullptr.
|
||||
* To get extended error information, call GetLastError().
|
||||
*/
|
||||
HistogramReport* frcHistogram(const Image* image, int numClasses, float min,
|
||||
float max) {
|
||||
Rect rect = IMAQ_NO_RECT;
|
||||
return frcHistogram(image, numClasses, min, max, rect);
|
||||
}
|
||||
|
||||
HistogramReport* frcHistogram(const Image* image, int numClasses, float min,
|
||||
float max, Rect rect) {
|
||||
int success;
|
||||
int fillValue = 1;
|
||||
|
||||
/* create the region of interest */
|
||||
ROI* pRoi = imaqCreateROI();
|
||||
success = imaqAddRectContour(pRoi, rect);
|
||||
if (!success) {
|
||||
GetLastVisionError();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* make a mask from the ROI */
|
||||
Image* pMask = frcCreateImage(IMAQ_IMAGE_U8);
|
||||
success = imaqROIToMask(pMask, pRoi, fillValue, nullptr, nullptr);
|
||||
if (!success) {
|
||||
GetLastVisionError();
|
||||
frcDispose(__FUNCTION__, pRoi, nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* get a histogram report */
|
||||
HistogramReport* pHr = nullptr;
|
||||
pHr = imaqHistogram(image, numClasses, min, max, pMask);
|
||||
|
||||
/* clean up */
|
||||
frcDispose(__FUNCTION__, pRoi, pMask, nullptr);
|
||||
|
||||
return pHr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculates the histogram, or pixel distribution, of a color image.
|
||||
* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.
|
||||
*
|
||||
* @param image Image whose histogram the function calculates.
|
||||
* @param numClasses The number of classes into which the function separates the
|
||||
* pixels. Determines the number of elements in the histogram
|
||||
* array returned
|
||||
* @param mode The color space in which to perform the histogram. Possible
|
||||
* values include IMAQ_RGB and IMAQ_HSL.
|
||||
* @param mask An optional mask image. This image must be an IMAQ_IMAGE_U8
|
||||
* image. The function calculates the histogram using only
|
||||
* those pixels in the image whose corresponding pixels in the
|
||||
* mask are non-zero. Set this parameter to nullptr to
|
||||
* calculate the histogram of the entire image, or use the
|
||||
* simplified call.
|
||||
*
|
||||
* @return On success, this function returns a report describing the
|
||||
* classification of each plane in a HistogramReport. When you are
|
||||
* finished with the report, dispose of it by calling frcDispose().
|
||||
* On failure, this function returns nullptr. To get extended error
|
||||
* information, call imaqGetLastError().
|
||||
*/
|
||||
ColorHistogramReport* frcColorHistogram(const Image* image, int numClasses,
|
||||
ColorMode mode) {
|
||||
return frcColorHistogram(image, numClasses, mode, nullptr);
|
||||
}
|
||||
|
||||
ColorHistogramReport* frcColorHistogram(const Image* image, int numClasses,
|
||||
ColorMode mode, Image* mask) {
|
||||
return imaqColorHistogram2(
|
||||
const_cast<Image*>(reinterpret_cast<const Image*>(image)), numClasses,
|
||||
mode, nullptr, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Measures the pixel intensities in a rectangle of an image.
|
||||
* Outputs intensity based statistics about an image such as Max, Min, Mean and
|
||||
* Std Dev of pixel value.
|
||||
* Supports IMAQ_IMAGE_U8 (grayscale) IMAQ_IMAGE_RGB (color) IMAQ_IMAGE_HSL
|
||||
* (color-HSL).
|
||||
*
|
||||
* @param image The image whose pixel value the function queries
|
||||
* @param pixel The coordinates of the pixel that the function queries
|
||||
* @param value On return, the value of the specified image pixel. This
|
||||
* parameter cannot be nullptr. This data structure contains
|
||||
* either grayscale, RGB, HSL, Complex or RGBU64Value depending on
|
||||
* the type of image.
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcGetPixelValue(const Image* image, Point pixel, PixelValue* value) {
|
||||
return imaqGetPixel(image, pixel, value);
|
||||
}
|
||||
|
||||
/* Particle Analysis functions */
|
||||
|
||||
/**
|
||||
* @brief Filters particles out of an image based on their measurements.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL.
|
||||
*
|
||||
* @param dest The destination image. If dest is used, it must be the
|
||||
* same size as the Source image. It will contain only the
|
||||
* filtered particles.
|
||||
* @param source The image containing the particles to filter.
|
||||
* @param criteria An array of criteria to apply to the particles in the
|
||||
* source image. This array cannot be nullptr. See the
|
||||
* NIVisionCVI.chm help file for definitions of criteria.
|
||||
* @param criteriaCount The number of elements in the criteria array.
|
||||
* @param options Binary filter options, including rejectMatches,
|
||||
* rejectBorder, and connectivity8.
|
||||
* @param rect Area of image to filter. If omitted, the default is
|
||||
* entire image.
|
||||
* @param numParticles On return, the number of particles left in the image
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcParticleFilter(Image* dest, Image* source,
|
||||
const ParticleFilterCriteria2* criteria,
|
||||
int criteriaCount, const ParticleFilterOptions* options,
|
||||
int* numParticles) {
|
||||
Rect rect = IMAQ_NO_RECT;
|
||||
return frcParticleFilter(dest, source, criteria, criteriaCount, options, rect,
|
||||
numParticles);
|
||||
}
|
||||
|
||||
int frcParticleFilter(Image* dest, Image* source,
|
||||
const ParticleFilterCriteria2* criteria,
|
||||
int criteriaCount, const ParticleFilterOptions* options,
|
||||
Rect rect, int* numParticles) {
|
||||
ROI* roi = imaqCreateROI();
|
||||
imaqAddRectContour(roi, rect);
|
||||
return imaqParticleFilter3(dest, source, criteria, criteriaCount, options,
|
||||
roi, numParticles);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Performs morphological transformations on binary images.
|
||||
* Supports IMAQ_IMAGE_U8.
|
||||
*
|
||||
* @param dest The destination image. The border size of the
|
||||
* destination image is not important.
|
||||
* @param source The image on which the function performs the
|
||||
* morphological operations. The calculation modifies
|
||||
* the border of the source image. The border must be
|
||||
* at least half as large as the larger dimension of
|
||||
* the structuring element. The connected source
|
||||
* image for a morphological transformation must have
|
||||
* been created with a border capable of supporting
|
||||
* the size of the structuring element. A 3 by 3
|
||||
* structuring element requires a minimal border of 1,
|
||||
* a 5 by 5 structuring element requires a minimal
|
||||
* border of 2, and so on.
|
||||
* @param method The morphological transform to apply.
|
||||
* @param structuringElement The structuring element used in the operation. Omit
|
||||
* this parameter if you do not want a custom
|
||||
* structuring element.
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcMorphology(Image* dest, Image* source, MorphologyMethod method) {
|
||||
return imaqMorphology(dest, source, method, nullptr);
|
||||
}
|
||||
|
||||
int frcMorphology(Image* dest, Image* source, MorphologyMethod method,
|
||||
const StructuringElement* structuringElement) {
|
||||
return imaqMorphology(dest, source, method, structuringElement);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Eliminates particles that touch the border of the image.
|
||||
* Supports IMAQ_IMAGE_U8.
|
||||
*
|
||||
* @param dest The destination image.
|
||||
* @param source The source image. If the image has a border, the
|
||||
* function sets all border pixel values to 0.
|
||||
* @param connectivity8 specifies the type of connectivity used by the algorithm
|
||||
* for particle detection. The connectivity mode directly
|
||||
* determines whether an adjacent pixel belongs to the same
|
||||
* particle or a different particle. Set to TRUE to use
|
||||
* connectivity-8 to determine whether particles are
|
||||
* touching. Set to FALSE to use connectivity-4 to
|
||||
* determine whether particles are touching. The default
|
||||
* setting for the simplified call is TRUE
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcRejectBorder(Image* dest, Image* source) {
|
||||
return imaqRejectBorder(dest, source, TRUE);
|
||||
}
|
||||
|
||||
int frcRejectBorder(Image* dest, Image* source, int connectivity8) {
|
||||
return imaqRejectBorder(dest, source, connectivity8);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Counts the number of particles in a binary image.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL.
|
||||
* @param image binary (thresholded) image
|
||||
* @param numParticles On return, the number of particles.
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcCountParticles(Image* image, int* numParticles) {
|
||||
return imaqCountParticles(image, 1, numParticles);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Conduct measurements for a single particle in an images.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL.
|
||||
*
|
||||
* @param image image with the particle to analyze. This function
|
||||
* modifies the source image. If you need the original
|
||||
* image, create a copy of the image using frcCopy()
|
||||
* before using this function.
|
||||
* @param particleNumber The number of the particle to get information on
|
||||
* @param par on return, a particle analysis report containing
|
||||
* information about the particle. This structure must be
|
||||
* created by the caller.
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcParticleAnalysis(Image* image, int particleNumber,
|
||||
ParticleAnalysisReport* par) {
|
||||
int success = 0;
|
||||
|
||||
/* image information */
|
||||
int height, width;
|
||||
if (!imaqGetImageSize(image, &width, &height)) {
|
||||
return success;
|
||||
}
|
||||
par->imageWidth = width;
|
||||
par->imageHeight = height;
|
||||
par->particleIndex = particleNumber;
|
||||
|
||||
/* center of mass point of the largest particle */
|
||||
double returnDouble;
|
||||
success = imaqMeasureParticle(image, particleNumber, 0,
|
||||
IMAQ_MT_CENTER_OF_MASS_X, &returnDouble);
|
||||
if (!success) {
|
||||
return success;
|
||||
}
|
||||
par->center_mass_x = static_cast<int>(returnDouble); // pixel
|
||||
|
||||
success = imaqMeasureParticle(image, particleNumber, 0,
|
||||
IMAQ_MT_CENTER_OF_MASS_Y, &returnDouble);
|
||||
if (!success) {
|
||||
return success;
|
||||
}
|
||||
par->center_mass_y = static_cast<int>(returnDouble); // pixel
|
||||
|
||||
/* particle size statistics */
|
||||
success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_AREA,
|
||||
&returnDouble);
|
||||
if (!success) {
|
||||
return success;
|
||||
}
|
||||
par->particleArea = returnDouble;
|
||||
|
||||
success = imaqMeasureParticle(image, particleNumber, 0,
|
||||
IMAQ_MT_BOUNDING_RECT_TOP, &returnDouble);
|
||||
if (!success) {
|
||||
return success;
|
||||
}
|
||||
par->boundingRect.top = static_cast<int>(returnDouble);
|
||||
|
||||
success = imaqMeasureParticle(image, particleNumber, 0,
|
||||
IMAQ_MT_BOUNDING_RECT_LEFT, &returnDouble);
|
||||
if (!success) {
|
||||
return success;
|
||||
}
|
||||
par->boundingRect.left = static_cast<int>(returnDouble);
|
||||
|
||||
success = imaqMeasureParticle(image, particleNumber, 0,
|
||||
IMAQ_MT_BOUNDING_RECT_HEIGHT, &returnDouble);
|
||||
if (!success) {
|
||||
return success;
|
||||
}
|
||||
par->boundingRect.height = static_cast<int>(returnDouble);
|
||||
|
||||
success = imaqMeasureParticle(image, particleNumber, 0,
|
||||
IMAQ_MT_BOUNDING_RECT_WIDTH, &returnDouble);
|
||||
if (!success) {
|
||||
return success;
|
||||
}
|
||||
par->boundingRect.width = static_cast<int>(returnDouble);
|
||||
|
||||
/* particle quality statistics */
|
||||
success = imaqMeasureParticle(image, particleNumber, 0,
|
||||
IMAQ_MT_AREA_BY_IMAGE_AREA, &returnDouble);
|
||||
if (!success) {
|
||||
return success;
|
||||
}
|
||||
par->particleToImagePercent = returnDouble;
|
||||
|
||||
success = imaqMeasureParticle(image, particleNumber, 0,
|
||||
IMAQ_MT_AREA_BY_PARTICLE_AND_HOLES_AREA,
|
||||
&returnDouble);
|
||||
if (!success) {
|
||||
return success;
|
||||
}
|
||||
par->particleQuality = returnDouble;
|
||||
|
||||
/* normalized position (-1 to 1) */
|
||||
par->center_mass_x_normalized = RangeToNormalized(par->center_mass_x, width);
|
||||
par->center_mass_y_normalized = RangeToNormalized(par->center_mass_y, height);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/* Image Enhancement functions */
|
||||
|
||||
/**
|
||||
* @brief Improves contrast on a grayscale image.
|
||||
* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16.
|
||||
* @param dest The destination image.
|
||||
* @param source The image to equalize
|
||||
* @param min the smallest value used for processing. After processing, all
|
||||
* pixel values that are less than or equal to the Minimum in the
|
||||
* original image are set to 0 for an 8-bit image. In 16-bit and
|
||||
* floating-point images, these pixel values are set to the
|
||||
* smallest pixel value found in the original image.
|
||||
* @param max the largest value used for processing. After processing, all
|
||||
* pixel values that are greater than or equal to the Maximum in
|
||||
* the original image are set to 255 for an 8-bit image. In 16-bit
|
||||
* and floating-point images, these pixel values are set to the
|
||||
* largest pixel value found in the original image.
|
||||
* @param mask an 8-bit image that specifies the region of the small image
|
||||
* that will be copied. Only those pixels in the Image Src (Small)
|
||||
* image that correspond to an equivalent non-zero pixel in the
|
||||
* mask image are copied. All other pixels keep their original
|
||||
* values. The entire image is processed if Image Mask is nullptr
|
||||
* or this parameter is omitted.
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*
|
||||
* option defaults:
|
||||
* searchRect = IMAQ_NO_RECT
|
||||
* minMatchScore = DEFAULT_MINMAX_SCORE (800)
|
||||
*/
|
||||
int frcEqualize(Image* dest, const Image* source, float min, float max) {
|
||||
return frcEqualize(dest, source, min, max, nullptr);
|
||||
}
|
||||
|
||||
int frcEqualize(Image* dest, const Image* source, float min, float max,
|
||||
const Image* mask) {
|
||||
return imaqEqualize(dest, source, min, max, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Improves contrast on a color image.
|
||||
* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL
|
||||
*
|
||||
* option defaults: colorEqualization = TRUE to equalize all three planes of the
|
||||
* image
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
* @param dest The destination image.
|
||||
* @param source The image to equalize
|
||||
* @param colorEqualization Set this parameter to TRUE to equalize all three
|
||||
* planes of the image (the default). Set this parameter to FALSE to equalize
|
||||
* only the luminance plane.
|
||||
*/
|
||||
int frcColorEqualize(Image* dest, const Image* source) {
|
||||
return imaqColorEqualize(dest, source, TRUE);
|
||||
}
|
||||
|
||||
int frcColorEqualize(Image* dest, const Image* source, int colorEqualization) {
|
||||
return imaqColorEqualize(dest, source, TRUE);
|
||||
}
|
||||
|
||||
/* Image Conversion functions */
|
||||
|
||||
/**
|
||||
* @brief Automatically thresholds a grayscale image into a binary image for
|
||||
* Particle Analysis based on a smart threshold.
|
||||
* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_I16
|
||||
* @param dest The destination image.
|
||||
* @param source The image to threshold
|
||||
* @param windowWidth The width of the rectangular window around the pixel
|
||||
* on which the function performs the local threshold.
|
||||
* This number must be at least 3 and cannot be larger
|
||||
* than the width of source
|
||||
* @param windowHeight The height of the rectangular window around the pixel
|
||||
* on which the function performs the local threshold.
|
||||
* This number must be at least 3 and cannot be larger
|
||||
* than the height of source
|
||||
* @param method Specifies the local thresholding method the function
|
||||
* uses. Value can be IMAQ_NIBLACK (which computes
|
||||
* thresholds for each pixel based on its local
|
||||
* statistics using the Niblack local thresholding
|
||||
* algorithm.), or IMAQ_BACKGROUND_CORRECTION (which
|
||||
* does background correction first to eliminate
|
||||
* non-uniform lighting effects, then performs
|
||||
* thresholding using the Otsu thresholding algorithm)
|
||||
* @param deviationWeight Specifies the k constant used in the Niblack local
|
||||
* thresholding algorithm, which determines the weight
|
||||
* applied to the variance calculation. Valid k constants
|
||||
* range from 0 to 1. Setting this value to 0 will
|
||||
* increase the performance of the function because the
|
||||
* function will not calculate the variance for any of
|
||||
* the pixels. The function ignores this value if method
|
||||
* is not set to IMAQ_NIBLACK
|
||||
* @param type Specifies the type of objects for which you want to
|
||||
* look. Values can be IMAQ_BRIGHT_OBJECTS or
|
||||
* IMAQ_DARK_OBJECTS.
|
||||
* @param replaceValue Specifies the replacement value the function uses for
|
||||
* the pixels of the kept objects in the destination
|
||||
* image.
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcSmartThreshold(Image* dest, const Image* source, int windowWidth,
|
||||
int windowHeight, LocalThresholdMethod method,
|
||||
double deviationWeight, ObjectType type) {
|
||||
float replaceValue = 1.0;
|
||||
return imaqLocalThreshold(dest, source, windowWidth, windowHeight, method,
|
||||
deviationWeight, type, replaceValue);
|
||||
}
|
||||
|
||||
int frcSmartThreshold(Image* dest, const Image* source, int windowWidth,
|
||||
int windowHeight, LocalThresholdMethod method,
|
||||
double deviationWeight, ObjectType type,
|
||||
float replaceValue) {
|
||||
return imaqLocalThreshold(dest, source, windowWidth, windowHeight, method,
|
||||
deviationWeight, type, replaceValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts a grayscale image to a binary image for Particle Analysis
|
||||
* based on a fixed threshold.
|
||||
* The function sets pixels values outside of the given range to 0. The function
|
||||
* sets pixel values within the range to a given value or leaves the values
|
||||
* unchanged. Use the simplified call to leave pixel values unchanged.
|
||||
* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_I16.
|
||||
*
|
||||
* @param dest The destination image.
|
||||
* @param source The image to threshold
|
||||
* @param rangeMin The lower boundary of the range of pixel values to keep
|
||||
* @param rangeMax The upper boundary of the range of pixel values to keep.
|
||||
*
|
||||
* @return error code: 0 = error. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcSimpleThreshold(Image* dest, const Image* source, float rangeMin,
|
||||
float rangeMax) {
|
||||
int newValue = 255;
|
||||
return frcSimpleThreshold(dest, source, rangeMin, rangeMax, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts a grayscale image to a binary image for Particle Analysis
|
||||
* based on a fixed threshold.
|
||||
* The function sets pixels values outside of the given range to 0. The function
|
||||
* sets pixel values within the range to the given value.
|
||||
* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_I16.
|
||||
*
|
||||
* @param dest The destination image.
|
||||
* @param source The image to threshold
|
||||
* @param rangeMin The lower boundary of the range of pixel values to keep
|
||||
* @param rangeMax The upper boundary of the range of pixel values to keep.
|
||||
* @param newValue The replacement value for pixels within the range. Use the
|
||||
* simplified call to leave the pixel values unchanged
|
||||
*
|
||||
* @return error code: 0 = error. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcSimpleThreshold(Image* dest, const Image* source, float rangeMin,
|
||||
float rangeMax, float newValue) {
|
||||
int useNewValue = TRUE;
|
||||
return imaqThreshold(dest, source, rangeMin, rangeMax, useNewValue, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Applies a threshold to the Red, Green, and Blue values of a RGB image
|
||||
* or the Hue, Saturation, Luminance values for a HSL image.
|
||||
* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.
|
||||
* This simpler version filters based on a hue range in the HSL mode.
|
||||
*
|
||||
* @param dest The destination image. This must be a IMAQ_IMAGE_U8 image.
|
||||
* @param source The image to threshold
|
||||
* @param mode The color space to perform the threshold in. valid values
|
||||
* are: IMAQ_RGB, IMAQ_HSL.
|
||||
* @param plane1Range The selection range for the first plane of the image. Set
|
||||
* this parameter to nullptr to use a selection range from 0
|
||||
* to 255.
|
||||
* @param plane2Range The selection range for the second plane of the image. Set
|
||||
* this parameter to nullptr to use a selection range from 0
|
||||
* to 255.
|
||||
* @param plane3Range The selection range for the third plane of the image. Set
|
||||
* this parameter to nullptr to use a selection range from 0
|
||||
* to 255.
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcColorThreshold(Image* dest, const Image* source, ColorMode mode,
|
||||
const Range* plane1Range, const Range* plane2Range,
|
||||
const Range* plane3Range) {
|
||||
int replaceValue = 1;
|
||||
return imaqColorThreshold(dest, source, replaceValue, mode, plane1Range,
|
||||
plane2Range, plane3Range);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Applies a threshold to the Red, Green, and Blue values of a RGB image
|
||||
* or the Hue, Saturation, Luminance values for a HSL image.
|
||||
* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.
|
||||
* The simpler version filters based on a hue range in the HSL mode.
|
||||
*
|
||||
* @param dest The destination image. This must be a IMAQ_IMAGE_U8
|
||||
* image.
|
||||
* @param source The image to threshold
|
||||
* @param replaceValue Value to assign to selected pixels. Defaults to 1 if
|
||||
* simplified call is used.
|
||||
* @param mode The color space to perform the threshold in. valid values
|
||||
* are: IMAQ_RGB, IMAQ_HSL.
|
||||
* @param plane1Range The selection range for the first plane of the image.
|
||||
* Set this parameter to nullptr to use a selection range
|
||||
* from 0 to 255.
|
||||
* @param plane2Range The selection range for the second plane of the image.
|
||||
* Set this parameter to nullptr to use a selection range
|
||||
* from 0 to 255.
|
||||
* @param plane3Range The selection range for the third plane of the image.
|
||||
* Set this parameter to nullptr to use a selection range
|
||||
* from 0 to 255.
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcColorThreshold(Image* dest, const Image* source, int replaceValue,
|
||||
ColorMode mode, const Range* plane1Range,
|
||||
const Range* plane2Range, const Range* plane3Range) {
|
||||
return imaqColorThreshold(dest, source, replaceValue, mode, plane1Range,
|
||||
plane2Range, plane3Range);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A simpler version of ColorThreshold that thresholds hue range in the
|
||||
* HSL mode. Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.
|
||||
* @param dest The destination image.
|
||||
* @param source The image to threshold
|
||||
* @param hueRange The selection range for the hue (color).
|
||||
* @param minSaturation The minimum saturation value (1-255). If not used,
|
||||
* DEFAULT_SATURATION_THRESHOLD is the default.
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcHueThreshold(Image* dest, const Image* source, const Range* hueRange) {
|
||||
return frcHueThreshold(dest, source, hueRange, DEFAULT_SATURATION_THRESHOLD);
|
||||
}
|
||||
|
||||
int frcHueThreshold(Image* dest, const Image* source, const Range* hueRange,
|
||||
int minSaturation) {
|
||||
// assume HSL mode
|
||||
ColorMode mode = IMAQ_HSL;
|
||||
// Set saturation 100 - 255
|
||||
Range satRange;
|
||||
satRange.minValue = minSaturation;
|
||||
satRange.maxValue = 255;
|
||||
// Set luminance 100 - 255
|
||||
Range lumRange;
|
||||
lumRange.minValue = 100;
|
||||
lumRange.maxValue = 255;
|
||||
// Replace pixels with 1 if pass threshold filter
|
||||
int replaceValue = 1;
|
||||
return imaqColorThreshold(dest, source, replaceValue, mode, hueRange,
|
||||
&satRange, &lumRange);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Extracts the Red, Green, Blue, or Hue, Saturation or Luminance
|
||||
* information from a color image.
|
||||
* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64.
|
||||
*
|
||||
* @param image The source image that the function extracts the planes from.
|
||||
* @param mode The color space that the function extracts the planes from.
|
||||
* Valid values are IMAQ_RGB, IMAQ_HSL, IMAQ_HSV, IMAQ_HSI.
|
||||
* @param plane1 On return, the first extracted plane. Set this parameter to
|
||||
* nullptr if you do not need this information. RGB-Red,
|
||||
* HSL/HSV/HSI-Hue.
|
||||
* @param plane2 On return, the second extracted plane. Set this parameter to
|
||||
* nullptr if you do not need this information. RGB-Green,
|
||||
* HSL/HSV/HSI-Saturation.
|
||||
* @param plane3 On return, the third extracted plane. Set this parameter to
|
||||
* nullptr if you do not need this information. RGB-Blue,
|
||||
* HSL-Luminance, HSV-Value, HSI-Intensity.
|
||||
*
|
||||
* @return error code: 0 = error. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcExtractColorPlanes(const Image* image, ColorMode mode, Image* plane1,
|
||||
Image* plane2, Image* plane3) {
|
||||
return imaqExtractColorPlanes(image, mode, plane1, plane2, plane3);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Extracts the Hue information from a color image. Supports
|
||||
* IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64
|
||||
*
|
||||
* @param image The source image that the function extracts the plane
|
||||
* from.
|
||||
* @param huePlane On return, the extracted hue plane.
|
||||
* @param minSaturation the minimum saturation level required 0-255 (try 50)
|
||||
*
|
||||
* @return On success: 1. On failure: 0. To get extended error information, call
|
||||
* GetLastError().
|
||||
*/
|
||||
int frcExtractHuePlane(const Image* image, Image* huePlane) {
|
||||
return frcExtractHuePlane(image, huePlane, DEFAULT_SATURATION_THRESHOLD);
|
||||
}
|
||||
|
||||
int frcExtractHuePlane(const Image* image, Image* huePlane, int minSaturation) {
|
||||
return frcExtractColorPlanes(image, IMAQ_HSL, huePlane, nullptr, nullptr);
|
||||
}
|
||||
|
||||
} // namespace frc
|
||||
@@ -1,646 +0,0 @@
|
||||
//==============================================================================
|
||||
//
|
||||
// Title : NIIMAQdx.h
|
||||
// Created : 1403685834 seconds after 1/1/1970 12:00:00 UTC
|
||||
// Copyright : © Copyright 2006, National Instruments Corporation, All rights reserved
|
||||
// Purpose : Include file for NI-IMAQdx library support.
|
||||
//
|
||||
//==============================================================================
|
||||
#ifndef ___niimaqdx_h___
|
||||
#define ___niimaqdx_h___
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(niimaqdx_types)
|
||||
#define niimaqdx_types
|
||||
|
||||
#ifdef _CVI_
|
||||
#pragma EnableLibraryRuntimeChecking
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
// Typedefs
|
||||
//==============================================================================
|
||||
#ifndef _NI_uInt8_DEFINED_
|
||||
#define _NI_uInt8_DEFINED_
|
||||
typedef unsigned char uInt8;
|
||||
#endif
|
||||
|
||||
#ifndef _NI_uInt16_DEFINED_
|
||||
#define _NI_uInt16_DEFINED_
|
||||
typedef unsigned short int uInt16;
|
||||
#endif
|
||||
|
||||
#ifndef _NI_uInt32_DEFINED_
|
||||
#define _NI_uInt32_DEFINED_
|
||||
#if defined(_MSC_VER)
|
||||
typedef unsigned long uInt32;
|
||||
#elif __GNUC__
|
||||
#if __x86_64__
|
||||
typedef unsigned int uInt32;
|
||||
#else
|
||||
typedef unsigned long uInt32;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _NI_uInt64_DEFINED_
|
||||
#define _NI_uInt64_DEFINED_
|
||||
#if defined(_MSC_VER) || _CVI_ >= 700
|
||||
typedef unsigned __int64 uInt64;
|
||||
#elif __GNUC__
|
||||
typedef unsigned long long uInt64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _NI_Int8_DEFINED_
|
||||
#define _NI_Int8_DEFINED_
|
||||
typedef char Int8;
|
||||
#endif
|
||||
|
||||
#ifndef _NI_Int16_DEFINED_
|
||||
#define _NI_Int16_DEFINED_
|
||||
typedef short int Int16;
|
||||
#endif
|
||||
|
||||
#ifndef _NI_Int32_DEFINED_
|
||||
#define _NI_Int32_DEFINED_
|
||||
#if defined(_MSC_VER)
|
||||
typedef long Int32;
|
||||
#elif __GNUC__
|
||||
#if __x86_64__
|
||||
typedef int Int32;
|
||||
#else
|
||||
typedef long Int32;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _NI_Int64_DEFINED_
|
||||
#define _NI_Int64_DEFINED_
|
||||
#if defined(_MSC_VER) || _CVI_ >= 700
|
||||
typedef __int64 Int64;
|
||||
#elif __GNUC__
|
||||
typedef long long int Int64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _NI_float32_DEFINED_
|
||||
#define _NI_float32_DEFINED_
|
||||
typedef float float32;
|
||||
#endif
|
||||
|
||||
#ifndef _NI_float64_DEFINED_
|
||||
#define _NI_float64_DEFINED_
|
||||
typedef double float64;
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE (1L)
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE (0L)
|
||||
#endif
|
||||
|
||||
#ifndef _NI_GUIDHNDL_DEFINED
|
||||
typedef uInt32 GUIHNDL;
|
||||
#endif
|
||||
|
||||
#if (defined(_MSC_VER) || defined(_CVI_))
|
||||
#ifndef _NI_FUNC_DEFINED
|
||||
#define NI_FUNC __stdcall
|
||||
#endif
|
||||
|
||||
#ifndef _NI_FUNCC_DEFINED
|
||||
#define NI_FUNCC __cdecl
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
#ifndef _NI_FUNC_DEFINED
|
||||
#define NI_FUNC
|
||||
#endif
|
||||
|
||||
#ifndef _NI_FUNCC_DEFINED
|
||||
#define NI_FUNCC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _NI_bool32_DEFINED_
|
||||
#define _NI_bool32_DEFINED_
|
||||
typedef uInt32 bool32;
|
||||
#endif
|
||||
|
||||
#ifndef _NI_IMAQdxSession_DEFINED_
|
||||
#define _NI_IMAQdxSession_DEFINED_
|
||||
typedef uInt32 IMAQdxSession;
|
||||
#endif
|
||||
|
||||
#define IMAQDX_MAX_API_STRING_LENGTH 512
|
||||
|
||||
//==============================================================================
|
||||
// Forward Declare Data Structures
|
||||
//==============================================================================
|
||||
typedef struct Image_struct Image;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Error Codes Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxError_enum {
|
||||
IMAQdxErrorSuccess = 0x0, // Success
|
||||
IMAQdxErrorSystemMemoryFull = 0xBFF69000, // Not enough memory
|
||||
IMAQdxErrorInternal, // Internal error
|
||||
IMAQdxErrorInvalidParameter, // Invalid parameter
|
||||
IMAQdxErrorInvalidPointer, // Invalid pointer
|
||||
IMAQdxErrorInvalidInterface, // Invalid camera session
|
||||
IMAQdxErrorInvalidRegistryKey, // Invalid registry key
|
||||
IMAQdxErrorInvalidAddress, // Invalid address
|
||||
IMAQdxErrorInvalidDeviceType, // Invalid device type
|
||||
IMAQdxErrorNotImplemented, // Not implemented
|
||||
IMAQdxErrorCameraNotFound, // Camera not found
|
||||
IMAQdxErrorCameraInUse, // Camera is already in use.
|
||||
IMAQdxErrorCameraNotInitialized, // Camera is not initialized.
|
||||
IMAQdxErrorCameraRemoved, // Camera has been removed.
|
||||
IMAQdxErrorCameraRunning, // Acquisition in progress.
|
||||
IMAQdxErrorCameraNotRunning, // No acquisition in progress.
|
||||
IMAQdxErrorAttributeNotSupported, // Attribute not supported by the camera.
|
||||
IMAQdxErrorAttributeNotSettable, // Unable to set attribute.
|
||||
IMAQdxErrorAttributeNotReadable, // Unable to get attribute.
|
||||
IMAQdxErrorAttributeOutOfRange, // Attribute value is out of range.
|
||||
IMAQdxErrorBufferNotAvailable, // Requested buffer is unavailable.
|
||||
IMAQdxErrorBufferListEmpty, // Buffer list is empty. Add one or more buffers.
|
||||
IMAQdxErrorBufferListLocked, // Buffer list is already locked. Reconfigure acquisition and try again.
|
||||
IMAQdxErrorBufferListNotLocked, // No buffer list. Reconfigure acquisition and try again.
|
||||
IMAQdxErrorResourcesAllocated, // Transfer engine resources already allocated. Reconfigure acquisition and try again.
|
||||
IMAQdxErrorResourcesUnavailable, // Insufficient transfer engine resources.
|
||||
IMAQdxErrorAsyncWrite, // Unable to perform asychronous register write.
|
||||
IMAQdxErrorAsyncRead, // Unable to perform asychronous register read.
|
||||
IMAQdxErrorTimeout, // Timeout.
|
||||
IMAQdxErrorBusReset, // Bus reset occurred during a transaction.
|
||||
IMAQdxErrorInvalidXML, // Unable to load camera's XML file.
|
||||
IMAQdxErrorFileAccess, // Unable to read/write to file.
|
||||
IMAQdxErrorInvalidCameraURLString, // Camera has malformed URL string.
|
||||
IMAQdxErrorInvalidCameraFile, // Invalid camera file.
|
||||
IMAQdxErrorGenICamError, // Unknown Genicam error.
|
||||
IMAQdxErrorFormat7Parameters, // For format 7: The combination of speed, image position, image size, and color coding is incorrect.
|
||||
IMAQdxErrorInvalidAttributeType, // The attribute type is not compatible with the passed variable type.
|
||||
IMAQdxErrorDLLNotFound, // The DLL could not be found.
|
||||
IMAQdxErrorFunctionNotFound, // The function could not be found.
|
||||
IMAQdxErrorLicenseNotActivated, // License not activated.
|
||||
IMAQdxErrorCameraNotConfiguredForListener, // The camera is not configured properly to support a listener.
|
||||
IMAQdxErrorCameraMulticastNotAvailable, // Unable to configure the system for multicast support.
|
||||
IMAQdxErrorBufferHasLostPackets, // The requested buffer has lost packets and the user requested an error to be generated.
|
||||
IMAQdxErrorGiGEVisionError, // Unknown GiGE Vision error.
|
||||
IMAQdxErrorNetworkError, // Unknown network error.
|
||||
IMAQdxErrorCameraUnreachable, // Unable to connect to the camera.
|
||||
IMAQdxErrorHighPerformanceNotSupported, // High performance acquisition is not supported on the specified network interface. Connect the camera to a network interface running the high performance driver.
|
||||
IMAQdxErrorInterfaceNotRenamed, // Unable to rename interface. Invalid or duplicate name specified.
|
||||
IMAQdxErrorNoSupportedVideoModes, // The camera does not have any video modes which are supported.
|
||||
IMAQdxErrorSoftwareTriggerOverrun, // Software trigger overrun.
|
||||
IMAQdxErrorTestPacketNotReceived, // The system did not receive a test packet from the camera. The packet size may be too large for the network configuration or a firewall may be enabled.
|
||||
IMAQdxErrorCorruptedImageReceived, // The camera returned a corrupted image.
|
||||
IMAQdxErrorCameraConfigurationHasChanged, // The camera did not return an image of the correct type it was configured for previously.
|
||||
IMAQdxErrorCameraInvalidAuthentication, // The camera is configured with password authentication and either the user name and password were not configured or they are incorrect.
|
||||
IMAQdxErrorUnknownHTTPError, // The camera returned an unknown HTTP error.
|
||||
IMAQdxErrorKernelDriverUnavailable, // Unable to attach to the kernel mode driver.
|
||||
IMAQdxErrorPixelFormatDecoderUnavailable, // No decoder available for selected pixel format.
|
||||
IMAQdxErrorFirmwareUpdateNeeded, // The acquisition hardware needs a firmware update before it can be used.
|
||||
IMAQdxErrorFirmwareUpdateRebootNeeded, // The firmware on the acquisition hardware has been updated and the system must be rebooted before use.
|
||||
IMAQdxErrorLightingCurrentOutOfRange, // The requested current level from the lighting controller is not possible.
|
||||
IMAQdxErrorUSB3VisionError, // Unknown USB3 Vision error.
|
||||
IMAQdxErrorInvalidU3VUSBDescriptor, // The camera has a USB descriptor that is incompatible with the USB3 Vision specification.
|
||||
IMAQdxErrorU3VInvalidControlInterface, // The USB3 Vision control interface is not implemented or is invalid on this camera.
|
||||
IMAQdxErrorU3VControlInterfaceError, // There was an error from the control interface of the USB3 Vision camera.
|
||||
IMAQdxErrorU3VInvalidEventInterface, // The USB3 Vision event interface is not implemented or is invalid on this camera.
|
||||
IMAQdxErrorU3VEventInterfaceError, // There was an error from the event interface of the USB3 Vision camera.
|
||||
IMAQdxErrorU3VInvalidStreamInterface, // The USB3 Vision stream interface is not implemented or is invalid on this camera.
|
||||
IMAQdxErrorU3VStreamInterfaceError, // There was an error from the stream interface of the USB3 Vision camera.
|
||||
IMAQdxErrorU3VUnsupportedConnectionSpeed, // The USB connection speed is not supported by the camera. Check whether the camera is plugged into a USB 2.0 port instead of a USB 3.0 port. If so, verify that the camera supports this use case.
|
||||
IMAQdxErrorU3VInsufficientPower, // The USB3 Vision camera requires more current than can be supplied by the USB port in use.
|
||||
IMAQdxErrorU3VInvalidMaxCurrent, // The U3V_MaximumCurrentUSB20_mA registry value is not valid for the connected USB3 Vision camera.
|
||||
IMAQdxErrorBufferIncompleteData, // The requested buffer has incomplete data and the user requested an error to be generated.
|
||||
IMAQdxErrorCameraAcquisitionConfigFailed, // The camera returned an error starting the acquisition.
|
||||
IMAQdxErrorCameraClosePending, // The camera still has outstanding references and will be closed when these operations complete.
|
||||
IMAQdxErrorSoftwareFault, // An unexpected software error occurred.
|
||||
IMAQdxErrorCameraPropertyInvalid, // The value for an invalid camera property was requested.
|
||||
IMAQdxErrorJumboFramesNotEnabled, // Jumbo frames are not enabled on the host. Maximum packet size is 1500 bytes.
|
||||
IMAQdxErrorBayerPixelFormatNotSelected, // This operation requires that the camera has a Bayer pixel format selected.
|
||||
IMAQdxErrorGuard = 0xFFFFFFFF,
|
||||
} IMAQdxError;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Bus Type Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxBusType_enum {
|
||||
IMAQdxBusTypeFireWire = 0x31333934,
|
||||
IMAQdxBusTypeEthernet = 0x69707634,
|
||||
IMAQdxBusTypeSimulator = 0x2073696D,
|
||||
IMAQdxBusTypeDirectShow = 0x64736877,
|
||||
IMAQdxBusTypeIP = 0x4950636D,
|
||||
IMAQdxBusTypeSmartCam2 = 0x53436132,
|
||||
IMAQdxBusTypeUSB3Vision = 0x55534233,
|
||||
IMAQdxBusTypeUVC = 0x55564320,
|
||||
IMAQdxBusTypeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxBusType;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Camera Control Mode Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxCameraControlMode_enum {
|
||||
IMAQdxCameraControlModeController,
|
||||
IMAQdxCameraControlModeListener,
|
||||
IMAQdxCameraControlModeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxCameraControlMode;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Buffer Number Mode Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxBufferNumberMode_enum {
|
||||
IMAQdxBufferNumberModeNext,
|
||||
IMAQdxBufferNumberModeLast,
|
||||
IMAQdxBufferNumberModeBufferNumber,
|
||||
IMAQdxBufferNumberModeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxBufferNumberMode;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Plug n Play Event Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxPnpEvent_enum {
|
||||
IMAQdxPnpEventCameraAttached,
|
||||
IMAQdxPnpEventCameraDetached,
|
||||
IMAQdxPnpEventBusReset,
|
||||
IMAQdxPnpEventGuard = 0xFFFFFFFF,
|
||||
} IMAQdxPnpEvent;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Bayer Pattern Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxBayerPattern_enum {
|
||||
IMAQdxBayerPatternNone,
|
||||
IMAQdxBayerPatternGB,
|
||||
IMAQdxBayerPatternGR,
|
||||
IMAQdxBayerPatternBG,
|
||||
IMAQdxBayerPatternRG,
|
||||
IMAQdxBayerPatternHardware,
|
||||
IMAQdxBayerPatternGuard = 0xFFFFFFFF,
|
||||
} IMAQdxBayerPattern;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Bayer Decode Algorithm Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxBayerAlgorithm_enum {
|
||||
IMAQdxBayerAlgorithmBilinear,
|
||||
IMAQdxBayerAlgorithmVNG,
|
||||
IMAQdxBayerAlgorithmGuard = 0xFFFFFFFF,
|
||||
} IMAQdxBayerAlgorithm;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Output Image Types -- Values match Vision Development Module image types
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxOutputImageType_enum {
|
||||
IMAQdxOutputImageTypeU8 = 0,
|
||||
IMAQdxOutputImageTypeI16 = 1,
|
||||
IMAQdxOutputImageTypeU16 = 7,
|
||||
IMAQdxOutputImageTypeRGB32 = 4,
|
||||
IMAQdxOutputImageTypeRGB64 = 6,
|
||||
IMAQdxOutputImageTypeAuto = 0x7FFFFFFF,
|
||||
IMAQdxOutputImageTypeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxOutputImageType;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Controller Destination Mode Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxDestinationMode_enum {
|
||||
IMAQdxDestinationModeUnicast,
|
||||
IMAQdxDestinationModeBroadcast,
|
||||
IMAQdxDestinationModeMulticast,
|
||||
IMAQdxDestinationModeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxDestinationMode;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Attribute Type Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxAttributeType_enum {
|
||||
IMAQdxAttributeTypeU32,
|
||||
IMAQdxAttributeTypeI64,
|
||||
IMAQdxAttributeTypeF64,
|
||||
IMAQdxAttributeTypeString,
|
||||
IMAQdxAttributeTypeEnum,
|
||||
IMAQdxAttributeTypeBool,
|
||||
IMAQdxAttributeTypeCommand,
|
||||
IMAQdxAttributeTypeBlob,
|
||||
IMAQdxAttributeTypeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxAttributeType;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Value Type Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxValueType_enum {
|
||||
IMAQdxValueTypeU32,
|
||||
IMAQdxValueTypeI64,
|
||||
IMAQdxValueTypeF64,
|
||||
IMAQdxValueTypeString,
|
||||
IMAQdxValueTypeEnumItem,
|
||||
IMAQdxValueTypeBool,
|
||||
IMAQdxValueTypeDisposableString,
|
||||
IMAQdxValueTypeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxValueType;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Interface File Flags Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxInterfaceFileFlags_enum {
|
||||
IMAQdxInterfaceFileFlagsConnected = 0x1,
|
||||
IMAQdxInterfaceFileFlagsDirty = 0x2,
|
||||
IMAQdxInterfaceFileFlagsGuard = 0xFFFFFFFF,
|
||||
} IMAQdxInterfaceFileFlags;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Overwrite Mode Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxOverwriteMode_enum {
|
||||
IMAQdxOverwriteModeGetOldest = 0x0,
|
||||
IMAQdxOverwriteModeFail = 0x2,
|
||||
IMAQdxOverwriteModeGetNewest = 0x3,
|
||||
IMAQdxOverwriteModeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxOverwriteMode;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Incomplete Buffer Mode Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxIncompleteBufferMode_enum {
|
||||
IMAQdxIncompleteBufferModeIgnore,
|
||||
IMAQdxIncompleteBufferModeFail,
|
||||
IMAQdxIncompleteBufferModeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxIncompleteBufferMode;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Lost Packet Mode Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxLostPacketMode_enum {
|
||||
IMAQdxLostPacketModeIgnore,
|
||||
IMAQdxLostPacketModeFail,
|
||||
IMAQdxLostPacketModeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxLostPacketMode;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Attribute Visibility Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxAttributeVisibility_enum {
|
||||
IMAQdxAttributeVisibilitySimple = 0x00001000,
|
||||
IMAQdxAttributeVisibilityIntermediate = 0x00002000,
|
||||
IMAQdxAttributeVisibilityAdvanced = 0x00004000,
|
||||
IMAQdxAttributeVisibilityGuard = 0xFFFFFFFF,
|
||||
} IMAQdxAttributeVisibility;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Stream Channel Mode Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxStreamChannelMode_enum {
|
||||
IMAQdxStreamChannelModeAutomatic,
|
||||
IMAQdxStreamChannelModeManual,
|
||||
IMAQdxStreamChannelModeGuard = 0xFFFFFFFF,
|
||||
} IMAQdxStreamChannelMode;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Pixel Signedness Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxPixelSignedness_enum {
|
||||
IMAQdxPixelSignednessUnsigned,
|
||||
IMAQdxPixelSignednessSigned,
|
||||
IMAQdxPixelSignednessHardware,
|
||||
IMAQdxPixelSignednessGuard = 0xFFFFFFFF,
|
||||
} IMAQdxPixelSignedness;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// USB Connection Speed Enumeration
|
||||
//==============================================================================
|
||||
typedef enum IMAQdxUSBConnectionSpeed_enum {
|
||||
IMAQdxUSBConnectionSpeedLow = 1,
|
||||
IMAQdxUSBConnectionSpeedFull = 2,
|
||||
IMAQdxUSBConnectionSpeedHigh = 4,
|
||||
IMAQdxUSBConnectionSpeedSuper = 8,
|
||||
IMAQdxUSBConnectionSpeedGuard = 0xFFFFFFFF,
|
||||
} IMAQdxUSBConnectionSpeed;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// CVI Structures
|
||||
//==============================================================================
|
||||
#pragma pack(push, 4)
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Camera Information Structure
|
||||
//==============================================================================
|
||||
typedef struct IMAQdxCameraInformation_struct {
|
||||
uInt32 Type;
|
||||
uInt32 Version;
|
||||
uInt32 Flags;
|
||||
uInt32 SerialNumberHi;
|
||||
uInt32 SerialNumberLo;
|
||||
IMAQdxBusType BusType;
|
||||
char InterfaceName[IMAQDX_MAX_API_STRING_LENGTH];
|
||||
char VendorName[IMAQDX_MAX_API_STRING_LENGTH];
|
||||
char ModelName[IMAQDX_MAX_API_STRING_LENGTH];
|
||||
char CameraFileName[IMAQDX_MAX_API_STRING_LENGTH];
|
||||
char CameraAttributeURL[IMAQDX_MAX_API_STRING_LENGTH];
|
||||
} IMAQdxCameraInformation;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Camera File Structure
|
||||
//==============================================================================
|
||||
typedef struct IMAQdxCameraFile_struct {
|
||||
uInt32 Type;
|
||||
uInt32 Version;
|
||||
char FileName[IMAQDX_MAX_API_STRING_LENGTH];
|
||||
} IMAQdxCameraFile;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Attribute Information Structure
|
||||
//==============================================================================
|
||||
typedef struct IMAQdxAttributeInformation_struct {
|
||||
IMAQdxAttributeType Type;
|
||||
bool32 Readable;
|
||||
bool32 Writable;
|
||||
char Name[IMAQDX_MAX_API_STRING_LENGTH];
|
||||
} IMAQdxAttributeInformation;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Enumeration Item Structure
|
||||
//==============================================================================
|
||||
typedef struct IMAQdxEnumItem_struct {
|
||||
uInt32 Value;
|
||||
uInt32 Reserved;
|
||||
char Name[IMAQDX_MAX_API_STRING_LENGTH];
|
||||
} IMAQdxEnumItem;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Camera Information Structure
|
||||
//==============================================================================
|
||||
typedef IMAQdxEnumItem IMAQdxVideoMode;
|
||||
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Callbacks
|
||||
//==============================================================================
|
||||
typedef uInt32 (NI_FUNC *FrameDoneEventCallbackPtr)(IMAQdxSession id, uInt32 bufferNumber, void* callbackData);
|
||||
typedef uInt32 (NI_FUNC *PnpEventCallbackPtr)(IMAQdxSession id, IMAQdxPnpEvent pnpEvent, void* callbackData);
|
||||
typedef void (NI_FUNC *AttributeUpdatedEventCallbackPtr)(IMAQdxSession id, const char* name, void* callbackData);
|
||||
|
||||
#endif //niimaqdx_types
|
||||
//==============================================================================
|
||||
// Attributes
|
||||
//==============================================================================
|
||||
#define IMAQdxAttributeBaseAddress "CameraInformation::BaseAddress" // Read only. Gets the base address of the camera registers.
|
||||
#define IMAQdxAttributeBusType "CameraInformation::BusType" // Read only. Gets the bus type of the camera.
|
||||
#define IMAQdxAttributeModelName "CameraInformation::ModelName" // Read only. Returns the model name.
|
||||
#define IMAQdxAttributeSerialNumberHigh "CameraInformation::SerialNumberHigh" // Read only. Gets the upper 32-bits of the camera 64-bit serial number.
|
||||
#define IMAQdxAttributeSerialNumberLow "CameraInformation::SerialNumberLow" // Read only. Gets the lower 32-bits of the camera 64-bit serial number.
|
||||
#define IMAQdxAttributeVendorName "CameraInformation::VendorName" // Read only. Returns the vendor name.
|
||||
#define IMAQdxAttributeHostIPAddress "CameraInformation::HostIPAddress" // Read only. Returns the host adapter IP address.
|
||||
#define IMAQdxAttributeIPAddress "CameraInformation::IPAddress" // Read only. Returns the IP address.
|
||||
#define IMAQdxAttributePrimaryURLString "CameraInformation::PrimaryURLString" // Read only. Gets the camera's primary URL string.
|
||||
#define IMAQdxAttributeSecondaryURLString "CameraInformation::SecondaryURLString" // Read only. Gets the camera's secondary URL string.
|
||||
#define IMAQdxAttributeAcqInProgress "StatusInformation::AcqInProgress" // Read only. Gets the current state of the acquisition. TRUE if acquiring; otherwise FALSE.
|
||||
#define IMAQdxAttributeLastBufferCount "StatusInformation::LastBufferCount" // Read only. Gets the number of transferred buffers.
|
||||
#define IMAQdxAttributeLastBufferNumber "StatusInformation::LastBufferNumber" // Read only. Gets the last cumulative buffer number transferred.
|
||||
#define IMAQdxAttributeLostBufferCount "StatusInformation::LostBufferCount" // Read only. Gets the number of lost buffers during an acquisition session.
|
||||
#define IMAQdxAttributeLostPacketCount "StatusInformation::LostPacketCount" // Read only. Gets the number of lost packets during an acquisition session.
|
||||
#define IMAQdxAttributeRequestedResendPackets "StatusInformation::RequestedResendPacketCount" // Read only. Gets the number of packets requested to be resent during an acquisition session.
|
||||
#define IMAQdxAttributeReceivedResendPackets "StatusInformation::ReceivedResendPackets" // Read only. Gets the number of packets that were requested to be resent during an acquisition session and were completed.
|
||||
#define IMAQdxAttributeHandledEventCount "StatusInformation::HandledEventCount" // Read only. Gets the number of handled events during an acquisition session.
|
||||
#define IMAQdxAttributeLostEventCount "StatusInformation::LostEventCount" // Read only. Gets the number of lost events during an acquisition session.
|
||||
#define IMAQdxAttributeBayerGainB "AcquisitionAttributes::Bayer::GainB" // Sets/gets the white balance gain for the blue component of the Bayer conversion.
|
||||
#define IMAQdxAttributeBayerGainG "AcquisitionAttributes::Bayer::GainG" // Sets/gets the white balance gain for the green component of the Bayer conversion.
|
||||
#define IMAQdxAttributeBayerGainR "AcquisitionAttributes::Bayer::GainR" // Sets/gets the white balance gain for the red component of the Bayer conversion.
|
||||
#define IMAQdxAttributeBayerPattern "AcquisitionAttributes::Bayer::Pattern" // Sets/gets the Bayer pattern to use.
|
||||
#define IMAQdxAttributeStreamChannelMode "AcquisitionAttributes::Controller::StreamChannelMode" // Gets/sets the mode for allocating a FireWire stream channel.
|
||||
#define IMAQdxAttributeDesiredStreamChannel "AcquisitionAttributes::Controller::DesiredStreamChannel" // Gets/sets the stream channel to manually allocate.
|
||||
#define IMAQdxAttributeFrameInterval "AcquisitionAttributes::FrameInterval" // Read only. Gets the duration in milliseconds between successive frames.
|
||||
#define IMAQdxAttributeIgnoreFirstFrame "AcquisitionAttributes::IgnoreFirstFrame" // Gets/sets the video delay of one frame between starting the camera and receiving the video feed.
|
||||
#define IMAQdxAttributeOffsetX "OffsetX" // Gets/sets the left offset of the image.
|
||||
#define IMAQdxAttributeOffsetY "OffsetY" // Gets/sets the top offset of the image.
|
||||
#define IMAQdxAttributeWidth "Width" // Gets/sets the width of the image.
|
||||
#define IMAQdxAttributeHeight "Height" // Gets/sets the height of the image.
|
||||
#define IMAQdxAttributePixelFormat "PixelFormat" // Gets/sets the pixel format of the source sensor.
|
||||
#define IMAQdxAttributePacketSize "PacketSize" // Gets/sets the packet size in bytes.
|
||||
#define IMAQdxAttributePayloadSize "PayloadSize" // Gets/sets the frame size in bytes.
|
||||
#define IMAQdxAttributeSpeed "AcquisitionAttributes::Speed" // Gets/sets the transfer speed in Mbps for a FireWire packet.
|
||||
#define IMAQdxAttributeShiftPixelBits "AcquisitionAttributes::ShiftPixelBits" // Gets/sets the alignment of 16-bit cameras. Downshift the pixel bits if the camera returns most significant bit-aligned data.
|
||||
#define IMAQdxAttributeSwapPixelBytes "AcquisitionAttributes::SwapPixelBytes" // Gets/sets the endianness of 16-bit cameras. Swap the pixel bytes if the camera returns little endian data.
|
||||
#define IMAQdxAttributeOverwriteMode "AcquisitionAttributes::OverwriteMode" // Gets/sets the overwrite mode, used to determine acquisition when an image transfer cannot be completed due to an overwritten internal buffer.
|
||||
#define IMAQdxAttributeTimeout "AcquisitionAttributes::Timeout" // Gets/sets the timeout value in milliseconds, used to abort an acquisition when the image transfer cannot be completed within the delay.
|
||||
#define IMAQdxAttributeVideoMode "AcquisitionAttributes::VideoMode" // Gets/sets the video mode for a camera.
|
||||
#define IMAQdxAttributeBitsPerPixel "AcquisitionAttributes::BitsPerPixel" // Gets/sets the actual bits per pixel. For 16-bit components, this represents the actual bit depth (10-, 12-, 14-, or 16-bit).
|
||||
#define IMAQdxAttributePixelSignedness "AcquisitionAttributes::PixelSignedness" // Gets/sets the signedness of the pixel. For 16-bit components, this represents the actual pixel signedness (Signed, or Unsigned).
|
||||
#define IMAQdxAttributeReserveDualPackets "AcquisitionAttributes::ReserveDualPackets" // Gets/sets if dual packets will be reserved for a very large FireWire packet.
|
||||
#define IMAQdxAttributeReceiveTimestampMode "AcquisitionAttributes::ReceiveTimestampMode" // Gets/sets the mode for timestamping images received by the driver.
|
||||
#define IMAQdxAttributeActualPeakBandwidth "AcquisitionAttributes::AdvancedEthernet::BandwidthControl::ActualPeakBandwidth" // Read only. Returns the actual maximum peak bandwidth the camera will be configured to use.
|
||||
#define IMAQdxAttributeDesiredPeakBandwidth "AcquisitionAttributes::AdvancedEthernet::BandwidthControl::DesiredPeakBandwidth" // Gets/sets the desired maximum peak bandwidth the camera should use.
|
||||
#define IMAQdxAttributeDestinationMode "AcquisitionAttributes::AdvancedEthernet::Controller::DestinationMode" // Gets/Sets where the camera is instructed to send the image stream.
|
||||
#define IMAQdxAttributeDestinationMulticastAddress "AcquisitionAttributes::AdvancedEthernet::Controller::DestinationMulticastAddress" // Gets/Sets the multicast address the camera should send data in multicast mode.
|
||||
#define IMAQdxAttributeEventsEnabled "AcquisitionAttributes::AdvancedEthernet::EventParameters::EventsEnabled" // Gets/Sets if events will be handled.
|
||||
#define IMAQdxAttributeMaxOutstandingEvents "AcquisitionAttributes::AdvancedEthernet::EventParameters::MaxOutstandingEvents" // Gets/Sets the maximum number of outstanding events to queue.
|
||||
#define IMAQdxAttributeTestPacketEnabled "AcquisitionAttributes::AdvancedEthernet::TestPacketParameters::TestPacketEnabled" // Gets/Sets whether the driver will validate the image streaming settings using test packets prior to an acquisition
|
||||
#define IMAQdxAttributeTestPacketTimeout "AcquisitionAttributes::AdvancedEthernet::TestPacketParameters::TestPacketTimeout" // Gets/Sets the timeout for validating test packet reception (if enabled)
|
||||
#define IMAQdxAttributeMaxTestPacketRetries "AcquisitionAttributes::AdvancedEthernet::TestPacketParameters::MaxTestPacketRetries" // Gets/Sets the number of retries for validating test packet reception (if enabled)
|
||||
#define IMAQdxAttributeChunkDataDecodingEnabled "AcquisitionAttributes::ChunkDataDecoding::ChunkDataDecodingEnabled" // Gets/Sets whether the driver will decode any chunk data in the image stream
|
||||
#define IMAQdxAttributeChunkDataDecodingMaxElementSize "AcquisitionAttributes::ChunkDataDecoding::MaximumChunkCopySize" // Gets/Sets the maximum size of any single chunk data element that will be made available
|
||||
#define IMAQdxAttributeLostPacketMode "AcquisitionAttributes::AdvancedEthernet::LostPacketMode" // Gets/sets the behavior when the user extracts a buffer that has missing packets.
|
||||
#define IMAQdxAttributeMemoryWindowSize "AcquisitionAttributes::AdvancedEthernet::ResendParameters::MemoryWindowSize" // Gets/sets the size of the memory window of the camera in kilobytes. Should match the camera's internal buffer size.
|
||||
#define IMAQdxAttributeResendsEnabled "AcquisitionAttributes::AdvancedEthernet::ResendParameters::ResendsEnabled" // Gets/sets if resends will be issued for missing packets.
|
||||
#define IMAQdxAttributeResendThresholdPercentage "AcquisitionAttributes::AdvancedEthernet::ResendParameters::ResendThresholdPercentage" // Gets/sets the threshold of the packet processing window that will trigger packets to be resent.
|
||||
#define IMAQdxAttributeResendBatchingPercentage "AcquisitionAttributes::AdvancedEthernet::ResendParameters::ResendBatchingPercentage" // Gets/sets the percent of the packet resend threshold that will be issued as one group past the initial threshold sent in a single request.
|
||||
#define IMAQdxAttributeMaxResendsPerPacket "AcquisitionAttributes::AdvancedEthernet::ResendParameters::MaxResendsPerPacket" // Gets/sets the maximum number of resend requests that will be issued for a missing packet.
|
||||
#define IMAQdxAttributeResendResponseTimeout "AcquisitionAttributes::AdvancedEthernet::ResendParameters::ResendResponseTimeout" // Gets/sets the time to wait for a resend request to be satisfied before sending another.
|
||||
#define IMAQdxAttributeNewPacketTimeout "AcquisitionAttributes::AdvancedEthernet::ResendParameters::NewPacketTimeout" // Gets/sets the time to wait for new packets to arrive in a partially completed image before assuming the rest of the image was lost.
|
||||
#define IMAQdxAttributeMissingPacketTimeout "AcquisitionAttributes::AdvancedEthernet::ResendParameters::MissingPacketTimeout" // Gets/sets the time to wait for a missing packet before issuing a resend.
|
||||
#define IMAQdxAttributeResendTimerResolution "AcquisitionAttributes::AdvancedEthernet::ResendParameters::ResendTimerResolution" // Gets/sets the resolution of the packet processing system that is used for all packet-related timeouts.
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// Functions
|
||||
//==============================================================================
|
||||
IMAQdxError NI_FUNC IMAQdxSnap(IMAQdxSession id, Image* image);
|
||||
IMAQdxError NI_FUNC IMAQdxConfigureGrab(IMAQdxSession id);
|
||||
IMAQdxError NI_FUNC IMAQdxGrab(IMAQdxSession id, Image* image, bool32 waitForNextBuffer, uInt32* actualBufferNumber);
|
||||
IMAQdxError NI_FUNC IMAQdxSequence(IMAQdxSession id, Image* images[], uInt32 count);
|
||||
IMAQdxError NI_FUNC IMAQdxDiscoverEthernetCameras(const char* address, uInt32 timeout);
|
||||
IMAQdxError NI_FUNC IMAQdxEnumerateCameras(IMAQdxCameraInformation cameraInformationArray[], uInt32* count, bool32 connectedOnly);
|
||||
IMAQdxError NI_FUNC IMAQdxResetCamera(const char* name, bool32 resetAll);
|
||||
IMAQdxError NI_FUNC IMAQdxOpenCamera(const char* name, IMAQdxCameraControlMode mode, IMAQdxSession* id);
|
||||
IMAQdxError NI_FUNC IMAQdxCloseCamera(IMAQdxSession id);
|
||||
IMAQdxError NI_FUNC IMAQdxConfigureAcquisition(IMAQdxSession id, bool32 continuous, uInt32 bufferCount);
|
||||
IMAQdxError NI_FUNC IMAQdxStartAcquisition(IMAQdxSession id);
|
||||
IMAQdxError NI_FUNC IMAQdxGetImage(IMAQdxSession id, Image* image, IMAQdxBufferNumberMode mode, uInt32 desiredBufferNumber, uInt32* actualBufferNumber);
|
||||
IMAQdxError NI_FUNC IMAQdxGetImageData(IMAQdxSession id, void* buffer, uInt32 bufferSize, IMAQdxBufferNumberMode mode, uInt32 desiredBufferNumber, uInt32* actualBufferNumber);
|
||||
IMAQdxError NI_FUNC IMAQdxStopAcquisition(IMAQdxSession id);
|
||||
IMAQdxError NI_FUNC IMAQdxUnconfigureAcquisition(IMAQdxSession id);
|
||||
IMAQdxError NI_FUNC IMAQdxEnumerateVideoModes(IMAQdxSession id, IMAQdxVideoMode videoModeArray[], uInt32* count, uInt32* currentMode);
|
||||
IMAQdxError NI_FUNC IMAQdxEnumerateAttributes(IMAQdxSession id, IMAQdxAttributeInformation attributeInformationArray[], uInt32* count, const char* root);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttribute(IMAQdxSession id, const char* name, IMAQdxValueType type, void* value);
|
||||
IMAQdxError NI_FUNCC IMAQdxSetAttribute(IMAQdxSession id, const char* name, IMAQdxValueType type, ...);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeMinimum(IMAQdxSession id, const char* name, IMAQdxValueType type, void* value);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeMaximum(IMAQdxSession id, const char* name, IMAQdxValueType type, void* value);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeIncrement(IMAQdxSession id, const char* name, IMAQdxValueType type, void* value);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeType(IMAQdxSession id, const char* name, IMAQdxAttributeType* type);
|
||||
IMAQdxError NI_FUNC IMAQdxIsAttributeReadable(IMAQdxSession id, const char* name, bool32* readable);
|
||||
IMAQdxError NI_FUNC IMAQdxIsAttributeWritable(IMAQdxSession id, const char* name, bool32* writable);
|
||||
IMAQdxError NI_FUNC IMAQdxEnumerateAttributeValues(IMAQdxSession id, const char* name, IMAQdxEnumItem list[], uInt32* size);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeTooltip(IMAQdxSession id, const char* name, char* tooltip, uInt32 length);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeUnits(IMAQdxSession id, const char* name, char* units, uInt32 length);
|
||||
IMAQdxError NI_FUNC IMAQdxRegisterFrameDoneEvent(IMAQdxSession id, uInt32 bufferInterval, FrameDoneEventCallbackPtr callbackFunction, void* callbackData);
|
||||
IMAQdxError NI_FUNC IMAQdxRegisterPnpEvent(IMAQdxSession id, IMAQdxPnpEvent event, PnpEventCallbackPtr callbackFunction, void* callbackData);
|
||||
IMAQdxError NI_FUNC IMAQdxWriteRegister(IMAQdxSession id, uInt32 offset, uInt32 value);
|
||||
IMAQdxError NI_FUNC IMAQdxReadRegister(IMAQdxSession id, uInt32 offset, uInt32* value);
|
||||
IMAQdxError NI_FUNC IMAQdxWriteMemory(IMAQdxSession id, uInt32 offset, const char* values, uInt32 count);
|
||||
IMAQdxError NI_FUNC IMAQdxReadMemory(IMAQdxSession id, uInt32 offset, char* values, uInt32 count);
|
||||
IMAQdxError NI_FUNC IMAQdxGetErrorString(IMAQdxError error, char* message, uInt32 messageLength);
|
||||
IMAQdxError NI_FUNC IMAQdxWriteAttributes(IMAQdxSession id, const char* filename);
|
||||
IMAQdxError NI_FUNC IMAQdxReadAttributes(IMAQdxSession id, const char* filename);
|
||||
IMAQdxError NI_FUNC IMAQdxResetEthernetCameraAddress(const char* name, const char* address, const char* subnet, const char* gateway, uInt32 timeout);
|
||||
IMAQdxError NI_FUNC IMAQdxEnumerateAttributes2(IMAQdxSession id, IMAQdxAttributeInformation attributeInformationArray[], uInt32* count, const char* root, IMAQdxAttributeVisibility visibility);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeVisibility(IMAQdxSession id, const char* name, IMAQdxAttributeVisibility* visibility);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeDescription(IMAQdxSession id, const char* name, char* description, uInt32 length);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeDisplayName(IMAQdxSession id, const char* name, char* displayName, uInt32 length);
|
||||
IMAQdxError NI_FUNC IMAQdxDispose(void* buffer);
|
||||
IMAQdxError NI_FUNC IMAQdxRegisterAttributeUpdatedEvent(IMAQdxSession id, const char* name, AttributeUpdatedEventCallbackPtr callbackFunction, void* callbackData);
|
||||
IMAQdxError NI_FUNC IMAQdxEnumerateAttributes3(IMAQdxSession id, IMAQdxAttributeInformation attributeInformationArray[], uInt32* count, const char* root, IMAQdxAttributeVisibility visibility);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif // ___niimaqdx_h___
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,63 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeU32(IMAQdxSession id, const char* name,
|
||||
uInt32* value);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeI64(IMAQdxSession id, const char* name,
|
||||
Int64* value);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeF64(IMAQdxSession id, const char* name,
|
||||
float64* value);
|
||||
IMAQdxError NI_FUNC
|
||||
IMAQdxGetAttributeString(IMAQdxSession id, const char* name,
|
||||
char value[IMAQDX_MAX_API_STRING_LENGTH]);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeEnum(IMAQdxSession id, const char* name,
|
||||
IMAQdxEnumItem* value);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeBool(IMAQdxSession id, const char* name,
|
||||
bool32* value);
|
||||
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeMinimumU32(IMAQdxSession id,
|
||||
const char* name,
|
||||
uInt32* value);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeMinimumI64(IMAQdxSession id,
|
||||
const char* name,
|
||||
Int64* value);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeMinimumF64(IMAQdxSession id,
|
||||
const char* name,
|
||||
float64* value);
|
||||
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeMaximumU32(IMAQdxSession id,
|
||||
const char* name,
|
||||
uInt32* value);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeMaximumI64(IMAQdxSession id,
|
||||
const char* name,
|
||||
Int64* value);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeMaximumF64(IMAQdxSession id,
|
||||
const char* name,
|
||||
float64* value);
|
||||
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeIncrementU32(IMAQdxSession id,
|
||||
const char* name,
|
||||
uInt32* value);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeIncrementI64(IMAQdxSession id,
|
||||
const char* name,
|
||||
Int64* value);
|
||||
IMAQdxError NI_FUNC IMAQdxGetAttributeIncrementF64(IMAQdxSession id,
|
||||
const char* name,
|
||||
float64* value);
|
||||
|
||||
IMAQdxError NI_FUNC IMAQdxSetAttributeU32(IMAQdxSession id, const char* name,
|
||||
uInt32 value);
|
||||
IMAQdxError NI_FUNC IMAQdxSetAttributeI64(IMAQdxSession id, const char* name,
|
||||
Int64 value);
|
||||
IMAQdxError NI_FUNC IMAQdxSetAttributeF64(IMAQdxSession id, const char* name,
|
||||
float64 value);
|
||||
IMAQdxError NI_FUNC IMAQdxSetAttributeString(IMAQdxSession id, const char* name,
|
||||
const char* value);
|
||||
IMAQdxError NI_FUNC IMAQdxSetAttributeEnum(IMAQdxSession id, const char* name,
|
||||
const IMAQdxEnumItem* value);
|
||||
IMAQdxError NI_FUNC IMAQdxSetAttributeBool(IMAQdxSession id, const char* name,
|
||||
bool32 value);
|
||||
@@ -1,5 +0,0 @@
|
||||
[IMAQdxGetAttributeString]
|
||||
outparams=value
|
||||
|
||||
[Block Comment]
|
||||
exclude=
|
||||
@@ -1,21 +0,0 @@
|
||||
IMAQdxGetAttributeU32
|
||||
IMAQdxGetAttributeI64
|
||||
IMAQdxGetAttributeF64
|
||||
IMAQdxGetAttributeString
|
||||
IMAQdxGetAttributeEnum
|
||||
IMAQdxGetAttributeBool
|
||||
IMAQdxGetAttributeMinimumU32
|
||||
IMAQdxGetAttributeMinimumI64
|
||||
IMAQdxGetAttributeMinimumF64
|
||||
IMAQdxGetAttributeMaximumU32
|
||||
IMAQdxGetAttributeMaximumI64
|
||||
IMAQdxGetAttributeMaximumF64
|
||||
IMAQdxGetAttributeIncrementU32
|
||||
IMAQdxGetAttributeIncrementI64
|
||||
IMAQdxGetAttributeIncrementF64
|
||||
IMAQdxSetAttributeU32
|
||||
IMAQdxSetAttributeI64
|
||||
IMAQdxSetAttributeF64
|
||||
IMAQdxSetAttributeString
|
||||
IMAQdxSetAttributeEnum
|
||||
IMAQdxSetAttributeBool
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,121 +0,0 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
try:
|
||||
import configparser
|
||||
except ImportError:
|
||||
import ConfigParser as configparser
|
||||
|
||||
from nivision_parse import *
|
||||
|
||||
|
||||
class StructSizerEmitter:
|
||||
def __init__(self, out, config, hname):
|
||||
self.out = out
|
||||
self.config = config
|
||||
print("""#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <{hname}>
|
||||
|
||||
int main()
|
||||
{{
|
||||
asm("#STRUCT_SIZER [_platform_]\\n");
|
||||
asm("#STRUCT_SIZER pointer=%0\\n" : : "n"((int)sizeof(void*)));
|
||||
""".format(hname=hname), file=self.out)
|
||||
|
||||
def finish(self):
|
||||
print("}", file=self.out)
|
||||
|
||||
def config_get(self, section, option, fallback):
|
||||
try:
|
||||
return self.config.get(section, option)
|
||||
except (ValueError, configparser.NoSectionError, configparser.NoOptionError):
|
||||
return fallback
|
||||
|
||||
def config_getboolean(self, section, option, fallback):
|
||||
try:
|
||||
return self.config.getboolean(section, option)
|
||||
except (ValueError, configparser.NoSectionError, configparser.NoOptionError):
|
||||
return fallback
|
||||
|
||||
def block_comment(self, comment):
|
||||
pass
|
||||
|
||||
def opaque_struct(self, name):
|
||||
pass
|
||||
|
||||
def define(self, name, value, comment):
|
||||
pass
|
||||
|
||||
def text(self, text):
|
||||
print(text, file=self.out)
|
||||
|
||||
def static_const(self, name, ctype, value):
|
||||
pass
|
||||
|
||||
def enum(self, name, values):
|
||||
pass
|
||||
|
||||
def typedef(self, name, typedef, arr):
|
||||
pass
|
||||
|
||||
def typedef_function(self, name, restype, params):
|
||||
pass
|
||||
|
||||
def function(self, name, restype, params):
|
||||
pass
|
||||
|
||||
def structunion(self, ctype, name, fields):
|
||||
if name in opaque_structs:
|
||||
return
|
||||
|
||||
print('asm("#STRUCT_SIZER [{name}]\\n");'.format(name=name), file=self.out)
|
||||
print('asm("#STRUCT_SIZER _SIZE_=%0\\n" : : "n"((int)sizeof({name})));'.format(name=name),
|
||||
file=self.out)
|
||||
|
||||
for fname, ftype, arr, comment in fields:
|
||||
if ':' in fname:
|
||||
continue # can't handle bitfields
|
||||
print(
|
||||
'asm("#STRUCT_SIZER {field}=%0\\n" : : "n"((int)offsetof({name}, {field})));'.format(
|
||||
name=name, field=fname), file=self.out)
|
||||
|
||||
def struct(self, name, fields):
|
||||
self.structunion("Structure", name, fields)
|
||||
|
||||
def union(self, name, fields):
|
||||
self.structunion("Union", name, fields)
|
||||
|
||||
|
||||
def generate(srcdir, configpath=None, hpath=None):
|
||||
# read config file
|
||||
config = configparser.ConfigParser()
|
||||
config.read(configpath)
|
||||
block_comment_exclude = set(x.strip() for x in
|
||||
config.get("Block Comment", "exclude").splitlines())
|
||||
|
||||
# open input file
|
||||
inf = open(hpath)
|
||||
|
||||
# prescan for undefined structures
|
||||
prescan_file(inf)
|
||||
inf.seek(0)
|
||||
|
||||
# generate
|
||||
with open("struct_sizer.c", "wt") as out:
|
||||
emit = StructSizerEmitter(out, config, os.path.basename(hpath))
|
||||
parse_file(emit, inf, block_comment_exclude)
|
||||
emit.finish()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 3:
|
||||
print("Usage: gen_struct_sizer.py <header.h> <config.ini>")
|
||||
exit(0)
|
||||
|
||||
fname = sys.argv[1]
|
||||
configname = sys.argv[2]
|
||||
|
||||
generate("", configname, fname)
|
||||
@@ -1,42 +0,0 @@
|
||||
#!/bin/bash
|
||||
#This script should be able to generate the JNI
|
||||
# bindings for NIVision. At some point,
|
||||
# it should be integrated into the build system.
|
||||
# Assumes running from allwpilib/wpilibj/wpilibJavaJNI/nivision
|
||||
|
||||
# Get structure sizes.
|
||||
python gen_struct_sizer.py ../../../wpilibc/wpilibC++Devices/include/nivision.h nivision_2011.ini
|
||||
arm-frc-linux-gnueabi-gcc -I../../../wpilibc/wpilibC++Devices/include -S struct_sizer.c
|
||||
cat struct_sizer.s | python get_struct_size.py > nivision_arm.ini
|
||||
|
||||
python gen_struct_sizer.py ../../../wpilibc/wpilibC++Devices/include/NIIMAQdx.h imaqdx.ini
|
||||
arm-frc-linux-gnueabi-gcc -I../../../wpilibc/wpilibC++Devices/include -S struct_sizer.c
|
||||
cat struct_sizer.s | python get_struct_size.py > imaqdx_arm.ini
|
||||
|
||||
# Get functions actually in the .so; some functions are in the header but
|
||||
# not the shared library!
|
||||
arm-frc-linux-gnueabi-nm -D ../../../ni-libraries/libnivision.so.14.0.0 | cut -c 12- | grep ^imaq > nivision_funcs.txt
|
||||
echo Priv_ReadJPEGString_C >> nivision_funcs.txt
|
||||
arm-frc-linux-gnueabi-nm -D ../../../ni-libraries/libniimaqdx.so.14.0.0 | cut -c 12- | grep ^IMAQdx > imaqdx_funcs.txt
|
||||
|
||||
# Run python generator.
|
||||
python gen_java.py \
|
||||
../../../wpilibc/wpilibC++Devices/include/nivision.h \
|
||||
nivision_arm.ini \
|
||||
nivision_2011.ini \
|
||||
nivision_funcs.txt \
|
||||
\
|
||||
../../../wpilibc/wpilibC++Devices/include/NIIMAQdx.h \
|
||||
imaqdx_arm.ini \
|
||||
imaqdx.ini \
|
||||
imaqdx_funcs.txt \
|
||||
\
|
||||
dxattr.h \
|
||||
imaqdx_arm.ini \
|
||||
dxattr.ini \
|
||||
dxattr_funcs.txt
|
||||
|
||||
# Stick generated files into appropriate places.
|
||||
cp NIVision.cpp ../lib/NIVisionJNI.cpp
|
||||
mkdir -p ../../wpilibJavaDevices/src/main/java/com/ni/vision
|
||||
cp *.java ../../wpilibJavaDevices/src/main/java/com/ni/vision/
|
||||
@@ -1,17 +0,0 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
for line in sys.stdin:
|
||||
line = line.strip()
|
||||
if not line.startswith("#STRUCT_SIZER"):
|
||||
continue
|
||||
line = line[14:]
|
||||
line = line.replace("#", "")
|
||||
print(line)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,80 +0,0 @@
|
||||
[Block Comment]
|
||||
exclude=
|
||||
Typedefs
|
||||
Forward Declare Data Structures
|
||||
Error Codes Enumeration
|
||||
Callbacks
|
||||
|
||||
; Error Codes Enumeration
|
||||
[IMAQdxError]
|
||||
|
||||
; Callbacks
|
||||
[FrameDoneEventCallbackPtr]
|
||||
exclude=True
|
||||
[PnpEventCallbackPtr]
|
||||
exclude=True
|
||||
[AttributeUpdatedEventCallbackPtr]
|
||||
exclude=True
|
||||
|
||||
; Functions
|
||||
[IMAQdxSequence]
|
||||
arraysize=images:count
|
||||
exclude=True
|
||||
[IMAQdxEnumerateCameras]
|
||||
arraysize=cameraInformationArray:count
|
||||
exclude=True
|
||||
[IMAQdxGetImageData]
|
||||
#arraysize=buffer:bufferSize
|
||||
[IMAQdxEnumerateVideoModes]
|
||||
arraysize=videoModeArray:count
|
||||
exclude=True
|
||||
[IMAQdxEnumerateAttributes]
|
||||
arraysize=attributeInformationArray:count
|
||||
exclude=True
|
||||
[IMAQdxGetAttribute]
|
||||
exclude=True
|
||||
[IMAQdxSetAttribute]
|
||||
# has to be manual due to "..."
|
||||
exclude=True
|
||||
[IMAQdxGetAttributeMinimum]
|
||||
exclude=True
|
||||
[IMAQdxGetAttributeMaximum]
|
||||
exclude=True
|
||||
[IMAQdxGetAttributeIncrement]
|
||||
exclude=True
|
||||
[IMAQdxEnumerateAttributeValues]
|
||||
arraysize=list:size
|
||||
exclude=True
|
||||
[IMAQdxGetAttributeTooltip]
|
||||
exclude=True
|
||||
[IMAQdxGetAttributeUnits]
|
||||
exclude=True
|
||||
[IMAQdxRegisterFrameDoneEvent]
|
||||
# callback
|
||||
exclude=True
|
||||
[IMAQdxRegisterPnpEvent]
|
||||
# callback
|
||||
exclude=True
|
||||
[IMAQdxWriteMemory]
|
||||
arraysize=values:count
|
||||
exclude=True
|
||||
[IMAQdxReadMemory]
|
||||
arraysize=values:count
|
||||
exclude=True
|
||||
[IMAQdxGetErrorString]
|
||||
exclude=True
|
||||
[IMAQdxEnumerateAttributes2]
|
||||
arraysize=attributeInformationArray:count
|
||||
exclude=True
|
||||
[IMAQdxGetAttributeDescription]
|
||||
exclude=True
|
||||
[IMAQdxGetAttributeDisplayName]
|
||||
exclude=True
|
||||
[IMAQdxDispose]
|
||||
exclude=True
|
||||
[IMAQdxRegisterAttributeUpdatedEvent]
|
||||
# callback
|
||||
exclude=True
|
||||
[IMAQdxEnumerateAttributes3]
|
||||
arraysize=attributeInformationArray:count
|
||||
exclude=True
|
||||
@@ -1,840 +0,0 @@
|
||||
;
|
||||
; [name]
|
||||
; arraysize -- comma separated list of "param:numParam" where param is the
|
||||
; name of the pointer parameter, and numParam is the name of
|
||||
; the parameter that contains the array size for the pointer
|
||||
; retarraysize -- name of the pass-by-reference parameter that on function
|
||||
; return contains the array size of the returned pointer
|
||||
; exclude -- if True, no code is output for this name (full custom)
|
||||
; underscore -- if True, only underscored raw wrapper is output (partial custom)
|
||||
; outparams -- comma separated list of output parameter names
|
||||
; inparams -- comma separated list of parameter names that are input
|
||||
; parameters (e.g. not output parameters)
|
||||
; defaults -- comma separated list of "param:default" where param is the
|
||||
; parameter name and default is the default value
|
||||
; exclude_members -- for structures, members to not emit
|
||||
; nullok -- comma separated list of parameter names that may be null
|
||||
; retref -- parameter that (if non-null) is returned as a reference
|
||||
; retunowned -- if True, return value should not be owned
|
||||
;
|
||||
; The generator code auto-detects many parameters, so this file is only needed
|
||||
; for overriding the auto-detected behavior.
|
||||
|
||||
; defines
|
||||
[IMAQ_IMPORT]
|
||||
exclude=True
|
||||
[IMAQ_FUNC]
|
||||
exclude=True
|
||||
[IMAQ_STDCALL]
|
||||
exclude=True
|
||||
[IMAQ_CALLBACK]
|
||||
exclude=True
|
||||
[IMAQ_DEFAULT_LEARNING_MODE]
|
||||
exclude=True
|
||||
[ERR_INVALID_COLORCOMPLEXITY]
|
||||
exclude=True
|
||||
|
||||
; structures
|
||||
[PolyModel]
|
||||
arraysize=kCoeffs:numKCoeffs
|
||||
[CalibrationReferencePoints]
|
||||
arraysize=pixelCoords:numPixelCoords,realCoords:numRealCoords
|
||||
[GetCameraParametersReport]
|
||||
#TODO: projectionMatrix:projectionMatrixRows*projectionMatrixCols
|
||||
exclude_members=projectionMatrix
|
||||
[GetCalibrationInfoReport]
|
||||
#TODO: errorMap:errorMapRows*errorMapCols
|
||||
exclude_members=errorMap
|
||||
[ContourFitSplineReport]
|
||||
arraysize=points:numberOfPoints
|
||||
[ContourFitPolynomialReport]
|
||||
arraysize=bestFit:numberOfPoints,polynomialCoefficients:numberOfCoefficients
|
||||
[SetupMatchPatternData]
|
||||
arraysize=matchSetupData:numMatchSetupData
|
||||
[ContourInfoReport]
|
||||
arraysize=pointsPixel:numPointsPixel,pointsReal:numPointsReal,curvaturePixel:numCurvaturePixel,curvatureReal:numCurvatureReal
|
||||
[SupervisedColorSegmentationReport]
|
||||
arraysize=labelOut:numLabelOut
|
||||
[LabelToROIReport]
|
||||
arraysize=roiArray:numOfROIs,labelsOutArray:numOfLabels,isTooManyVectorsArray:isTooManyVectorsArraySize
|
||||
[ClassifiedCurve]
|
||||
arraysize=curvePoints:numCurvePoints
|
||||
[CurvatureAnalysisReport]
|
||||
arraysize=curves:numCurves
|
||||
[ComputeDistancesReport]
|
||||
arraysize=distances:numDistances,distancesReal:numDistancesReal
|
||||
[ClassifiedDisparity]
|
||||
arraysize=templateSubsection:numTemplateSubsection,targetSubsection:numTargetSubsection
|
||||
[ClassifyDistancesReport]
|
||||
arraysize=classifiedDistances:numClassifiedDistances
|
||||
[ContourComputeCurvatureReport]
|
||||
arraysize=curvaturePixel:numCurvaturePixel,curvatureReal:numCurvatureReal
|
||||
[ExtractContourReport]
|
||||
arraysize=contourPoints:numContourPoints,sourcePoints:numSourcePoints
|
||||
[ExtractTextureFeaturesReport]
|
||||
arraysize=waveletBands:numWaveletBands
|
||||
#TODO: textureFeatures:textureFeaturesRows:textureFeaturesCols
|
||||
exclude_members=textureFeatures
|
||||
[WaveletBandsReport]
|
||||
#TODO: LLBand:rows:cols
|
||||
#TODO: LHBand:rows:cols
|
||||
#TODO: HLBand:rows:cols
|
||||
#TODO: HHBand:rows:cols
|
||||
#TODO: LLLBand:rows:cols
|
||||
#TODO: LLHBand:rows:cols
|
||||
#TODO: LHHBand:rows:cols
|
||||
exclude_members=LLBand,LHBand,HLBand,HHBand,LLLBand,LLHBand,LHHBand
|
||||
[MeasureParticlesReport]
|
||||
#TODO: pixelMeasurements:numParticles:numMeasurements
|
||||
#TODO: calibratedMeasurements:numParticles:numMeasurements
|
||||
exclude_members=pixelMeasurements,calibratedMeasurements
|
||||
[ClassifierReportAdvanced]
|
||||
arraysize=allScores:allScoresSize,sampleScores:sampleScoresSize
|
||||
[FindEdgeReport]
|
||||
arraysize=straightEdges:numStraightEdges
|
||||
[ReadTextReport3]
|
||||
arraysize=characterReport:numCharacterReports
|
||||
[EdgeReport2]
|
||||
arraysize=edges:numEdges,gradientInfo:numGradientInfo
|
||||
[ConcentricRakeReport2]
|
||||
arraysize=firstEdges:numFirstEdges,lastEdges:numLastEdges,searchArcs:numSearchArcs
|
||||
[SpokeReport2]
|
||||
arraysize=firstEdges:numFirstEdges,lastEdges:numLastEdges,searchLines:numSearchLines
|
||||
[RakeReport2]
|
||||
arraysize=firstEdges:numFirstEdges,lastEdges:numLastEdges,searchLines:numSearchLines
|
||||
[QRCodeDataToken]
|
||||
arraysize=data:dataLength
|
||||
[StraightEdgeReport2]
|
||||
arraysize=straightEdges:numStraightEdges,searchLines:numSearchLines
|
||||
[StraightEdge]
|
||||
arraysize=usedEdges:numUsedEdges
|
||||
[QRCodeReport]
|
||||
arraysize=data:dataLength,tokenizedData:sizeOfTokenizedData
|
||||
[DataMatrixReport]
|
||||
arraysize=data:dataLength
|
||||
[ReadTextReport2]
|
||||
arraysize=characterReport:numCharacterReports
|
||||
[FeatureData]
|
||||
arraysize=contourPoints:numContourPoints
|
||||
uniontype=feature:type:IMAQ_CIRCLE_FEATURE=circle:IMAQ_ELLIPSE_FEATURE=ellipse:IMAQ_CONST_CURVE_FEATURE=constCurve:IMAQ_RECTANGLE_FEATURE=rectangle:IMAQ_LEG_FEATURE=leg:IMAQ_CORNER_FEATURE=corner:IMAQ_PARALLEL_LINE_PAIR_FEATURE=parallelLinePair:IMAQ_PAIR_OF_PARALLEL_LINE_PAIRS_FEATURE=pairOfParallelLinePairs:IMAQ_LINE_FEATURE=line:IMAQ_CLOSED_CURVE_FEATURE=closedCurve
|
||||
[GeometricPatternMatch2]
|
||||
arraysize=featureData:numFeatureData
|
||||
[ShapeDetectionOptions]
|
||||
arraysize=angleRanges:numAngleRanges
|
||||
[Curve]
|
||||
arraysize=points:numPoints
|
||||
[Barcode2DInfo]
|
||||
arraysize=data:dataLength
|
||||
[ClassifierAccuracyReport]
|
||||
arraysize=classNames:size,classAccuracy:size,classPredictiveValue:size
|
||||
#TODO: classificationDistribution:classPredictiveValue:size
|
||||
exclude_members=classificationDistribution
|
||||
[NearestNeighborTrainingReport]
|
||||
arraysize=allScores:allScoresSize
|
||||
#TODO: classDistancesTable
|
||||
exclude_members=classDistancesTable
|
||||
[ClassifierSampleInfo]
|
||||
arraysize=featureVector:featureVectorSize
|
||||
[ClassifierReport]
|
||||
arraysize=allScores:allScoresSize
|
||||
[MatchGeometricPatternOptions]
|
||||
arraysize=angleRanges:numAngleRanges
|
||||
[ConstructROIOptions2]
|
||||
arraysize=palette:numColors
|
||||
[BestEllipse2]
|
||||
arraysize=pointsUsed:numPointsUsed
|
||||
[BestCircle2]
|
||||
arraysize=pointsUsed:numPointsUsed
|
||||
[ReadTextOptions]
|
||||
arraysize=validChars:numValidChars
|
||||
[ReadTextReport]
|
||||
arraysize=characterReport:numCharacterReports
|
||||
[EdgeLocationReport]
|
||||
arraysize=edges:numEdges
|
||||
[ImageInfo]
|
||||
#TODO: imageStart
|
||||
exclude_members=reserved0,reserved1,imageStart
|
||||
[LCDReport]
|
||||
arraysize=segmentInfo:numCharacters
|
||||
exclude_members=reserved
|
||||
[LCDSegments]
|
||||
exclude_members=reserved
|
||||
[LearnColorPatternOptions]
|
||||
arraysize=colorsToIgnore:numColorsToIgnore
|
||||
[LinearAverages]
|
||||
arraysize=columnAverages:columnCount,rowAverages:rowCount,risingDiagAverages:risingDiagCount,fallingDiagAverages:fallingDiagCount
|
||||
[LineProfile]
|
||||
arraysize=profileData:dataCount
|
||||
[MatchColorPatternOptions]
|
||||
arraysize=angleRanges:numRanges
|
||||
[HistogramReport]
|
||||
arraysize=histogram:histogramCount
|
||||
[BestLine]
|
||||
arraysize=pointsUsed:numPointsUsed
|
||||
[CalibrationInfo]
|
||||
#TODO: errorMap:mapColumns*mapRows
|
||||
exclude_members=errorMap
|
||||
[CalibrationPoints]
|
||||
arraysize=pixelCoordinates:numCoordinates,realWorldCoordinates:numCoordinates
|
||||
[CaliperReport]
|
||||
exclude_members=reserved
|
||||
[ClosedContour]
|
||||
arraysize=points:numPoints
|
||||
[ColorInformation]
|
||||
arraysize=info:infoCount
|
||||
[ConcentricRakeReport]
|
||||
arraysize=rakeArcs:numArcs,firstEdges:numFirstEdges,lastEdges:numLastEdges,allEdges:numLinesWithEdges,linesWithEdges:numLinesWithEdges
|
||||
[ConstructROIOptions]
|
||||
arraysize=palette:numColors
|
||||
[ContourInfo]
|
||||
arraysize=points:numPoints
|
||||
[ContourInfo2]
|
||||
uniontype=structure:type:IMAQ_POINT=point:IMAQ_LINE=line:IMAQ_RECT=rect:IMAQ_OVAL=ovalBoundingBox:IMAQ_CLOSED_CONTOUR=closedContour:IMAQ_OPEN_CONTOUR=openContour:IMAQ_ANNULUS=annulus:IMAQ_ROTATED_RECT=rotatedRect
|
||||
[UserPointSymbol]
|
||||
#TODO: pixels:cols*rows
|
||||
exclude_members=pixels
|
||||
[MatchPatternOptions]
|
||||
arraysize=angleRanges:numRanges
|
||||
[OpenContour]
|
||||
arraysize=points:numPoints
|
||||
[QuantifyReport]
|
||||
arraysize=regions:regionCount
|
||||
[RakeReport]
|
||||
arraysize=rakeLines:numRakeLines,firstEdges:numFirstEdges,lastEdges:numLastEdges,allEdges:numLinesWithEdges,linesWithEdges:numLinesWithEdges
|
||||
[TransformReport]
|
||||
arraysize=points:numPoints,validPoints:numPoints
|
||||
[MeterArc]
|
||||
arraysize=arcCoordPoints:numOfArcCoordPoints
|
||||
[StructuringElement]
|
||||
#TODO: arraysize=kernel:matrixRows*matrixCols
|
||||
exclude_members=kernel
|
||||
[SpokeReport]
|
||||
arraysize=spokeLines:numSpokeLines,firstEdges:numFirstEdges,lastEdges:numLastEdges,allEdges:numLinesWithEdges,linesWithEdges:numLinesWithEdges
|
||||
[ToolWindowOptions]
|
||||
exclude_members=reserved2,reserved3,reserved4
|
||||
[EventCallback]
|
||||
exclude=True
|
||||
|
||||
; Logical functions
|
||||
; TODO: constant versions
|
||||
[imaqAndConstant]
|
||||
exclude=True
|
||||
[imaqCompareConstant]
|
||||
exclude=True
|
||||
[imaqLogicalDifferenceConstant]
|
||||
exclude=True
|
||||
[imaqNandConstant]
|
||||
exclude=True
|
||||
[imaqNorConstant]
|
||||
exclude=True
|
||||
[imaqOrConstant]
|
||||
exclude=True
|
||||
[imaqXnorConstant]
|
||||
exclude=True
|
||||
[imaqXorConstant]
|
||||
exclude=True
|
||||
|
||||
; Arithmetic functions
|
||||
; TODO: constant versions
|
||||
[imaqAbsoluteDifferenceConstant]
|
||||
exclude=True
|
||||
[imaqAddConstant]
|
||||
exclude=True
|
||||
[imaqAverageConstant]
|
||||
exclude=True
|
||||
[imaqDivideConstant2]
|
||||
exclude=True
|
||||
[imaqMaxConstant2]
|
||||
exclude=True
|
||||
[imaqMinConstant]
|
||||
exclude=True
|
||||
[imaqModuloConstant]
|
||||
exclude=True
|
||||
[imaqMultiplyConstant]
|
||||
exclude=True
|
||||
[imaqSubtractConstant]
|
||||
exclude=True
|
||||
|
||||
; Particle Analysis functions
|
||||
[imaqCountParticles]
|
||||
outparams=numParticles
|
||||
[imaqMeasureParticle]
|
||||
outparams=value
|
||||
[imaqMeasureParticles]
|
||||
arraysize=measurements:numMeasurements
|
||||
[imaqParticleFilter4]
|
||||
arraysize=criteria:criteriaCount
|
||||
outparams=numParticles
|
||||
nullok=roi
|
||||
|
||||
; Morphology functions
|
||||
[imaqFindCircles]
|
||||
retarraysize=numCircles
|
||||
[imaqLabel2]
|
||||
outparams=particleCount
|
||||
[imaqMorphology]
|
||||
nullok=structuringElement
|
||||
[imaqSeparation]
|
||||
nullok=structuringElement
|
||||
[imaqSimpleDistance]
|
||||
nullok=structuringElement
|
||||
[imaqSizeFilter]
|
||||
nullok=structuringElement
|
||||
|
||||
; Acquisition functions
|
||||
[imaqCopyFromRing]
|
||||
nullok=image,imageNumber
|
||||
outparams=imageNumber
|
||||
retref=image
|
||||
[imaqExtractFromRing]
|
||||
nullok=imageNumber
|
||||
outparams=imageNumber
|
||||
retunowned=True
|
||||
[imaqGrab]
|
||||
nullok=image
|
||||
retref=image
|
||||
[imaqSetupRing]
|
||||
arraysize=images:numImages
|
||||
inparams=images
|
||||
[imaqSetupSequence]
|
||||
arraysize=images:numImages
|
||||
inparams=images
|
||||
[imaqSnap]
|
||||
nullok=image
|
||||
retref=image
|
||||
|
||||
; Caliper functions
|
||||
[imaqCaliperTool]
|
||||
retarraysize=numEdgePairs
|
||||
arraysize=points:numPoints
|
||||
[imaqDetectExtremes]
|
||||
retarraysize=numExtremes
|
||||
arraysize=pixels:numPixels
|
||||
[imaqFindTransformRect2]
|
||||
outparams=baseSystem,newSystem,axisReport
|
||||
[imaqFindTransformRects2]
|
||||
outparams=baseSystem,newSystem,axisReport
|
||||
[imaqSimpleEdge]
|
||||
retarraysize=numEdges
|
||||
arraysize=points:numPoints
|
||||
|
||||
; Spatial Filters functions
|
||||
[imaqCannyEdgeFilter]
|
||||
nullok=options
|
||||
[imaqConvolve2]
|
||||
inparams=kernel
|
||||
exclude=True
|
||||
[imaqEdgeFilter]
|
||||
nullok=mask
|
||||
[imaqLowPass]
|
||||
nullok=mask
|
||||
[imaqMedianFilter]
|
||||
nullok=mask
|
||||
[imaqNthOrderFilter]
|
||||
nullok=mask
|
||||
|
||||
; Drawing functions
|
||||
[imaqDrawTextOnImage]
|
||||
nullok=options,fontNameUsed
|
||||
|
||||
; Interlacing functions
|
||||
[imaqInterlaceSeparate]
|
||||
nullok=odd,even
|
||||
|
||||
; Image Information functions
|
||||
[imaqEnumerateCustomKeys]
|
||||
retarraysize=size
|
||||
[imaqGetImageSize]
|
||||
nullok=width,height
|
||||
[imaqGetPixelAddress]
|
||||
underscored=True
|
||||
exclude=True
|
||||
[imaqReadCustomData]
|
||||
retsize=size
|
||||
retunowned=True
|
||||
[imaqWriteCustomData]
|
||||
size=data:size
|
||||
|
||||
; Display functions
|
||||
[imaqGetLastKey]
|
||||
nullok=keyPressed,windowNumber,modifiers
|
||||
[imaqGetSystemWindowHandle]
|
||||
exclude=True
|
||||
[imaqGetWindowCenterPos]
|
||||
outparams=centerPosition
|
||||
|
||||
; Image Manipulation functions
|
||||
[imaqCast]
|
||||
nullok=lookup
|
||||
exclude=True
|
||||
[imaqFlatten]
|
||||
retsize=size
|
||||
[imaqRotate2]
|
||||
# TODO because of PixelValue
|
||||
exclude=True
|
||||
[imaqShift]
|
||||
# TODO because of PixelValue
|
||||
exclude=True
|
||||
[imaqUnflatten]
|
||||
size=data:size
|
||||
|
||||
; File I/O functions
|
||||
[imaqGetAVIInfo]
|
||||
outparams=info
|
||||
[imaqGetFileInfo]
|
||||
nullok=calibrationUnit,calibrationX,calibrationY,width,height,imageType
|
||||
[imaqGetFilterNames]
|
||||
retarraysize=numFilters
|
||||
[imaqLoadImagePopup]
|
||||
retarraysize=numPaths
|
||||
[imaqReadAVIFrame]
|
||||
size=data:dataSize
|
||||
# unclear whether dataSize is input or output parameter
|
||||
exclude=True
|
||||
[imaqReadFile]
|
||||
;nullok=colorTable,numColors
|
||||
;arraysize=colorTable:numColors
|
||||
[imaqWriteAVIFrame]
|
||||
size=data:dataLength
|
||||
[imaqWriteBMPFile]
|
||||
nullok=colorTable
|
||||
defaults=colorTable:null
|
||||
[imaqWriteFile]
|
||||
nullok=colorTable
|
||||
defaults=colorTable:null
|
||||
[imaqWriteJPEGFile]
|
||||
nullok=colorTable
|
||||
defaults=colorTable:null
|
||||
inparams=colorTable
|
||||
[imaqWritePNGFile2]
|
||||
nullok=colorTable
|
||||
defaults=colorTable:null
|
||||
[imaqWriteTIFFFile]
|
||||
nullok=options,colorTable
|
||||
defaults=options:null,colorTable:null
|
||||
|
||||
; Analytic Geometry functions
|
||||
[imaqBuildCoordinateSystem]
|
||||
outparams=system
|
||||
[imaqFitCircle2]
|
||||
arraysize=points:numPoints
|
||||
[imaqFitEllipse2]
|
||||
arraysize=points:numPoints
|
||||
[imaqFitLine]
|
||||
arraysize=points:numPoints
|
||||
[imaqGetBisectingLine]
|
||||
outparams=bisectStart,bisectEnd
|
||||
[imaqGetIntersection]
|
||||
outparams=intersection
|
||||
[imaqGetMidLine]
|
||||
outparams=midLineStart,midLineEnd
|
||||
[imaqGetPerpendicularLine]
|
||||
outparams=perpLineStart,perpLineEnd
|
||||
[imaqGetPointsOnContour]
|
||||
retarraysize=numSegments
|
||||
[imaqGetPointsOnLine]
|
||||
retarraysize=numPoints
|
||||
[imaqInterpolatePoints]
|
||||
retarraysize=interpCount
|
||||
arraysize=points:numPoints
|
||||
|
||||
; Clipboard functions
|
||||
[imaqClipboardToImage]
|
||||
nullok=palette
|
||||
[imaqImageToClipboard]
|
||||
nullok=palette
|
||||
|
||||
; Image Management functions
|
||||
[imaqCreateImage]
|
||||
defaults=borderSize:0
|
||||
[imaqImageToArray]
|
||||
nullok=columns,rows
|
||||
underscored=True
|
||||
exclude=True
|
||||
|
||||
; Color Processing functions
|
||||
[imaqChangeColorSpace2]
|
||||
# TODO because of Color2
|
||||
exclude=True
|
||||
[imaqColorBCGTransform]
|
||||
nullok=redOptions,greenOptions,blueOptions,mask
|
||||
[imaqColorHistogram2]
|
||||
nullok=mask
|
||||
[imaqColorLookup]
|
||||
nullok=mask,plane1,plane2,plane3
|
||||
exclude=True
|
||||
[imaqColorThreshold]
|
||||
nullok=plane1Range,plane2Range,plane3Range
|
||||
|
||||
; Transform functions
|
||||
[imaqBCGTransform]
|
||||
nullok=mask
|
||||
[imaqEqualize]
|
||||
nullok=mask
|
||||
[imaqInverse]
|
||||
nullok=mask
|
||||
[imaqMathTransform]
|
||||
nullok=mask
|
||||
[imaqLookup2]
|
||||
nullok=mask
|
||||
exclude=True
|
||||
|
||||
; Window Management functions
|
||||
[imaqGetMousePos]
|
||||
nullok=position,windowNumber
|
||||
[imaqGetWindowBackground]
|
||||
outparams=backgroundColor
|
||||
[imaqGetWindowDisplayMapping]
|
||||
outparams=mapping
|
||||
[imaqGetWindowGrid]
|
||||
nullok=xResolution,yResolution
|
||||
[imaqGetWindowPos]
|
||||
outparams=position
|
||||
[imaqGetWindowSize]
|
||||
nullok=width,height
|
||||
[imaqSetWindowPalette]
|
||||
arraysize=palette:numColors
|
||||
nullok=palette
|
||||
|
||||
; Utilities functions
|
||||
; Many Make* functions are faster in native Python
|
||||
[imaqGetKernel]
|
||||
exclude=True
|
||||
[imaqMakeAnnulus]
|
||||
exclude=True
|
||||
[imaqMakePoint]
|
||||
exclude=True
|
||||
[imaqMakePointFloat]
|
||||
exclude=True
|
||||
[imaqMakeRect]
|
||||
exclude=True
|
||||
[imaqMakeRectFromRotatedRect]
|
||||
exclude=True
|
||||
[imaqMakeRotatedRect]
|
||||
exclude=True
|
||||
[imaqMakeRotatedRectFromRect]
|
||||
exclude=True
|
||||
[imaqMulticoreOptions]
|
||||
underscored=True
|
||||
|
||||
; Tool Window functions
|
||||
[imaqGetLastEvent]
|
||||
nullok=windowNumber,tool,rect
|
||||
outparams=type,tool,rect
|
||||
[imaqGetToolWindowHandle]
|
||||
exclude=True
|
||||
[imaqGetToolWindowPos]
|
||||
outparams=position
|
||||
[imaqSetEventCallback]
|
||||
exclude=True
|
||||
[imaqSetupToolWindow]
|
||||
nullok=options
|
||||
|
||||
; Meter functions
|
||||
[imaqReadMeter]
|
||||
outparams=endOfNeedle
|
||||
|
||||
; Calibration functions
|
||||
[imaqCorrectCalibratedImage]
|
||||
# TODO because of PixelValue
|
||||
exclude=True
|
||||
[imaqTransformPixelToRealWorld]
|
||||
arraysize=pixelCoordinates:numCoordinates
|
||||
[imaqTransformRealWorldToPixel]
|
||||
arraysize=realWorldCoordinates:numCoordinates
|
||||
|
||||
; Pixel Manipulation functions
|
||||
[imaqArrayToComplexPlane]
|
||||
exclude=True
|
||||
[imaqComplexPlaneToArray]
|
||||
nullok=columns,rows
|
||||
underscored=True
|
||||
exclude=True
|
||||
[imaqExtractColorPlanes]
|
||||
nullok=plane1,plane2,plane3
|
||||
[imaqFillImage]
|
||||
nullok=mask
|
||||
# TODO because of PixelValue
|
||||
exclude=True
|
||||
[imaqGetLine]
|
||||
nullok=numPoints
|
||||
underscored=True
|
||||
exclude=True
|
||||
[imaqGetPixel]
|
||||
outparams=value
|
||||
# TODO because of PixelValue
|
||||
exclude=True
|
||||
[imaqReplaceColorPlanes]
|
||||
nullok=plane1,plane2,plane3
|
||||
[imaqSetLine]
|
||||
underscored=True
|
||||
exclude=True
|
||||
[imaqSetPixel]
|
||||
# TODO because of PixelValue
|
||||
exclude=True
|
||||
|
||||
; Color Matching functions
|
||||
[imaqLearnColor]
|
||||
nullok=roi
|
||||
[imaqMatchColor]
|
||||
retarraysize=numScores
|
||||
nullok=roi
|
||||
|
||||
; Barcode I/O functions
|
||||
[imaqGradeDataMatrixBarcodeAIM]
|
||||
outparams=report
|
||||
[imaqReadBarcode]
|
||||
nullok=roi
|
||||
[imaqReadPDF417Barcode]
|
||||
retarraysize=numBarcodes
|
||||
[imaqReadQRCode]
|
||||
defaults=reserved:IMAQ_QR_NO_GRADING
|
||||
|
||||
; LCD functions
|
||||
[imaqFindLCDSegments]
|
||||
nullok=options
|
||||
[imaqReadLCD]
|
||||
nullok=options
|
||||
|
||||
; Shape Matching functions
|
||||
[imaqMatchShape]
|
||||
retarraysize=numMatches
|
||||
|
||||
; Contours functions
|
||||
[imaqAddClosedContour]
|
||||
arraysize=points:numPoints
|
||||
[imaqAddOpenContour]
|
||||
arraysize=points:numPoints
|
||||
[imaqGetContourColor]
|
||||
outparams=contourColor
|
||||
|
||||
; Regions of Interest functions
|
||||
[imaqGetROIBoundingBox]
|
||||
outparams=boundingBox
|
||||
[imaqGetROIColor]
|
||||
outparams=roiColor
|
||||
[imaqSetWindowROI]
|
||||
nullok=roi
|
||||
|
||||
; Image Analysis functions
|
||||
[imaqExtractCurves]
|
||||
retarraysize=numCurves
|
||||
[imaqHistogram]
|
||||
nullok=mask
|
||||
[imaqQuantify]
|
||||
nullok=mask
|
||||
|
||||
; Error Management functions
|
||||
[imaqClearError]
|
||||
exclude=True
|
||||
[imaqGetErrorText]
|
||||
exclude=True
|
||||
[imaqGetLastError]
|
||||
exclude=True
|
||||
[imaqGetLastErrorFunc]
|
||||
exclude=True
|
||||
[imaqSetError]
|
||||
nullok=function
|
||||
exclude=True
|
||||
|
||||
; Threshold functions
|
||||
[imaqMultithreshold]
|
||||
arraysize=ranges:numRanges
|
||||
|
||||
; Memory Management functions
|
||||
[imaqDispose]
|
||||
# This is done as a full-custom function
|
||||
exclude=True
|
||||
|
||||
; Pattern Matching functions
|
||||
[imaqDetectCircles]
|
||||
retarraysize=numMatchesReturned
|
||||
[imaqDetectEllipses]
|
||||
retarraysize=numMatchesReturned
|
||||
[imaqDetectLines]
|
||||
retarraysize=numMatchesReturned
|
||||
[imaqDetectRectangles]
|
||||
retarraysize=numMatchesReturned
|
||||
[imaqGetGeometricFeaturesFromCurves]
|
||||
retarraysize=numFeatures
|
||||
arraysize=curves:numCurves,featureTypes:numFeatureTypes
|
||||
[imaqGetGeometricTemplateFeatureInfo]
|
||||
retarraysize=numFeatures
|
||||
[imaqLearnMultipleGeometricPatterns]
|
||||
arraysize=patterns:numberOfPatterns
|
||||
exclude=True
|
||||
[imaqMatchColorPattern]
|
||||
retarraysize=numMatches
|
||||
[imaqMatchGeometricPattern2]
|
||||
retarraysize=numMatches
|
||||
[imaqMatchMultipleGeometricPatterns]
|
||||
retarraysize=numMatches
|
||||
[imaqReadMultipleGeometricPatternFile]
|
||||
underscored=True
|
||||
[imaqRefineMatches]
|
||||
retarraysize=numCandidatesOut
|
||||
arraysize=candidatesIn:numCandidatesIn
|
||||
[imaqMatchGeometricPattern3]
|
||||
retarraysize=numMatches
|
||||
[imaqMatchPattern3]
|
||||
retarraysize=numMatches
|
||||
nullok=options
|
||||
|
||||
; Overlay functions
|
||||
[imaqGetOverlayProperties]
|
||||
outparams=transformBehaviors
|
||||
[imaqMergeOverlay]
|
||||
arraysize=palette:numColors
|
||||
[imaqOverlayBitmap]
|
||||
underscored=True
|
||||
[imaqOverlayClosedContour]
|
||||
arraysize=points:numPoints
|
||||
[imaqOverlayOpenContour]
|
||||
arraysize=points:numPoints
|
||||
[imaqOverlayPoints]
|
||||
arraysize=points:numPoints,colors:numColors
|
||||
|
||||
; OCR functions
|
||||
[imaqVerifyPatterns]
|
||||
arraysize=expectedPatterns:patternCount
|
||||
retarraysize=numScores
|
||||
[imaqVerifyText]
|
||||
retarraysize=numScores
|
||||
|
||||
; Geometric Matching functions
|
||||
[imaqContourClassifyCurvature]
|
||||
arraysize=curvatureClasses:numCurvatureClasses
|
||||
[imaqContourClassifyDistances]
|
||||
arraysize=distanceRanges:numDistanceRanges
|
||||
[imaqContourSetupMatchPattern]
|
||||
arraysize=rangeSettings:numRangeSettings
|
||||
[imaqContourAdvancedSetupMatchPattern]
|
||||
arraysize=geometricOptions:numGeometricOptions
|
||||
|
||||
; Morphology Reconstruction functions
|
||||
[imaqGrayMorphologyReconstruct]
|
||||
arraysize=points:numOfPoints
|
||||
[imaqMorphologyReconstruct]
|
||||
arraysize=points:numOfPoints
|
||||
|
||||
; Texture functions
|
||||
[imaqClassificationTextureDefectOptions]
|
||||
exclude=True
|
||||
[imaqCooccurrenceMatrix]
|
||||
exclude=True
|
||||
[imaqExtractTextureFeatures]
|
||||
inparams=waveletBands
|
||||
exclude=True
|
||||
[imaqExtractWaveletBands]
|
||||
inparams=waveletBands
|
||||
exclude=True
|
||||
|
||||
; Regions of Interest Manipulation functions
|
||||
[imaqMaskToROI]
|
||||
nullok=withinLimit
|
||||
[imaqROIToMask]
|
||||
nullok=imageModel,inSpace
|
||||
[imaqLabelToROI]
|
||||
arraysize=labelsIn:numLabelsIn
|
||||
|
||||
; Morphology functions
|
||||
[imaqGrayMorphology]
|
||||
nullok=structuringElement
|
||||
|
||||
; Classification functions
|
||||
[imaqAddClassifierSample]
|
||||
arraysize=featureVector:vectorSize
|
||||
[imaqAdvanceClassify]
|
||||
arraysize=featureVector:vectorSize
|
||||
[imaqClassify]
|
||||
arraysize=featureVector:vectorSize
|
||||
[imaqGetColorClassifierOptions]
|
||||
outparams=options
|
||||
[imaqGetNearestNeighborOptions]
|
||||
outparams=options
|
||||
;[imaqReadClassifierFile]
|
||||
;[imaqWriteClassifierFile]
|
||||
|
||||
; Obsolete functions
|
||||
[imaqWritePNGFile]
|
||||
nullok=colorTable
|
||||
defaults=colorTable:null
|
||||
[imaqRotate]
|
||||
# TODO because of PixelValue
|
||||
exclude=True
|
||||
[imaqSelectParticles]
|
||||
retarraysize=selectedCount
|
||||
[imaqGetParticleInfo]
|
||||
retarraysize=reportCount
|
||||
[imaqEdgeTool]
|
||||
retarraysize=numEdges
|
||||
[imaqCircles]
|
||||
retarraysize=numCircles
|
||||
[imaqFitEllipse]
|
||||
arraysize=points:numPoints
|
||||
outparams=ellipse
|
||||
[imaqFitCircle]
|
||||
arraysize=points:numPoints
|
||||
outparams=circle
|
||||
[imaqChangeColorSpace]
|
||||
# TODO because of Color
|
||||
exclude=True
|
||||
[imaqMatchPattern]
|
||||
retarraysize=numMatches
|
||||
nullok=options
|
||||
[imaqLineGaugeTool]
|
||||
nullok=reference
|
||||
[imaqBestCircle]
|
||||
arraysize=points:numPoints
|
||||
outparams=center
|
||||
[imaqCoordinateReference]
|
||||
outparams=origin
|
||||
[imaqSetWindowOverlay]
|
||||
nullok=overlay
|
||||
[imaqGetCalibrationInfo]
|
||||
outparams=unit,xDistance,yDistance
|
||||
nullok=unit,xDistance,yDistance
|
||||
[imaqGetParticleClassifierOptions]
|
||||
outparams=preprocessingOptions,options
|
||||
[imaqConvolve]
|
||||
nullok=mask
|
||||
inparams=kernel
|
||||
exclude=True
|
||||
[imaqDivideConstant]
|
||||
# TODO because of PixelValue
|
||||
exclude=True
|
||||
[imaqLookup]
|
||||
nullok=mask
|
||||
exclude=True
|
||||
[imaqMatchPattern2]
|
||||
retarraysize=numMatches
|
||||
nullok=options
|
||||
[imaqMaxConstant]
|
||||
# TODO because of PixelValue
|
||||
exclude=True
|
||||
[imaqParticleFilter2]
|
||||
arraysize=criteria:criteriaCount
|
||||
[imaqEdgeTool2]
|
||||
retarraysize=numEdges
|
||||
[imaqReadDataMatrixBarcode]
|
||||
retarraysize=numBarcodes
|
||||
[imaqMatchGeometricPattern]
|
||||
retarraysize=numMatches
|
||||
[imaqColorHistogram]
|
||||
nullok=mask
|
||||
[Priv_ReadJPEGString_C]
|
||||
arraysize=string:stringLength
|
||||
inparams=image,string
|
||||
|
||||
; block comment exclusion list
|
||||
[Block Comment]
|
||||
exclude=
|
||||
Includes
|
||||
Control Defines
|
||||
Macros
|
||||
This accomplishes said task.
|
||||
If using Visual C++, force startup & shutdown code to run.
|
||||
Error Management functions
|
||||
Callback Function Type
|
||||
Backwards Compatibility
|
||||
Error Codes
|
||||
@@ -1,242 +0,0 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import re
|
||||
import traceback
|
||||
|
||||
__all__ = ["define_after_struct", "defined", "forward_structs", "opaque_structs", "enums",
|
||||
"structs", "prescan_file", "parse_file", "number_re", "constant_re"]
|
||||
|
||||
# parser regular expressions
|
||||
number_re = re.compile(r'-?[0-9]+')
|
||||
constant_re = re.compile(r'[A-Z0-9_]+')
|
||||
define_re = re.compile(r'^#define\s+(?P<name>(IMAQ|ERR)[A-Z0-9_]+)\s+(?P<value>.*)')
|
||||
enum_re = re.compile(r'^typedef\s+enum\s+(?P<name>[A-Za-z0-9]+)_enum\s*{')
|
||||
enum_value_re = re.compile(r'^\s*(?P<name>[A-Za-z0-9_]+)\s*(=\s*(?P<value>-?[0-9A-Fx]+))?\s*,?')
|
||||
struct_re = re.compile(r'^typedef\s+struct\s+(?P<name>[A-Za-z0-9]+)_struct\s*{')
|
||||
union_re = re.compile(r'^typedef\s+union\s+(?P<name>[A-Za-z0-9]+)_union\s*{')
|
||||
func_pointer_re = re.compile(
|
||||
r'\s*(?P<restype>[A-Za-z0-9_*]+)\s*\(\s*[A-Za-z0-9_]*\s*[*]\s*(?P<name>[A-Za-z0-9_]+)\s*\)\s*\((?P<params>[^)]*)\)')
|
||||
static_const_re = re.compile(
|
||||
r'^static\s+const\s+(?P<type>[A-Za-z0-9_]+)\s+(?P<name>[A-Za-z0-9_]+)\s*=\s*(?P<value>[^;]+);')
|
||||
function_re = re.compile(
|
||||
r'^((IMAQ|NI)_FUNC\s+)?(?P<restype>(const\s+)?[A-Za-z0-9_*]+)\s+((IMAQ_STDCALL|NI_FUNC[C]?)\s+)?(?P<name>[A-Za-z0-9_]+)\s*\((?P<params>[^)]*)\);')
|
||||
|
||||
# defines deferred until after structures
|
||||
define_after_struct = []
|
||||
defined = set()
|
||||
forward_structs = set()
|
||||
opaque_structs = set()
|
||||
enums = set()
|
||||
structs = set()
|
||||
|
||||
|
||||
def parse_cdecl(decl):
|
||||
decl = " ".join(decl.split())
|
||||
ctype, sep, name = decl.rpartition(' ')
|
||||
# look for array[]
|
||||
name, bracket, arr = name.partition('[')
|
||||
if arr:
|
||||
arr = arr[:-1]
|
||||
else:
|
||||
arr = None
|
||||
return name, ctype, arr
|
||||
|
||||
|
||||
def split_comment(line):
|
||||
if line.startswith('/*'):
|
||||
return "", ""
|
||||
parts = line.split('//', 1)
|
||||
code = parts[0].strip()
|
||||
comment = parts[1].strip() if len(parts) > 1 else None
|
||||
return code, comment
|
||||
|
||||
|
||||
def prescan_file(f):
|
||||
for line in f:
|
||||
code, comment = split_comment(line)
|
||||
if not code and not comment:
|
||||
continue
|
||||
|
||||
# typedef struct {
|
||||
m = struct_re.match(code)
|
||||
if m is not None:
|
||||
structs.add(m.group('name'))
|
||||
continue
|
||||
|
||||
# other typedef
|
||||
if code.startswith("typedef"):
|
||||
if '(' in code:
|
||||
continue
|
||||
name, typedef, arr = parse_cdecl(code[8:-1])
|
||||
if typedef.startswith("struct"):
|
||||
forward_structs.add(name)
|
||||
continue
|
||||
|
||||
opaque_structs.update(forward_structs - structs)
|
||||
|
||||
|
||||
def parse_file(emit, f, block_comment_exclude):
|
||||
in_block_comment = False
|
||||
cur_block = ""
|
||||
in_enum = None
|
||||
in_struct = None
|
||||
in_union = None
|
||||
|
||||
for lineno, line in enumerate(f):
|
||||
code, comment = split_comment(line)
|
||||
if not code and not comment:
|
||||
continue
|
||||
# print(comment)
|
||||
|
||||
# in block comment
|
||||
if in_block_comment:
|
||||
if not code and comment is not None and comment[0] == '=':
|
||||
# closing block comment; emit if not excluded
|
||||
if cur_block not in block_comment_exclude:
|
||||
try:
|
||||
emit.block_comment(cur_block)
|
||||
except Exception as e:
|
||||
print("%d: exception in block_comment():\n%s" % (
|
||||
lineno + 1, traceback.format_exc()))
|
||||
in_block_comment = False
|
||||
# emit "after struct" constants in Globals
|
||||
if cur_block == "Globals":
|
||||
for dname, dtext in define_after_struct:
|
||||
try:
|
||||
emit.text(dtext)
|
||||
except Exception as e:
|
||||
print("%d: exception in text():\n%s" % (
|
||||
lineno + 1, traceback.format_exc()))
|
||||
defined.add(dname)
|
||||
continue
|
||||
if not code and comment is not None:
|
||||
# remember current block
|
||||
cur_block = comment
|
||||
continue
|
||||
|
||||
# inside enum
|
||||
if in_enum is not None:
|
||||
if code[0] == '}':
|
||||
# closing
|
||||
try:
|
||||
emit.enum(*in_enum)
|
||||
except Exception as e:
|
||||
print("%d: exception in enum():\n%s" % (lineno + 1, traceback.format_exc()))
|
||||
in_enum = None
|
||||
continue
|
||||
m = enum_value_re.match(code)
|
||||
if m is not None:
|
||||
in_enum[1].append((m.group('name'), m.group('value'), comment))
|
||||
continue
|
||||
|
||||
# inside struct/union
|
||||
if in_struct is not None or in_union is not None:
|
||||
if code[0] == '}':
|
||||
# closing
|
||||
if in_struct is not None:
|
||||
try:
|
||||
emit.struct(*in_struct)
|
||||
except Exception as e:
|
||||
print("%d: exception in struct(\"%s\"):\n%s" % (
|
||||
lineno + 1, in_struct[0], traceback.format_exc()))
|
||||
in_struct = None
|
||||
if in_union is not None:
|
||||
try:
|
||||
emit.union(*in_union)
|
||||
except Exception as e:
|
||||
print("%d: exception in union(\"%s\"):\n%s" % (
|
||||
lineno + 1, in_union[0], traceback.format_exc()))
|
||||
in_union = None
|
||||
continue
|
||||
name, ctype, arr = parse_cdecl(code[:-1])
|
||||
# add to fields
|
||||
if in_struct is not None:
|
||||
in_struct[1].append((name, ctype, arr, comment))
|
||||
if in_union is not None:
|
||||
in_union[1].append((name, ctype, arr, comment))
|
||||
continue
|
||||
|
||||
# block comment
|
||||
if not code and comment is not None and comment[0] == '=':
|
||||
in_block_comment = True
|
||||
|
||||
# #define
|
||||
m = define_re.match(code)
|
||||
if m is not None:
|
||||
try:
|
||||
emit.define(m.group('name'), m.group('value').strip(), comment)
|
||||
except Exception as e:
|
||||
print("%d: exception in define():\n%s" % (lineno + 1, traceback.format_exc()))
|
||||
continue
|
||||
|
||||
# typedef enum {
|
||||
m = enum_re.match(code)
|
||||
if m is not None:
|
||||
in_enum = (m.group('name'), [])
|
||||
continue
|
||||
|
||||
# typedef struct {
|
||||
m = struct_re.match(code)
|
||||
if m is not None:
|
||||
in_struct = (m.group('name'), [])
|
||||
continue
|
||||
|
||||
# typedef union {
|
||||
m = union_re.match(code)
|
||||
if m is not None:
|
||||
in_union = (m.group('name'), [])
|
||||
continue
|
||||
|
||||
# other typedef
|
||||
if code.startswith("typedef"):
|
||||
# typedef function?
|
||||
m = func_pointer_re.match(code[8:-1])
|
||||
if m is not None:
|
||||
params = [parse_cdecl(param.strip()) for param in
|
||||
m.group('params').strip().split(',') if param.strip()]
|
||||
try:
|
||||
emit.typedef_function(m.group('name'), m.group('restype'), params)
|
||||
except Exception as e:
|
||||
print("%d: exception in typedef_function():\n%s" % (
|
||||
lineno + 1, traceback.format_exc()))
|
||||
continue
|
||||
if '(' in code:
|
||||
print("Invalid typedef: %s" % code)
|
||||
continue
|
||||
emit.typedef(*parse_cdecl(code[8:-1]))
|
||||
continue
|
||||
|
||||
# function
|
||||
m = function_re.match(code)
|
||||
if m is not None:
|
||||
params = [parse_cdecl(param.strip()) for param in m.group('params').strip().split(',')
|
||||
if param.strip()]
|
||||
try:
|
||||
emit.function(m.group('name'), m.group('restype'), params)
|
||||
except Exception as e:
|
||||
print("%d: exception in function(\"%s\"):\n%s" % (
|
||||
lineno + 1, m.group('name'), traceback.format_exc()))
|
||||
continue
|
||||
|
||||
# static const
|
||||
m = static_const_re.match(code)
|
||||
if m is not None:
|
||||
value = m.group('value')
|
||||
if value[0] == '{':
|
||||
value = [v.strip() for v in value[1:-1].strip().split(',') if v.strip()]
|
||||
try:
|
||||
emit.static_const(m.group('name'), m.group('type'), value)
|
||||
except Exception as e:
|
||||
print("%d: exception in static_const():\n%s" % (lineno + 1, traceback.format_exc()))
|
||||
continue
|
||||
|
||||
if not code or code[0] == '#':
|
||||
continue
|
||||
|
||||
if not code or code[0] == '#':
|
||||
continue
|
||||
|
||||
if code == 'extern "C" {' or code == "}":
|
||||
continue
|
||||
|
||||
print("%d: Unrecognized: %s" % (lineno + 1, code))
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,20 +0,0 @@
|
||||
//
|
||||
// This file is auto-generated by wpilibj/wpilibJavaJNI/nivision/gen_java.py
|
||||
// Please do not edit!
|
||||
//
|
||||
|
||||
package com.ni.vision;
|
||||
|
||||
public class VisionException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public VisionException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VisionException [" + super.toString() + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,381 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import com.ni.vision.NIVision;
|
||||
import com.ni.vision.NIVision.Image;
|
||||
import com.ni.vision.NIVision.RawData;
|
||||
import com.ni.vision.VisionException;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
import edu.wpi.first.wpilibj.vision.USBCamera;
|
||||
|
||||
// replicates CameraServer.cpp in java lib
|
||||
|
||||
public class CameraServer {
|
||||
|
||||
private static final int kPort = 1180;
|
||||
private static final byte[] kMagicNumber = {0x01, 0x00, 0x00, 0x00};
|
||||
private static final int kSize640x480 = 0;
|
||||
private static final int kSize320x240 = 1;
|
||||
private static final int kSize160x120 = 2;
|
||||
private static final int kHardwareCompression = -1;
|
||||
private static final String kDefaultCameraName = "cam1";
|
||||
private static final int kMaxImageSize = 200000;
|
||||
private static CameraServer server;
|
||||
|
||||
@SuppressWarnings("JavadocMethod")
|
||||
public static CameraServer getInstance() {
|
||||
if (server == null) {
|
||||
server = new CameraServer();
|
||||
}
|
||||
return server;
|
||||
}
|
||||
|
||||
private int m_quality;
|
||||
private boolean m_autoCaptureStarted;
|
||||
private boolean m_hwClient = true;
|
||||
private USBCamera m_camera;
|
||||
private CameraData m_imageData;
|
||||
private Deque<ByteBuffer> m_imageDataPool;
|
||||
|
||||
@SuppressWarnings("JavadocMethod")
|
||||
private final class CameraData {
|
||||
@SuppressWarnings("MemberName")
|
||||
private final RawData data;
|
||||
@SuppressWarnings("MemberName")
|
||||
private final int start;
|
||||
|
||||
CameraData(RawData data, int start) {
|
||||
this.data = data;
|
||||
this.start = start;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("JavadocMethod")
|
||||
private CameraServer() {
|
||||
m_quality = 50;
|
||||
m_camera = null;
|
||||
m_imageData = null;
|
||||
m_imageDataPool = new ArrayDeque<>(3);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
m_imageDataPool.addLast(ByteBuffer.allocateDirect(kMaxImageSize));
|
||||
}
|
||||
final Thread serverThread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
serve();
|
||||
} catch (IOException ex) {
|
||||
// do stuff here
|
||||
} catch (InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
});
|
||||
serverThread.setName("CameraServer Send Thread");
|
||||
serverThread.start();
|
||||
}
|
||||
|
||||
@SuppressWarnings("JavadocMethod")
|
||||
private synchronized void setImageData(RawData data, int start) {
|
||||
if (m_imageData != null && m_imageData.data != null) {
|
||||
m_imageData.data.free();
|
||||
if (m_imageData.data.getBuffer() != null) {
|
||||
m_imageDataPool.addLast(m_imageData.data.getBuffer());
|
||||
}
|
||||
m_imageData = null;
|
||||
}
|
||||
m_imageData = new CameraData(data, start);
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually change the image that is served by the MJPEG stream. This can be called to pass custom
|
||||
* annotated images to the dashboard. Note that, for 640x480 video, this method could take between
|
||||
* 40 and 50 milliseconds to complete.
|
||||
*
|
||||
* <p>This shouldn't be called if {@link #startAutomaticCapture} is called.
|
||||
*
|
||||
* @param image The IMAQ image to show on the dashboard
|
||||
*/
|
||||
public void setImage(Image image) {
|
||||
// handle multi-threadedness
|
||||
|
||||
/* Flatten the IMAQ image to a JPEG */
|
||||
|
||||
RawData data =
|
||||
NIVision.imaqFlatten(image, NIVision.FlattenType.FLATTEN_IMAGE,
|
||||
NIVision.CompressionType.COMPRESSION_JPEG, 10 * m_quality);
|
||||
ByteBuffer buffer = data.getBuffer();
|
||||
boolean hwClient;
|
||||
|
||||
synchronized (this) {
|
||||
hwClient = m_hwClient;
|
||||
}
|
||||
|
||||
/* Find the start of the JPEG data */
|
||||
int index = 0;
|
||||
if (hwClient) {
|
||||
while (index < buffer.limit() - 1) {
|
||||
if ((buffer.get(index) & 0xff) == 0xFF && (buffer.get(index + 1) & 0xff) == 0xD8) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer.limit() - index - 1 <= 2) {
|
||||
throw new VisionException("data size of flattened image is less than 2. Try another "
|
||||
+ "camera!");
|
||||
}
|
||||
|
||||
setImageData(data, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start automatically capturing images to send to the dashboard. You should call this method to
|
||||
* just see a camera feed on the dashboard without doing any vision processing on the roboRIO.
|
||||
* {@link #setImage} shouldn't be called after this is called. This overload calles {@link
|
||||
* #startAutomaticCapture(String)} with the default camera name
|
||||
*/
|
||||
public void startAutomaticCapture() {
|
||||
startAutomaticCapture(USBCamera.kDefaultCameraName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start automatically capturing images to send to the dashboard.
|
||||
*
|
||||
* <p>You should call this method to just see a camera feed on the dashboard without doing any
|
||||
* vision processing on the roboRIO. {@link #setImage} shouldn't be called after this is called.
|
||||
*
|
||||
* @param cameraName The name of the camera interface (e.g. "cam1")
|
||||
*/
|
||||
public void startAutomaticCapture(String cameraName) {
|
||||
try {
|
||||
USBCamera camera = new USBCamera(cameraName);
|
||||
camera.openCamera();
|
||||
startAutomaticCapture(camera);
|
||||
} catch (VisionException ex) {
|
||||
DriverStation.reportError(
|
||||
"Error when starting the camera: " + cameraName + " " + ex.getMessage(), true);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("JavadocMethod")
|
||||
public synchronized void startAutomaticCapture(USBCamera camera) {
|
||||
if (m_autoCaptureStarted) {
|
||||
return;
|
||||
}
|
||||
m_autoCaptureStarted = true;
|
||||
m_camera = camera;
|
||||
|
||||
m_camera.startCapture();
|
||||
|
||||
Thread captureThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
capture();
|
||||
}
|
||||
});
|
||||
captureThread.setName("Camera Capture Thread");
|
||||
captureThread.start();
|
||||
}
|
||||
|
||||
protected void capture() {
|
||||
Image frame = NIVision.imaqCreateImage(NIVision.ImageType.IMAGE_RGB, 0);
|
||||
while (true) {
|
||||
boolean hwClient;
|
||||
ByteBuffer dataBuffer = null;
|
||||
synchronized (this) {
|
||||
hwClient = m_hwClient;
|
||||
if (hwClient) {
|
||||
dataBuffer = m_imageDataPool.removeLast();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (hwClient && dataBuffer != null) {
|
||||
// Reset the image buffer limit
|
||||
dataBuffer.limit(dataBuffer.capacity() - 1);
|
||||
m_camera.getImageData(dataBuffer);
|
||||
setImageData(new RawData(dataBuffer), 0);
|
||||
} else {
|
||||
m_camera.getImage(frame);
|
||||
setImage(frame);
|
||||
}
|
||||
} catch (VisionException ex) {
|
||||
DriverStation.reportError("Error when getting image from the camera: " + ex.getMessage(),
|
||||
true);
|
||||
if (dataBuffer != null) {
|
||||
synchronized (this) {
|
||||
m_imageDataPool.addLast(dataBuffer);
|
||||
Timer.delay(.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if auto capture is started.
|
||||
*/
|
||||
public synchronized boolean isAutoCaptureStarted() {
|
||||
return m_autoCaptureStarted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the image to use. Use the public kSize constants to set the correct mode, or
|
||||
* set it directory on a camera and call the appropriate autoCapture method.
|
||||
*
|
||||
* @param size The size to use
|
||||
*/
|
||||
public synchronized void setSize(int size) {
|
||||
if (m_camera == null) {
|
||||
return;
|
||||
}
|
||||
switch (size) {
|
||||
case kSize640x480:
|
||||
m_camera.setSize(640, 480);
|
||||
break;
|
||||
case kSize320x240:
|
||||
m_camera.setSize(320, 240);
|
||||
break;
|
||||
case kSize160x120:
|
||||
m_camera.setSize(160, 120);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported size: " + size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the quality of the compressed image sent to the dashboard.
|
||||
*
|
||||
* @param quality The quality of the JPEG image, from 0 to 100
|
||||
*/
|
||||
public synchronized void setQuality(int quality) {
|
||||
m_quality = quality > 100 ? 100 : quality < 0 ? 0 : quality;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the quality of the compressed image sent to the dashboard.
|
||||
*
|
||||
* @return The quality, from 0 to 100
|
||||
*/
|
||||
public synchronized int getQuality() {
|
||||
return m_quality;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the M-JPEG server.
|
||||
*
|
||||
* <p>This function listens for a connection from the dashboard in a background thread, then
|
||||
* sends back the M-JPEG stream.
|
||||
*
|
||||
* @throws IOException if the Socket connection fails
|
||||
* @throws InterruptedException if the sleep is interrupted
|
||||
*/
|
||||
protected void serve() throws IOException, InterruptedException {
|
||||
|
||||
ServerSocket socket = new ServerSocket();
|
||||
socket.setReuseAddress(true);
|
||||
InetSocketAddress address = new InetSocketAddress(kPort);
|
||||
socket.bind(address);
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
Socket socket1 = socket.accept();
|
||||
|
||||
DataInputStream is = new DataInputStream(socket1.getInputStream());
|
||||
DataOutputStream os = new DataOutputStream(socket1.getOutputStream());
|
||||
|
||||
int fps = is.readInt();
|
||||
int compression = is.readInt();
|
||||
int size = is.readInt();
|
||||
|
||||
if (compression != kHardwareCompression) {
|
||||
DriverStation.reportError("Choose \"USB Camera HW\" on the dashboard", false);
|
||||
socket1.close();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Wait for the camera
|
||||
synchronized (this) {
|
||||
System.out.println("Camera not yet ready, awaiting image");
|
||||
if (m_camera == null) {
|
||||
wait();
|
||||
}
|
||||
m_hwClient = compression == kHardwareCompression;
|
||||
if (!m_hwClient) {
|
||||
setQuality(100 - compression);
|
||||
} else if (m_camera != null) {
|
||||
m_camera.setFPS(fps);
|
||||
}
|
||||
setSize(size);
|
||||
}
|
||||
|
||||
long period = (long) (1000 / (1.0 * fps));
|
||||
while (true) {
|
||||
long t0 = System.currentTimeMillis();
|
||||
final CameraData imageData;
|
||||
synchronized (this) {
|
||||
wait();
|
||||
imageData = m_imageData;
|
||||
m_imageData = null;
|
||||
}
|
||||
|
||||
if (imageData == null) {
|
||||
continue;
|
||||
}
|
||||
// Set the buffer position to the start of the data,
|
||||
// and then create a new wrapper for the data at
|
||||
// exactly that position
|
||||
imageData.data.getBuffer().position(imageData.start);
|
||||
byte[] imageArray = new byte[imageData.data.getBuffer().remaining()];
|
||||
imageData.data.getBuffer().get(imageArray, 0, imageData.data.getBuffer().remaining());
|
||||
|
||||
// write numbers
|
||||
try {
|
||||
os.write(kMagicNumber);
|
||||
os.writeInt(imageArray.length);
|
||||
os.write(imageArray);
|
||||
os.flush();
|
||||
long dt = System.currentTimeMillis() - t0;
|
||||
|
||||
if (dt < period) {
|
||||
Thread.sleep(period - dt);
|
||||
}
|
||||
} catch (IOException | UnsupportedOperationException ex) {
|
||||
DriverStation.reportError(ex.getMessage(), true);
|
||||
break;
|
||||
} finally {
|
||||
imageData.data.free();
|
||||
if (imageData.data.getBuffer() != null) {
|
||||
synchronized (this) {
|
||||
m_imageDataPool.addLast(imageData.data.getBuffer());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
DriverStation.reportError(ex.getMessage(), true);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.first.wpilibj.image;
|
||||
|
||||
import com.ni.vision.NIVision;
|
||||
|
||||
import edu.wpi.first.wpilibj.util.SortedVector;
|
||||
|
||||
/**
|
||||
* An image where each pixel is treated as either on or off.
|
||||
*/
|
||||
public class BinaryImage extends MonoImage {
|
||||
private int m_numParticles = -1;
|
||||
|
||||
BinaryImage() throws NIVisionException {
|
||||
}
|
||||
|
||||
BinaryImage(BinaryImage sourceImage) {
|
||||
super(sourceImage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of particles.
|
||||
*
|
||||
* @return The number of particles
|
||||
*/
|
||||
public int getNumberParticles() throws NIVisionException {
|
||||
if (m_numParticles < 0) {
|
||||
m_numParticles = NIVision.imaqCountParticles(image, 1);
|
||||
}
|
||||
return m_numParticles;
|
||||
}
|
||||
|
||||
|
||||
private class ParticleSizeReport {
|
||||
final int m_index;
|
||||
final double m_size;
|
||||
|
||||
public ParticleSizeReport(int index) throws NIVisionException {
|
||||
if ((!(index < BinaryImage.this.getNumberParticles())) || index < 0) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
m_index = index;
|
||||
m_size = ParticleAnalysisReport.getParticleToImagePercent(BinaryImage.this, index);
|
||||
}
|
||||
|
||||
public ParticleAnalysisReport getParticleAnalysisReport() throws NIVisionException {
|
||||
return new ParticleAnalysisReport(BinaryImage.this, m_index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a particle analysis report for the particle at the given index.
|
||||
*
|
||||
* @param index The index of the particle to report on.
|
||||
* @return The ParticleAnalysisReport for the particle at the given index
|
||||
*/
|
||||
public ParticleAnalysisReport getParticleAnalysisReport(int index) throws NIVisionException {
|
||||
if (!(index < getNumberParticles())) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return new ParticleAnalysisReport(this, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the particle analysis reports ordered from largest area to smallest.
|
||||
*
|
||||
* @param size The number of particles to return
|
||||
* @return An array of ParticleReports from largest area to smallest
|
||||
*/
|
||||
public ParticleAnalysisReport[] getOrderedParticleAnalysisReports(int size)
|
||||
throws NIVisionException {
|
||||
if (size > getNumberParticles()) {
|
||||
size = getNumberParticles();
|
||||
}
|
||||
ParticleSizeReport[] reports = new ParticleSizeReport[size];
|
||||
SortedVector sorter = new SortedVector(new SortedVector.Comparator() {
|
||||
public int compare(Object object1, Object object2) {
|
||||
ParticleSizeReport p1 = (ParticleSizeReport) object1;
|
||||
ParticleSizeReport p2 = (ParticleSizeReport) object2;
|
||||
if (p1.m_size < p2.m_size) {
|
||||
return -1;
|
||||
} else if (p1.m_size > p2.m_size) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
for (int i = 0; i < getNumberParticles(); i++) {
|
||||
sorter.addElement(new ParticleSizeReport(i));
|
||||
}
|
||||
sorter.setSize(size);
|
||||
sorter.copyInto(reports);
|
||||
ParticleAnalysisReport[] finalReports = new ParticleAnalysisReport[reports.length];
|
||||
for (int i = 0; i < finalReports.length; i++) {
|
||||
finalReports[i] = reports[i].getParticleAnalysisReport();
|
||||
}
|
||||
return finalReports;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the particle analysis reports ordered from largest area to smallest.
|
||||
*
|
||||
* @return An array of ParticleReports from largest are to smallest
|
||||
*/
|
||||
public ParticleAnalysisReport[] getOrderedParticleAnalysisReports() throws NIVisionException {
|
||||
return getOrderedParticleAnalysisReports(getNumberParticles());
|
||||
}
|
||||
|
||||
@SuppressWarnings({"summaryjavadoc", "javadocmethod"})
|
||||
public void write(String fileName) throws NIVisionException {
|
||||
NIVision.RGBValue colorTable = new NIVision.RGBValue(0, 0, 255, 0);
|
||||
try {
|
||||
NIVision.imaqWriteFile(image, fileName, colorTable);
|
||||
} finally {
|
||||
colorTable.free();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* removeSmallObjects filters particles based on their m_size. The algorithm erodes the image a
|
||||
* specified number of times and keeps the particles from the original image that remain in the
|
||||
* eroded image.
|
||||
*
|
||||
* @param connectivity8 true to use connectivity-8 or false for connectivity-4 to determine
|
||||
* whether particles are touching. For more information about connectivity,
|
||||
* see Chapter 9, Binary Morphology, in the NI Vision Concepts manual.
|
||||
* @param erosions the number of erosions to perform
|
||||
* @return a BinaryImage after applying the filter
|
||||
*/
|
||||
public BinaryImage removeSmallObjects(boolean connectivity8, int erosions)
|
||||
throws NIVisionException {
|
||||
BinaryImage result = new BinaryImage();
|
||||
NIVision.imaqSizeFilter(result.image, image, connectivity8 ? 1 : 0, erosions,
|
||||
NIVision.SizeType.KEEP_LARGE, null);
|
||||
result.free();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* removeLargeObjects filters particles based on their m_size. The algorithm erodes the image a
|
||||
* specified number of times and discards the particles from the original image that remain in the
|
||||
* eroded image.
|
||||
*
|
||||
* @param connectivity8 true to use connectivity-8 or false for connectivity-4 to determine
|
||||
* whether particles are touching. For more information about connectivity,
|
||||
* see Chapter 9, Binary Morphology, in the NI Vision Concepts manual.
|
||||
* @param erosions the number of erosions to perform
|
||||
* @return a BinaryImage after applying the filter
|
||||
*/
|
||||
public BinaryImage removeLargeObjects(boolean connectivity8, int erosions)
|
||||
throws NIVisionException {
|
||||
BinaryImage result = new BinaryImage();
|
||||
NIVision.imaqSizeFilter(result.image, image, connectivity8 ? 1 : 0, erosions,
|
||||
NIVision.SizeType.KEEP_SMALL, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"summaryjavadoc", "javadocmethod"})
|
||||
public BinaryImage convexHull(boolean connectivity8) throws NIVisionException {
|
||||
BinaryImage result = new BinaryImage();
|
||||
NIVision.imaqConvexHull(result.image, image, connectivity8 ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"summaryjavadoc", "javadocmethod"})
|
||||
public BinaryImage particleFilter(NIVision.ParticleFilterCriteria2[] criteria)
|
||||
throws NIVisionException {
|
||||
BinaryImage result = new BinaryImage();
|
||||
NIVision.ParticleFilterOptions2 options = new NIVision.ParticleFilterOptions2(0, 0, 0, 1);
|
||||
NIVision.imaqParticleFilter4(result.image, image, criteria, options, null);
|
||||
options.free();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,423 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.first.wpilibj.image;
|
||||
|
||||
import com.ni.vision.NIVision;
|
||||
|
||||
/**
|
||||
* A class representing a color image.
|
||||
*/
|
||||
public abstract class ColorImage extends ImageBase {
|
||||
|
||||
ColorImage(NIVision.ImageType type) throws NIVisionException {
|
||||
super(type);
|
||||
}
|
||||
|
||||
ColorImage(ColorImage sourceImage) {
|
||||
super(sourceImage);
|
||||
}
|
||||
|
||||
private BinaryImage threshold(NIVision.ColorMode colorMode, int low1, int high1, int low2,
|
||||
int high2, int low3, int high3) throws NIVisionException {
|
||||
BinaryImage res = new BinaryImage();
|
||||
NIVision.Range range1 = new NIVision.Range(low1, high1);
|
||||
NIVision.Range range2 = new NIVision.Range(low2, high2);
|
||||
NIVision.Range range3 = new NIVision.Range(low3, high3);
|
||||
NIVision.imaqColorThreshold(res.image, image, 1, colorMode, range1, range2, range3);
|
||||
res.free();
|
||||
range1.free();
|
||||
range2.free();
|
||||
range3.free();
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a mask of the areas of the image that fall within the given ranges for color values
|
||||
*
|
||||
* @param redLow The lower red limit.
|
||||
* @param redHigh The upper red limit.
|
||||
* @param greenLow The lower green limit.
|
||||
* @param greenHigh The upper green limit.
|
||||
* @param blueLow The lower blue limit.
|
||||
* @param blueHigh The upper blue limit.
|
||||
* @return A BinaryImage masking the areas which match the given thresholds.
|
||||
*/
|
||||
public BinaryImage thresholdRGB(int redLow, int redHigh, int greenLow, int greenHigh,
|
||||
int blueLow, int blueHigh) throws NIVisionException {
|
||||
return threshold(NIVision.ColorMode.RGB, redLow, redHigh, greenLow, greenHigh, blueLow,
|
||||
blueHigh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a mask of the areas of the image that fall within the given ranges for color values
|
||||
*
|
||||
* @param hueLow The lower hue limit.
|
||||
* @param hueHigh The upper hue limit.
|
||||
* @param saturationLow The lower saturation limit.
|
||||
* @param saturationHigh The upper saturation limit.
|
||||
* @param luminenceLow The lower luminence limit.
|
||||
* @param luminenceHigh The upper luminence limit.
|
||||
* @return A BinaryImage masking the areas which match the given thresholds.
|
||||
*/
|
||||
public BinaryImage thresholdHSL(int hueLow, int hueHigh, int saturationLow, int saturationHigh,
|
||||
int luminenceLow, int luminenceHigh) throws NIVisionException {
|
||||
return threshold(NIVision.ColorMode.HSL, hueLow, hueHigh, saturationLow, saturationHigh,
|
||||
luminenceLow, luminenceHigh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a mask of the areas of the image that fall within the given ranges for color values
|
||||
*
|
||||
* @param hueLow The lower hue limit.
|
||||
* @param hueHigh The upper hue limit.
|
||||
* @param saturationLow The lower saturation limit.
|
||||
* @param saturationHigh The upper saturation limit.
|
||||
* @param valueHigh The lower value limit.
|
||||
* @param valueLow The upper value limit.
|
||||
* @return A BinaryImage masking the areas which match the given thresholds.
|
||||
*/
|
||||
public BinaryImage thresholdHSV(int hueLow, int hueHigh, int saturationLow, int saturationHigh,
|
||||
int valueLow, int valueHigh) throws NIVisionException {
|
||||
return threshold(NIVision.ColorMode.HSV, hueLow, hueHigh, saturationLow, saturationHigh,
|
||||
valueLow, valueHigh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a mask of the areas of the image that fall within the given ranges for color values
|
||||
*
|
||||
* @param hueLow The lower hue limit.
|
||||
* @param hueHigh The upper hue limit.
|
||||
* @param saturationLow The lower saturation limit.
|
||||
* @param saturationHigh The upper saturation limit.
|
||||
* @param intansityLow The lower intensity limit.
|
||||
* @param intensityHigh The upper intensity limit.
|
||||
* @return A BinaryImage masking the areas which match the given thresholds.
|
||||
*/
|
||||
public BinaryImage thresholdHSI(int hueLow, int hueHigh, int saturationLow, int saturationHigh,
|
||||
int intansityLow, int intensityHigh) throws NIVisionException {
|
||||
return threshold(NIVision.ColorMode.HSI, hueLow, hueHigh, saturationLow, saturationHigh,
|
||||
intansityLow, intensityHigh);
|
||||
}
|
||||
|
||||
MonoImage extractFirstColorPlane(NIVision.ColorMode mode) throws NIVisionException {
|
||||
MonoImage result = new MonoImage();
|
||||
NIVision.imaqExtractColorPlanes(image, mode, result.image, null, null);
|
||||
result.free();
|
||||
return result;
|
||||
}
|
||||
|
||||
MonoImage extractSecondColorPlane(NIVision.ColorMode mode) throws NIVisionException {
|
||||
MonoImage result = new MonoImage();
|
||||
NIVision.imaqExtractColorPlanes(image, mode, null, result.image, null);
|
||||
result.free();
|
||||
return result;
|
||||
}
|
||||
|
||||
MonoImage extractThirdColorPlane(NIVision.ColorMode mode) throws NIVisionException {
|
||||
MonoImage result = new MonoImage();
|
||||
NIVision.imaqExtractColorPlanes(image, mode, null, null, result.image);
|
||||
result.free();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the red color plane from the image when represented in RGB color space.
|
||||
*
|
||||
* @return The red color plane from the image.
|
||||
*/
|
||||
public MonoImage getRedPlane() throws NIVisionException {
|
||||
return extractFirstColorPlane(NIVision.ColorMode.RGB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the green color plane from the image when represented in RGB color space.
|
||||
*
|
||||
* @return The green color plane from the image.
|
||||
*/
|
||||
public MonoImage getGreenPlane() throws NIVisionException {
|
||||
return extractSecondColorPlane(NIVision.ColorMode.RGB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the blue color plane from the image when represented in RGB color space.
|
||||
*
|
||||
* @return The blue color plane from the image.
|
||||
*/
|
||||
public MonoImage getBluePlane() throws NIVisionException {
|
||||
return extractThirdColorPlane(NIVision.ColorMode.RGB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hue color plane from the image when represented in HSL color space.
|
||||
*
|
||||
* @return The hue color plane from the image.
|
||||
*/
|
||||
public MonoImage getHSLHuePlane() throws NIVisionException {
|
||||
return extractFirstColorPlane(NIVision.ColorMode.HSL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hue color plane from the image when represented in HSV color space.
|
||||
*
|
||||
* @return The hue color plane from the image.
|
||||
*/
|
||||
public MonoImage getHSVHuePlane() throws NIVisionException {
|
||||
return extractFirstColorPlane(NIVision.ColorMode.HSV);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hue color plane from the image when represented in HSI color space.
|
||||
*
|
||||
* @return The hue color plane from the image.
|
||||
*/
|
||||
public MonoImage getHSIHuePlane() throws NIVisionException {
|
||||
return extractFirstColorPlane(NIVision.ColorMode.HSI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the saturation color plane from the image when represented in HSL color space.
|
||||
*
|
||||
* @return The saturation color plane from the image.
|
||||
*/
|
||||
public MonoImage getHSLSaturationPlane() throws NIVisionException {
|
||||
return extractSecondColorPlane(NIVision.ColorMode.HSL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the saturation color plane from the image when represented in HSV color space.
|
||||
*
|
||||
* @return The saturation color plane from the image.
|
||||
*/
|
||||
public MonoImage getHSVSaturationPlane() throws NIVisionException {
|
||||
return extractSecondColorPlane(NIVision.ColorMode.HSV);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the saturation color plane from the image when represented in HSI color space.
|
||||
*
|
||||
* @return The saturation color plane from the image.
|
||||
*/
|
||||
public MonoImage getHSISaturationPlane() throws NIVisionException {
|
||||
return extractSecondColorPlane(NIVision.ColorMode.HSI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the luminance color plane from the image when represented in HSL color space.
|
||||
*
|
||||
* @return The luminance color plane from the image.
|
||||
*/
|
||||
public MonoImage getLuminancePlane() throws NIVisionException {
|
||||
return extractThirdColorPlane(NIVision.ColorMode.HSL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value color plane from the image when represented in HSV color space.
|
||||
*
|
||||
* @return The value color plane from the image.
|
||||
*/
|
||||
public MonoImage getValuePlane() throws NIVisionException {
|
||||
return extractThirdColorPlane(NIVision.ColorMode.HSV);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the intensity color plane from the image when represented in HSI color space.
|
||||
*
|
||||
* @return The intensity color plane from the image.
|
||||
*/
|
||||
public MonoImage getIntensityPlane() throws NIVisionException {
|
||||
return extractThirdColorPlane(NIVision.ColorMode.HSI);
|
||||
}
|
||||
|
||||
ColorImage replaceFirstColorPlane(NIVision.ColorMode mode, MonoImage plane)
|
||||
throws NIVisionException {
|
||||
NIVision.imaqReplaceColorPlanes(image, image, mode, plane.image, null, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
ColorImage replaceSecondColorPlane(NIVision.ColorMode mode, MonoImage plane)
|
||||
throws NIVisionException {
|
||||
NIVision.imaqReplaceColorPlanes(image, image, mode, null, plane.image, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
ColorImage replaceThirdColorPlane(NIVision.ColorMode mode, MonoImage plane)
|
||||
throws NIVisionException {
|
||||
NIVision.imaqReplaceColorPlanes(image, image, mode, null, null, plane.image);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the red color plane from the image when represented in RGB color space. This does not
|
||||
* create a new image, but modifies this one instead. Create a copy before hand if you need to
|
||||
* continue using the original.
|
||||
*
|
||||
* @param plane The MonoImage representing the new color plane.
|
||||
* @return The resulting image.
|
||||
*/
|
||||
public ColorImage replaceRedPlane(MonoImage plane) throws NIVisionException {
|
||||
return replaceFirstColorPlane(NIVision.ColorMode.RGB, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the green color plane from the image when represented in RGB color space. This does not
|
||||
* create a new image, but modifies this one instead. Create a copy before hand if you need to
|
||||
* continue using the original.
|
||||
*
|
||||
* @param plane The MonoImage representing the new color plane.
|
||||
* @return The resulting image.
|
||||
*/
|
||||
public ColorImage replaceGreenPlane(MonoImage plane) throws NIVisionException {
|
||||
return replaceSecondColorPlane(NIVision.ColorMode.RGB, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the blue color plane from the image when represented in RGB color space. This does not
|
||||
* create a new image, but modifies this one instead. Create a copy before hand if you need to
|
||||
* continue using the original.
|
||||
*
|
||||
* @param plane The MonoImage representing the new color plane.
|
||||
* @return The resulting image.
|
||||
*/
|
||||
public ColorImage replaceBluePlane(MonoImage plane) throws NIVisionException {
|
||||
return replaceThirdColorPlane(NIVision.ColorMode.RGB, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hue color plane from the image when represented in HSL color space. This does not
|
||||
* create a new image, but modifies this one instead. Create a copy before hand if you need to
|
||||
* continue using the original.
|
||||
*
|
||||
* @param plane The MonoImage representing the new color plane.
|
||||
* @return The resulting image.
|
||||
*/
|
||||
public ColorImage replaceHSLHuePlane(MonoImage plane) throws NIVisionException {
|
||||
return replaceFirstColorPlane(NIVision.ColorMode.HSL, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hue color plane from the image when represented in HSV color space. This does not
|
||||
* create a new image, but modifies this one instead. Create a copy before hand if you need to
|
||||
* continue using the original.
|
||||
*
|
||||
* @param plane The MonoImage representing the new color plane.
|
||||
* @return The resulting image.
|
||||
*/
|
||||
public ColorImage replaceHSVHuePlane(MonoImage plane) throws NIVisionException {
|
||||
return replaceFirstColorPlane(NIVision.ColorMode.HSV, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hue color plane from the image when represented in HSI color space. This does not
|
||||
* create a new image, but modifies this one instead. Create a copy before hand if you need to
|
||||
* continue using the original.
|
||||
*
|
||||
* @param plane The MonoImage representing the new color plane.
|
||||
* @return The resulting image.
|
||||
*/
|
||||
public ColorImage replaceHSIHuePlane(MonoImage plane) throws NIVisionException {
|
||||
return replaceFirstColorPlane(NIVision.ColorMode.HSI, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the saturation color plane from the image when represented in HSL color space. This does
|
||||
* not create a new image, but modifies this one instead. Create a copy before hand if you need to
|
||||
* continue using the original.
|
||||
*
|
||||
* @param plane The MonoImage representing the new color plane.
|
||||
* @return The resulting image.
|
||||
*/
|
||||
public ColorImage replaceHSLSaturationPlane(MonoImage plane) throws NIVisionException {
|
||||
return replaceSecondColorPlane(NIVision.ColorMode.HSL, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the saturation color plane from the image when represented in HSV color space. This does
|
||||
* not create a new image, but modifies this one instead. Create a copy before hand if you need to
|
||||
* continue using the original.
|
||||
*
|
||||
* @param plane The MonoImage representing the new color plane.
|
||||
* @return The resulting image.
|
||||
*/
|
||||
public ColorImage replaceHSVSaturationPlane(MonoImage plane) throws NIVisionException {
|
||||
return replaceSecondColorPlane(NIVision.ColorMode.HSV, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the saturation color plane from the image when represented in HSI color space. This does
|
||||
* not create a new image, but modifies this one instead. Create a copy before hand if you need to
|
||||
* continue using the original.
|
||||
*
|
||||
* @param plane The MonoImage representing the new color plane.
|
||||
* @return The resulting image.
|
||||
*/
|
||||
public ColorImage replaceHSISaturationPlane(MonoImage plane) throws NIVisionException {
|
||||
return replaceSecondColorPlane(NIVision.ColorMode.HSI, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the luminance color plane from the image when represented in HSL color space. This does not
|
||||
* create a new image, but modifies this one instead. Create a copy before hand if you need to
|
||||
* continue using the original.
|
||||
*
|
||||
* @param plane The MonoImage representing the new color plane.
|
||||
* @return The resulting image.
|
||||
*/
|
||||
public ColorImage replaceLuminancePlane(MonoImage plane) throws NIVisionException {
|
||||
return replaceThirdColorPlane(NIVision.ColorMode.HSL, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value color plane from the image when represented in HSV color space. This does not
|
||||
* create a new image, but modifies this one instead. Create a copy before hand if you need to
|
||||
* continue using the original.
|
||||
*
|
||||
* @param plane The MonoImage representing the new color plane.
|
||||
* @return The resulting image.
|
||||
*/
|
||||
public ColorImage replaceValuePlane(MonoImage plane) throws NIVisionException {
|
||||
return replaceThirdColorPlane(NIVision.ColorMode.HSV, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the intensity color plane from the image when represented in HSI color space. This does not
|
||||
* create a new image, but modifies this one instead. Create a copy before hand if you need to
|
||||
* continue using the original.
|
||||
*
|
||||
* @param plane The MonoImage representing the new color plane.
|
||||
* @return The resulting image.
|
||||
*/
|
||||
public ColorImage replaceIntensityPlane(MonoImage plane) throws NIVisionException {
|
||||
return replaceThirdColorPlane(NIVision.ColorMode.HSI, plane);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the histogram of each plane of a color image and redistributes pixel values across
|
||||
* the desired range while maintaining pixel value groupings. This does not create a new image,
|
||||
* but modifies this one instead. Create a copy before hand if you need to continue using the
|
||||
* original.
|
||||
*
|
||||
* @return The modified image.
|
||||
*/
|
||||
public ColorImage colorEqualize() throws NIVisionException {
|
||||
NIVision.imaqColorEqualize(image, image, 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the histogram of each plane of a color image and redistributes pixel values across
|
||||
* the desired range while maintaining pixel value groupings for the Luminance plane only. This
|
||||
* does not create a new image, but modifies this one instead. Create a copy before hand if you
|
||||
* need to continue using the original.
|
||||
*
|
||||
* @return The modified image.
|
||||
*/
|
||||
public ColorImage luminanceEqualize() throws NIVisionException {
|
||||
NIVision.imaqColorEqualize(image, image, 0);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.first.wpilibj.image;
|
||||
|
||||
import com.ni.vision.NIVision;
|
||||
|
||||
/**
|
||||
* A color image represented in HSL color space at 3 bytes per pixel.
|
||||
*/
|
||||
public class HSLImage extends ColorImage {
|
||||
|
||||
/**
|
||||
* Create a new 0x0 image.
|
||||
*/
|
||||
public HSLImage() throws NIVisionException {
|
||||
super(NIVision.ImageType.IMAGE_HSL);
|
||||
}
|
||||
|
||||
HSLImage(HSLImage sourceImage) {
|
||||
super(sourceImage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new image by loading a file.
|
||||
*
|
||||
* @param fileName The path of the file to load.
|
||||
*/
|
||||
public HSLImage(String fileName) throws NIVisionException {
|
||||
super(NIVision.ImageType.IMAGE_HSL);
|
||||
NIVision.imaqReadFile(image, fileName);
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.first.wpilibj.image;
|
||||
|
||||
import com.ni.vision.NIVision;
|
||||
import com.ni.vision.NIVision.Image;
|
||||
|
||||
/**
|
||||
* Class representing a generic image.
|
||||
*/
|
||||
public abstract class ImageBase {
|
||||
|
||||
/**
|
||||
* Pointer to the image memory.
|
||||
*/
|
||||
@SuppressWarnings("MemberName")
|
||||
public final Image image;
|
||||
static final int DEFAULT_BORDER_SIZE = 3;
|
||||
|
||||
ImageBase(NIVision.ImageType type) throws NIVisionException {
|
||||
image = NIVision.imaqCreateImage(type, DEFAULT_BORDER_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new image pointing to the same data as the source image. The imgae data is not
|
||||
* copied, it is just referenced by both objects. Freeing one will free both.
|
||||
*
|
||||
* @param sourceImage The image to reference
|
||||
*/
|
||||
ImageBase(ImageBase sourceImage) {
|
||||
image = sourceImage.image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the image to a file.
|
||||
*
|
||||
* <p>Supported extensions: .aipd or .apd AIPD .bmp BMP .jpg or .jpeg JPEG .jp2 JPEG2000 .png PNG
|
||||
* .tif or .tiff TIFF
|
||||
*
|
||||
* @param fileName The path to write the image to.
|
||||
*/
|
||||
public void write(String fileName) throws NIVisionException {
|
||||
NIVision.RGBValue value = new NIVision.RGBValue();
|
||||
NIVision.imaqWriteFile(image, fileName, value);
|
||||
value.free();
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the memory associated with an image.
|
||||
*/
|
||||
public void free() throws NIVisionException {
|
||||
image.free();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the height of the image in pixels.
|
||||
*
|
||||
* @return The height of the image.
|
||||
*/
|
||||
public int getHeight() throws NIVisionException {
|
||||
return NIVision.imaqGetImageSize(image).height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the width of the image in pixels.
|
||||
*
|
||||
* @return The width of the image.
|
||||
*/
|
||||
public int getWidth() throws NIVisionException {
|
||||
return NIVision.imaqGetImageSize(image).width;
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.first.wpilibj.image;
|
||||
|
||||
import com.ni.vision.NIVision;
|
||||
import com.ni.vision.NIVision.CurveOptions;
|
||||
import com.ni.vision.NIVision.DetectEllipsesResult;
|
||||
import com.ni.vision.NIVision.EllipseDescriptor;
|
||||
import com.ni.vision.NIVision.ROI;
|
||||
import com.ni.vision.NIVision.ShapeDetectionOptions;
|
||||
|
||||
/**
|
||||
* A grey scale image represented at a byte per pixel.
|
||||
*/
|
||||
public class MonoImage extends ImageBase {
|
||||
|
||||
/**
|
||||
* Create a new 0x0 image.
|
||||
*/
|
||||
public MonoImage() throws NIVisionException {
|
||||
super(NIVision.ImageType.IMAGE_U8);
|
||||
}
|
||||
|
||||
MonoImage(MonoImage sourceImage) {
|
||||
super(sourceImage);
|
||||
}
|
||||
|
||||
public DetectEllipsesResult detectEllipses(EllipseDescriptor ellipseDescriptor,
|
||||
CurveOptions curveOptions,
|
||||
ShapeDetectionOptions shapeDetectionOptions,
|
||||
ROI roi) throws NIVisionException {
|
||||
return NIVision
|
||||
.imaqDetectEllipses(image, ellipseDescriptor, curveOptions, shapeDetectionOptions, roi);
|
||||
}
|
||||
|
||||
public DetectEllipsesResult detectEllipses(EllipseDescriptor ellipseDescriptor)
|
||||
throws NIVisionException {
|
||||
return NIVision.imaqDetectEllipses(image, ellipseDescriptor, null, null, null);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,140 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.first.wpilibj.image;
|
||||
|
||||
import com.ni.vision.NIVision;
|
||||
|
||||
/**
|
||||
* Class to store commonly used information about a particle.
|
||||
*/
|
||||
public class ParticleAnalysisReport {
|
||||
|
||||
/**
|
||||
* The height of the image in pixels.
|
||||
*/
|
||||
@SuppressWarnings("membername")
|
||||
public final int imageHeight;
|
||||
/**
|
||||
* The width of the image in pixels.
|
||||
*/
|
||||
@SuppressWarnings("membername")
|
||||
public final int imageWidth;
|
||||
/**
|
||||
* X-coordinate of the point representing the average position of the total particle mass,
|
||||
* assuming every point in the particle has a constant density.
|
||||
*/
|
||||
@SuppressWarnings("membername")
|
||||
public final int center_mass_x; // MeasurementType: IMAQ_MT_CENTER_OF_MASS_X
|
||||
/**
|
||||
* Y-coordinate of the point representing the average position of the total particle mass,
|
||||
* assuming every point in the particle has a constant density.
|
||||
*/
|
||||
@SuppressWarnings("membername")
|
||||
public final int center_mass_y; // MeasurementType: IMAQ_MT_CENTER_OF_MASS_Y
|
||||
/**
|
||||
* Center of mass x value normalized to -1.0 to +1.0 range.
|
||||
*/
|
||||
@SuppressWarnings("membername")
|
||||
public final double center_mass_x_normalized;
|
||||
/**
|
||||
* Center of mass y value normalized to -1.0 to +1.0 range.
|
||||
*/
|
||||
@SuppressWarnings("membername")
|
||||
public final double center_mass_y_normalized;
|
||||
/**
|
||||
* Area of the particle.
|
||||
*/
|
||||
@SuppressWarnings("membername")
|
||||
public final double particleArea; // MeasurementType: IMAQ_MT_AREA
|
||||
/**
|
||||
* Bounding Rectangle.
|
||||
*/
|
||||
@SuppressWarnings("membername")
|
||||
public final int boundingRectLeft; // left/top/width/height
|
||||
/**
|
||||
* Bounding Rectangle.
|
||||
*/
|
||||
@SuppressWarnings("membername")
|
||||
public final int boundingRectTop;
|
||||
/**
|
||||
* Bounding Rectangle.
|
||||
*/
|
||||
@SuppressWarnings("membername")
|
||||
public final int boundingRectWidth;
|
||||
/**
|
||||
* Bounding Rectangle.
|
||||
*/
|
||||
@SuppressWarnings("membername")
|
||||
public final int boundingRectHeight;
|
||||
/**
|
||||
* Percentage of the particle Area covering the Image Area.
|
||||
*/
|
||||
@SuppressWarnings("membername")
|
||||
public final double particleToImagePercent; // MeasurementType:
|
||||
// IMAQ_MT_AREA_BY_IMAGE_AREA
|
||||
/**
|
||||
* Percentage of the particle Area in relation to its Particle and Holes Area.
|
||||
*/
|
||||
@SuppressWarnings("membername")
|
||||
public final double particleQuality; // MeasurementType:
|
||||
// IMAQ_MT_AREA_BY_PARTICLE_AND_HOLES_AREA
|
||||
|
||||
ParticleAnalysisReport(BinaryImage image, int index) throws NIVisionException {
|
||||
imageHeight = image.getHeight();
|
||||
imageWidth = image.getWidth();
|
||||
center_mass_x =
|
||||
(int) NIVision.imaqMeasureParticle(image.image, index, 0,
|
||||
NIVision.MeasurementType.MT_CENTER_OF_MASS_X);
|
||||
center_mass_y =
|
||||
(int) NIVision.imaqMeasureParticle(image.image, index, 0,
|
||||
NIVision.MeasurementType.MT_CENTER_OF_MASS_Y);
|
||||
center_mass_x_normalized = (2.0 * center_mass_x / imageWidth) - 1.0;
|
||||
center_mass_y_normalized = (2.0 * center_mass_y / imageHeight) - 1.0;
|
||||
particleArea =
|
||||
NIVision.imaqMeasureParticle(image.image, index, 0, NIVision.MeasurementType.MT_AREA);
|
||||
boundingRectLeft =
|
||||
(int) NIVision.imaqMeasureParticle(image.image, index, 0,
|
||||
NIVision.MeasurementType.MT_BOUNDING_RECT_LEFT);
|
||||
boundingRectTop =
|
||||
(int) NIVision.imaqMeasureParticle(image.image, index, 0,
|
||||
NIVision.MeasurementType.MT_BOUNDING_RECT_TOP);
|
||||
boundingRectWidth =
|
||||
(int) NIVision.imaqMeasureParticle(image.image, index, 0,
|
||||
NIVision.MeasurementType.MT_BOUNDING_RECT_WIDTH);
|
||||
boundingRectHeight =
|
||||
(int) NIVision.imaqMeasureParticle(image.image, index, 0,
|
||||
NIVision.MeasurementType.MT_BOUNDING_RECT_HEIGHT);
|
||||
particleToImagePercent =
|
||||
NIVision.imaqMeasureParticle(image.image, index, 0,
|
||||
NIVision.MeasurementType.MT_AREA_BY_IMAGE_AREA);
|
||||
particleQuality =
|
||||
NIVision.imaqMeasureParticle(image.image, index, 0,
|
||||
NIVision.MeasurementType.MT_AREA_BY_PARTICLE_AND_HOLES_AREA);
|
||||
}
|
||||
|
||||
static double getParticleToImagePercent(BinaryImage image, int index) throws NIVisionException {
|
||||
return NIVision.imaqMeasureParticle(image.image, index, 0,
|
||||
NIVision.MeasurementType.MT_AREA_BY_IMAGE_AREA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string representation of the particle analysis report.
|
||||
*
|
||||
* @return A string representation of the particle analysis report.
|
||||
*/
|
||||
public String toString() {
|
||||
return "Particle Report: \n" + " Image Height : " + imageHeight + "\n"
|
||||
+ " Image Width : " + imageWidth + "\n" + " Center of mass : ( " + center_mass_x
|
||||
+ " , " + center_mass_y + " )\n" + " normalized : ( " + center_mass_x_normalized
|
||||
+ " , " + center_mass_y_normalized + " )\n" + " Area : " + particleArea
|
||||
+ "\n" + " percent : " + particleToImagePercent + "\n"
|
||||
+ " Bounding Rect : ( " + boundingRectLeft + " , " + boundingRectTop + " ) "
|
||||
+ boundingRectWidth + "*" + boundingRectHeight + "\n" + " Quality : "
|
||||
+ particleQuality + "\n";
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.first.wpilibj.image;
|
||||
|
||||
import com.ni.vision.NIVision;
|
||||
|
||||
/**
|
||||
* A color image represented in RGB color space at 3 bytes per pixel.
|
||||
*/
|
||||
public class RGBImage extends ColorImage {
|
||||
|
||||
/**
|
||||
* Create a new 0x0 image.
|
||||
*/
|
||||
public RGBImage() throws NIVisionException {
|
||||
super(NIVision.ImageType.IMAGE_RGB);
|
||||
}
|
||||
|
||||
RGBImage(RGBImage sourceImage) {
|
||||
super(sourceImage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new image by loading a file.
|
||||
*
|
||||
* @param fileName The path of the file to load.
|
||||
*/
|
||||
public RGBImage(String fileName) throws NIVisionException {
|
||||
super(NIVision.ImageType.IMAGE_RGB);
|
||||
NIVision.imaqReadFile(image, fileName);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Image Processing Wrappers</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=MacRoman">
|
||||
</head>
|
||||
<body>
|
||||
Provides classes to access National Instrument's nivison library for machine vision enables
|
||||
automated image processing for color identification, tracking and analysis. The full
|
||||
specification for the simplified FRC Vision programming interface is in the FRC Vision API
|
||||
Specification document, which is in the WindRiver\docs\extensions\FRC directory of the Wind River
|
||||
installation with this document.
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,550 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.first.wpilibj.vision;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import edu.wpi.first.wpilibj.Timer;
|
||||
import edu.wpi.first.wpilibj.image.ColorImage;
|
||||
import edu.wpi.first.wpilibj.image.HSLImage;
|
||||
import edu.wpi.first.wpilibj.image.NIVisionException;
|
||||
|
||||
import static com.ni.vision.NIVision.Image;
|
||||
import static com.ni.vision.NIVision.Priv_ReadJPEGString_C;
|
||||
|
||||
/**
|
||||
* Axis M1011 network camera.
|
||||
*/
|
||||
public class AxisCamera {
|
||||
public enum WhiteBalance {
|
||||
kAutomatic, kHold, kFixedOutdoor1, kFixedOutdoor2, kFixedIndoor, kFixedFluorescent1,
|
||||
kFixedFluorescent2,
|
||||
}
|
||||
|
||||
public enum ExposureControl {
|
||||
kAutomatic, kHold, kFlickerFree50Hz, kFlickerFree60Hz,
|
||||
}
|
||||
|
||||
public enum Resolution {
|
||||
k640x480, k480x360, k320x240, k240x180, k176x144, k160x120,
|
||||
}
|
||||
|
||||
public enum Rotation {
|
||||
k0, k180
|
||||
}
|
||||
|
||||
private static final String[] kWhiteBalanceStrings = {"auto", "hold", "fixed_outdoor1",
|
||||
"fixed_outdoor2", "fixed_indoor", "fixed_fluor1", "fixed_fluor2",};
|
||||
|
||||
private static final String[] kExposureControlStrings = {"auto", "hold", "flickerfree50",
|
||||
"flickerfree60",};
|
||||
|
||||
private static final String[] kResolutionStrings = {"640x480", "480x360", "320x240", "240x180",
|
||||
"176x144", "160x120",};
|
||||
|
||||
private static final String[] kRotationStrings = {"0", "180",};
|
||||
|
||||
private static final int kImageBufferAllocationIncrement = 1000;
|
||||
|
||||
private String m_cameraHost;
|
||||
private Socket m_cameraSocket;
|
||||
|
||||
private ByteBuffer m_imageData = ByteBuffer.allocate(5000);
|
||||
private final Object m_imageDataLock = new Object();
|
||||
private boolean m_freshImage = false;
|
||||
|
||||
private int m_brightness = 50;
|
||||
private WhiteBalance m_whiteBalance = WhiteBalance.kAutomatic;
|
||||
private int m_colorLevel = 50;
|
||||
private ExposureControl m_exposureControl = ExposureControl.kAutomatic;
|
||||
private int m_exposurePriority = 50;
|
||||
private int m_maxFPS = 0;
|
||||
private Resolution m_resolution = Resolution.k640x480;
|
||||
private int m_compression = 50;
|
||||
private Rotation m_rotation = Rotation.k0;
|
||||
private final Object m_parametersLock = new Object();
|
||||
private boolean m_parametersDirty = true;
|
||||
private boolean m_streamDirty = true;
|
||||
|
||||
private boolean m_done = false;
|
||||
|
||||
/**
|
||||
* AxisCamera constructor.
|
||||
*
|
||||
* @param cameraHost The host to find the camera at, typically an IP address
|
||||
*/
|
||||
public AxisCamera(String cameraHost) {
|
||||
m_cameraHost = cameraHost;
|
||||
|
||||
/*
|
||||
Thread spawned by AxisCamera constructor to receive images from cam.
|
||||
*/
|
||||
final Thread captureThread = new Thread(() -> {
|
||||
int consecutiveErrors = 0;
|
||||
|
||||
// Loop on trying to setup the camera connection. This happens in a
|
||||
// background
|
||||
// thread so it shouldn't effect the operation of user programs.
|
||||
while (!m_done) {
|
||||
String requestString =
|
||||
"GET /mjpg/video.mjpg HTTP/1.1\n" + "User-Agent: HTTPStreamClient\n"
|
||||
+ "Connection: Keep-Alive\n" + "Cache-Control: no-cache\n"
|
||||
+ "Authorization: Basic RlJDOkZSQw==\n\n";
|
||||
|
||||
try {
|
||||
m_cameraSocket = AxisCamera.this.createCameraSocket(requestString);
|
||||
AxisCamera.this.readImagesFromCamera();
|
||||
consecutiveErrors = 0;
|
||||
} catch (IOException ex) {
|
||||
consecutiveErrors++;
|
||||
|
||||
if (consecutiveErrors > 5) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
Timer.delay(0.5);
|
||||
}
|
||||
});
|
||||
captureThread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the latest image from the camera has not been retrieved by calling GetImage()
|
||||
* yet.
|
||||
*
|
||||
* @return true if the image has not been retrieved yet.
|
||||
*/
|
||||
public boolean isFreshImage() {
|
||||
return m_freshImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an image from the camera and store it in the provided image.
|
||||
*
|
||||
* @param image The imaq image to store the result in. This must be an HSL or RGB image.
|
||||
* @return <code>true</code> upon success, <code>false</code> on a failure
|
||||
*/
|
||||
public boolean getImage(Image image) {
|
||||
if (m_imageData.limit() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
synchronized (m_imageDataLock) {
|
||||
Priv_ReadJPEGString_C(image, m_imageData.array());
|
||||
}
|
||||
|
||||
m_freshImage = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an image from the camera and store it in the provided image.
|
||||
*
|
||||
* @param image The image to store the result in. This must be an HSL or RGB image
|
||||
* @return true upon success, false on a failure
|
||||
*/
|
||||
public boolean getImage(ColorImage image) {
|
||||
return this.getImage(image.image);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a new image object and fill it with the latest image from the camera.
|
||||
*
|
||||
* @return a pointer to an HSLImage object
|
||||
*/
|
||||
public HSLImage getImage() throws NIVisionException {
|
||||
HSLImage image = new HSLImage();
|
||||
this.getImage(image);
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a change in the brightness of the camera images.
|
||||
*
|
||||
* @param brightness valid values 0 .. 100
|
||||
*/
|
||||
public void writeBrightness(int brightness) {
|
||||
if (brightness < 0 || brightness > 100) {
|
||||
throw new IllegalArgumentException("Brightness must be from 0 to 100");
|
||||
}
|
||||
|
||||
synchronized (m_parametersLock) {
|
||||
if (m_brightness != brightness) {
|
||||
m_brightness = brightness;
|
||||
m_parametersDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The brightness.
|
||||
*
|
||||
* @return The configured brightness of the camera images
|
||||
*/
|
||||
public int getBrightness() {
|
||||
synchronized (m_parametersLock) {
|
||||
return m_brightness;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a change in the white balance on the camera.
|
||||
*
|
||||
* @param whiteBalance Valid values from the <code>WhiteBalance</code> enum.
|
||||
*/
|
||||
public void writeWhiteBalance(WhiteBalance whiteBalance) {
|
||||
synchronized (m_parametersLock) {
|
||||
if (m_whiteBalance != whiteBalance) {
|
||||
m_whiteBalance = whiteBalance;
|
||||
m_parametersDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The white balance.
|
||||
*
|
||||
* @return The configured white balances of the camera images
|
||||
*/
|
||||
public WhiteBalance getWhiteBalance() {
|
||||
synchronized (m_parametersLock) {
|
||||
return m_whiteBalance;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a change in the color level of the camera images.
|
||||
*
|
||||
* @param colorLevel valid values are 0 .. 100
|
||||
*/
|
||||
public void writeColorLevel(int colorLevel) {
|
||||
if (colorLevel < 0 || colorLevel > 100) {
|
||||
throw new IllegalArgumentException("Color level must be from 0 to 100");
|
||||
}
|
||||
|
||||
synchronized (m_parametersLock) {
|
||||
if (m_colorLevel != colorLevel) {
|
||||
m_colorLevel = colorLevel;
|
||||
m_parametersDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The current color level.
|
||||
*
|
||||
* @return The configured color level of the camera images
|
||||
*/
|
||||
public int getColorLevel() {
|
||||
synchronized (m_parametersLock) {
|
||||
return m_colorLevel;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a change in the camera's exposure mode.
|
||||
*
|
||||
* @param exposureControl A mode to write in the <code>Exposure</code> enum.
|
||||
*/
|
||||
public void writeExposureControl(ExposureControl exposureControl) {
|
||||
synchronized (m_parametersLock) {
|
||||
if (m_exposureControl != exposureControl) {
|
||||
m_exposureControl = exposureControl;
|
||||
m_parametersDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The current exposure control.
|
||||
*
|
||||
* @return The configured exposure control mode of the camera
|
||||
*/
|
||||
public ExposureControl getExposureControl() {
|
||||
synchronized (m_parametersLock) {
|
||||
return m_exposureControl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a change in the exposure priority of the camera.
|
||||
*
|
||||
* @param exposurePriority Valid values are 0, 50, 100. 0 = Prioritize image quality 50 = None 100
|
||||
* = Prioritize frame rate
|
||||
*/
|
||||
public void writeExposurePriority(int exposurePriority) {
|
||||
if (exposurePriority != 0 && exposurePriority != 50 && exposurePriority != 100) {
|
||||
throw new IllegalArgumentException("Exposure priority must be 0, 50, or 100");
|
||||
}
|
||||
|
||||
synchronized (m_parametersLock) {
|
||||
if (m_exposurePriority != exposurePriority) {
|
||||
m_exposurePriority = exposurePriority;
|
||||
m_parametersDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exposure priority.
|
||||
*
|
||||
* @return The configured exposure priority of the camera
|
||||
*/
|
||||
public int getExposurePriority() {
|
||||
synchronized (m_parametersLock) {
|
||||
return m_exposurePriority;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the maximum frames per second that the camera should send Write 0 to send as many as
|
||||
* possible.
|
||||
*
|
||||
* @param maxFPS The number of frames the camera should send in a second, exposure permitting.
|
||||
*/
|
||||
public void writeMaxFPS(int maxFPS) {
|
||||
synchronized (m_parametersLock) {
|
||||
if (m_maxFPS != maxFPS) {
|
||||
m_maxFPS = maxFPS;
|
||||
m_parametersDirty = true;
|
||||
m_streamDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The max frames per second of the camera.
|
||||
*
|
||||
* @return The configured maximum FPS of the camera
|
||||
*/
|
||||
public int getMaxFPS() {
|
||||
synchronized (m_parametersLock) {
|
||||
return m_maxFPS;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write resolution value to camera.
|
||||
*
|
||||
* @param resolution The camera resolution value to write to the camera.
|
||||
*/
|
||||
public void writeResolution(Resolution resolution) {
|
||||
synchronized (m_parametersLock) {
|
||||
if (m_resolution != resolution) {
|
||||
m_resolution = resolution;
|
||||
m_parametersDirty = true;
|
||||
m_streamDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configured resolution (not necessarily the same resolution as the most recent
|
||||
* image, if it was changed recently).
|
||||
*
|
||||
* @return The configured resolution of the camera.
|
||||
*/
|
||||
public Resolution getResolution() {
|
||||
synchronized (m_parametersLock) {
|
||||
return m_resolution;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the compression value to the camera.
|
||||
*
|
||||
* @param compression Values between 0 and 100.
|
||||
*/
|
||||
public void writeCompression(int compression) {
|
||||
if (compression < 0 || compression > 100) {
|
||||
throw new IllegalArgumentException("Compression must be from 0 to 100");
|
||||
}
|
||||
|
||||
synchronized (m_parametersLock) {
|
||||
if (m_compression != compression) {
|
||||
m_compression = compression;
|
||||
m_parametersDirty = true;
|
||||
m_streamDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configured compression level of the camera images.
|
||||
*
|
||||
* @return The configured compression level of the camera images.
|
||||
*/
|
||||
public int getCompression() {
|
||||
synchronized (m_parametersLock) {
|
||||
return m_compression;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the motation value to the camera. If you mount your camera upside down, use this to
|
||||
* adjust the image for you.
|
||||
*
|
||||
* @param rotation A value from the {@link Rotation} enum
|
||||
*/
|
||||
public void writeRotation(Rotation rotation) {
|
||||
synchronized (m_parametersLock) {
|
||||
if (m_rotation != rotation) {
|
||||
m_rotation = rotation;
|
||||
m_parametersDirty = true;
|
||||
m_streamDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configured rotation mode of the camera.
|
||||
*
|
||||
* @return The configured rotation mode of the camera
|
||||
*/
|
||||
public Rotation getRotation() {
|
||||
synchronized (m_parametersLock) {
|
||||
return m_rotation;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function actually reads the images from the camera.
|
||||
*/
|
||||
private void readImagesFromCamera() throws IOException {
|
||||
DataInputStream cameraInputStream = new DataInputStream(m_cameraSocket.getInputStream());
|
||||
|
||||
while (!m_done) {
|
||||
String line = cameraInputStream.readLine();
|
||||
|
||||
if (line.startsWith("Content-Length: ")) {
|
||||
int contentLength = Integer.valueOf(line.substring(16));
|
||||
|
||||
/* Skip the next blank line */
|
||||
cameraInputStream.readLine();
|
||||
contentLength -= 4;
|
||||
|
||||
/* The next four bytes are the JPEG magic number */
|
||||
byte[] data = new byte[contentLength];
|
||||
cameraInputStream.readFully(data);
|
||||
|
||||
synchronized (m_imageDataLock) {
|
||||
if (m_imageData.capacity() < data.length) {
|
||||
m_imageData = ByteBuffer.allocate(data.length + kImageBufferAllocationIncrement);
|
||||
}
|
||||
|
||||
m_imageData.clear();
|
||||
m_imageData.limit(contentLength);
|
||||
m_imageData.put(data);
|
||||
|
||||
m_freshImage = true;
|
||||
}
|
||||
|
||||
if (this.writeParameters()) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Skip the boundary and Content-Type header */
|
||||
cameraInputStream.readLine();
|
||||
cameraInputStream.readLine();
|
||||
}
|
||||
}
|
||||
|
||||
m_cameraSocket.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a request to the camera to set all of the parameters. This is called in the capture thread
|
||||
* between each frame. This strategy avoids making lots of redundant HTTP requests, accounts for
|
||||
* failed initial requests, and avoids blocking calls in the main thread unless necessary.
|
||||
*
|
||||
* <p>This method does nothing if no parameters have been modified since it last completely
|
||||
* successfully.
|
||||
*
|
||||
* @return <code>true</code> if the stream should be restarted due to a parameter changing.
|
||||
*/
|
||||
private boolean writeParameters() {
|
||||
if (m_parametersDirty) {
|
||||
String request = "GET /axis-cgi/admin/param.cgi?action=update";
|
||||
|
||||
synchronized (m_parametersLock) {
|
||||
request += "&ImageSource.I0.Sensor.Brightness=" + m_brightness;
|
||||
request +=
|
||||
"&ImageSource.I0.Sensor.WhiteBalance=" + kWhiteBalanceStrings[m_whiteBalance.ordinal()];
|
||||
request += "&ImageSource.I0.Sensor.ColorLevel=" + m_colorLevel;
|
||||
request +=
|
||||
"&ImageSource.I0.Sensor.Exposure="
|
||||
+ kExposureControlStrings[m_exposureControl.ordinal()];
|
||||
request += "&ImageSource.I0.Sensor.ExposurePriority=" + m_exposurePriority;
|
||||
request += "&Image.I0.Stream.FPS=" + m_maxFPS;
|
||||
request += "&Image.I0.Appearance.Resolution=" + kResolutionStrings[m_resolution.ordinal()];
|
||||
request += "&Image.I0.Appearance.Compression=" + m_compression;
|
||||
request += "&Image.I0.Appearance.Rotation=" + kRotationStrings[m_rotation.ordinal()];
|
||||
}
|
||||
|
||||
request += " HTTP/1.1\n";
|
||||
request += "User-Agent: HTTPStreamClient\n";
|
||||
request += "Connection: Keep-Alive\n";
|
||||
request += "Cache-Control: no-cache\n";
|
||||
request += "Authorization: Basic RlJDOkZSQw==\n\n";
|
||||
|
||||
try {
|
||||
Socket socket = createCameraSocket(request);
|
||||
socket.close();
|
||||
|
||||
m_parametersDirty = false;
|
||||
|
||||
if (m_streamDirty) {
|
||||
m_streamDirty = false;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (IOException | NullPointerException ex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a socket connected to camera Used to create a connection for reading images and setting
|
||||
* parameters
|
||||
*
|
||||
* @param requestString The initial request string to send upon successful connection.
|
||||
* @return The created socket
|
||||
*/
|
||||
private Socket createCameraSocket(String requestString) throws IOException {
|
||||
/* Connect to the server */
|
||||
Socket socket = new Socket();
|
||||
socket.connect(new InetSocketAddress(m_cameraHost, 80), 5000);
|
||||
|
||||
/* Send the HTTP headers */
|
||||
OutputStream socketOutputStream = socket.getOutputStream();
|
||||
socketOutputStream.write(requestString.getBytes());
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AxisCamera{" + "FreshImage=" + isFreshImage() + ", Brightness=" + getBrightness()
|
||||
+ ", WhiteBalance=" + getWhiteBalance() + ", ColorLevel=" + getColorLevel()
|
||||
+ ", ExposureControl=" + getExposureControl() + ", ExposurePriority="
|
||||
+ getExposurePriority() + ", MaxFPS=" + getMaxFPS() + ", Resolution=" + getResolution()
|
||||
+ ", Compression=" + getCompression() + ", Rotation=" + getRotation() + '}';
|
||||
}
|
||||
}
|
||||
@@ -1,387 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2016. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.first.wpilibj.vision;
|
||||
|
||||
import com.ni.vision.NIVision;
|
||||
import com.ni.vision.VisionException;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import edu.wpi.first.wpilibj.Timer;
|
||||
|
||||
public class USBCamera {
|
||||
public static final String kDefaultCameraName = "cam0";
|
||||
|
||||
private static final String ATTR_VIDEO_MODE = "AcquisitionAttributes::VideoMode";
|
||||
private static final String ATTR_WB_MODE = "CameraAttributes::WhiteBalance::Mode";
|
||||
private static final String ATTR_WB_VALUE = "CameraAttributes::WhiteBalance::Value";
|
||||
private static final String ATTR_EX_MODE = "CameraAttributes::Exposure::Mode";
|
||||
private static final String ATTR_EX_VALUE = "CameraAttributes::Exposure::Value";
|
||||
private static final String ATTR_BR_MODE = "CameraAttributes::Brightness::Mode";
|
||||
private static final String ATTR_BR_VALUE = "CameraAttributes::Brightness::Value";
|
||||
|
||||
public class WhiteBalance {
|
||||
public static final int kFixedIndoor = 3000;
|
||||
public static final int kFixedOutdoor1 = 4000;
|
||||
public static final int kFixedOutdoor2 = 5000;
|
||||
public static final int kFixedFluorescent1 = 5100;
|
||||
public static final int kFixedFlourescent2 = 5200;
|
||||
}
|
||||
|
||||
private Pattern m_reMode =
|
||||
Pattern
|
||||
.compile("(?<width>[0-9]+)\\s*x\\s*(?<height>[0-9]+)\\s+(?<format>.*?)"
|
||||
+ "\\s+(?<fps>[0-9.]+)\\s*fps");
|
||||
|
||||
private String m_name = kDefaultCameraName;
|
||||
private int m_id = -1;
|
||||
private boolean m_active = false;
|
||||
private boolean m_useJpeg = true;
|
||||
private int m_width = 320;
|
||||
private int m_height = 240;
|
||||
private int m_fps = 30;
|
||||
private String m_whiteBalance = "auto";
|
||||
private int m_whiteBalanceValue = -1;
|
||||
private String m_exposure = "auto";
|
||||
private int m_exposureValue = -1;
|
||||
private int m_brightness = 50;
|
||||
private boolean m_needSettingsUpdate = true;
|
||||
|
||||
public USBCamera() {
|
||||
openCamera();
|
||||
}
|
||||
|
||||
public USBCamera(String name) {
|
||||
m_name = name;
|
||||
openCamera();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the camera.
|
||||
*/
|
||||
public synchronized void openCamera() {
|
||||
if (m_id != -1) {
|
||||
return; // Camera is already open
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
try {
|
||||
m_id =
|
||||
NIVision.IMAQdxOpenCamera(m_name,
|
||||
NIVision.IMAQdxCameraControlMode.CameraControlModeController);
|
||||
} catch (VisionException ex) {
|
||||
if (i == 2) {
|
||||
throw ex;
|
||||
}
|
||||
Timer.delay(2.0);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the camera.
|
||||
*/
|
||||
public synchronized void closeCamera() {
|
||||
if (m_id == -1) {
|
||||
return;
|
||||
}
|
||||
NIVision.IMAQdxCloseCamera(m_id);
|
||||
m_id = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts capturing images from the camera.
|
||||
*/
|
||||
public synchronized void startCapture() {
|
||||
if (m_id == -1 || m_active) {
|
||||
return;
|
||||
}
|
||||
NIVision.IMAQdxConfigureGrab(m_id);
|
||||
NIVision.IMAQdxStartAcquisition(m_id);
|
||||
m_active = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops acquiring new images from the camera.
|
||||
*/
|
||||
public synchronized void stopCapture() {
|
||||
if (m_id == -1 || !m_active) {
|
||||
return;
|
||||
}
|
||||
NIVision.IMAQdxStopAcquisition(m_id);
|
||||
NIVision.IMAQdxUnconfigureAcquisition(m_id);
|
||||
m_active = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the settings for the camera.
|
||||
*/
|
||||
public synchronized void updateSettings() {
|
||||
boolean wasActive = m_active;
|
||||
// Stop acquistion, close and reopen camera
|
||||
if (wasActive) {
|
||||
stopCapture();
|
||||
}
|
||||
if (m_id != -1) {
|
||||
closeCamera();
|
||||
}
|
||||
openCamera();
|
||||
|
||||
// Video Mode
|
||||
NIVision.dxEnumerateVideoModesResult enumerated = NIVision.IMAQdxEnumerateVideoModes(m_id);
|
||||
NIVision.IMAQdxEnumItem foundMode = null;
|
||||
int foundFps = 1000;
|
||||
for (NIVision.IMAQdxEnumItem mode : enumerated.videoModeArray) {
|
||||
Matcher matcher = m_reMode.matcher(mode.Name);
|
||||
if (!matcher.matches()) {
|
||||
continue;
|
||||
}
|
||||
if (Integer.parseInt(matcher.group("m_width")) != m_width) {
|
||||
continue;
|
||||
}
|
||||
if (Integer.parseInt(matcher.group("m_height")) != m_height) {
|
||||
continue;
|
||||
}
|
||||
double fps = Double.parseDouble(matcher.group("fps"));
|
||||
if (fps < m_fps) {
|
||||
continue;
|
||||
}
|
||||
if (fps > foundFps) {
|
||||
continue;
|
||||
}
|
||||
String format = matcher.group("format");
|
||||
boolean isJpeg = format.equals("jpeg") || format.equals("JPEG");
|
||||
if ((m_useJpeg && !isJpeg) || (!m_useJpeg && isJpeg)) {
|
||||
continue;
|
||||
}
|
||||
foundMode = mode;
|
||||
foundFps = (int) fps;
|
||||
}
|
||||
if (foundMode != null) {
|
||||
System.out.println("found mode " + foundMode.Value + ": " + foundMode.Name);
|
||||
if (foundMode.Value != enumerated.currentMode) {
|
||||
NIVision.IMAQdxSetAttributeU32(m_id, ATTR_VIDEO_MODE, foundMode.Value);
|
||||
}
|
||||
}
|
||||
|
||||
// White Balance
|
||||
if ("auto".equals(m_whiteBalance)) {
|
||||
NIVision.IMAQdxSetAttributeString(m_id, ATTR_WB_MODE, "Auto");
|
||||
} else {
|
||||
NIVision.IMAQdxSetAttributeString(m_id, ATTR_WB_MODE, "Manual");
|
||||
if (m_whiteBalanceValue != -1) {
|
||||
NIVision.IMAQdxSetAttributeI64(m_id, ATTR_WB_VALUE, m_whiteBalanceValue);
|
||||
}
|
||||
}
|
||||
|
||||
// Exposure
|
||||
if ("auto".equals(m_exposure)) {
|
||||
NIVision.IMAQdxSetAttributeString(m_id, ATTR_EX_MODE, "AutoAperaturePriority");
|
||||
} else {
|
||||
NIVision.IMAQdxSetAttributeString(m_id, ATTR_EX_MODE, "Manual");
|
||||
if (m_exposureValue != -1) {
|
||||
long minv = NIVision.IMAQdxGetAttributeMinimumI64(m_id, ATTR_EX_VALUE);
|
||||
long maxv = NIVision.IMAQdxGetAttributeMaximumI64(m_id, ATTR_EX_VALUE);
|
||||
long val = minv + (long) (((double) (maxv - minv)) * (((double) m_exposureValue) / 100.0));
|
||||
NIVision.IMAQdxSetAttributeI64(m_id, ATTR_EX_VALUE, val);
|
||||
}
|
||||
}
|
||||
|
||||
// Brightness
|
||||
NIVision.IMAQdxSetAttributeString(m_id, ATTR_BR_MODE, "Manual");
|
||||
long minv = NIVision.IMAQdxGetAttributeMinimumI64(m_id, ATTR_BR_VALUE);
|
||||
long maxv = NIVision.IMAQdxGetAttributeMaximumI64(m_id, ATTR_BR_VALUE);
|
||||
long val = minv + (long) (((double) (maxv - minv)) * (((double) m_brightness) / 100.0));
|
||||
NIVision.IMAQdxSetAttributeI64(m_id, ATTR_BR_VALUE, val);
|
||||
|
||||
// Restart acquisition
|
||||
if (wasActive) {
|
||||
startCapture();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the frames per second that the camera frames should be acquired at.
|
||||
*
|
||||
* @param fps The frames per second.
|
||||
*/
|
||||
public synchronized void setFPS(int fps) {
|
||||
if (m_fps != fps) {
|
||||
m_needSettingsUpdate = true;
|
||||
m_fps = fps;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the input of the USB camera.
|
||||
*
|
||||
* @param width The m_width of the camera input.
|
||||
* @param height The m_height of the camera input.
|
||||
*/
|
||||
public synchronized void setSize(int width, int height) {
|
||||
if (m_width != width || m_height != height) {
|
||||
m_needSettingsUpdate = true;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the m_brightness, as a percentage (0-100).
|
||||
*/
|
||||
public synchronized void setBrightness(int brightness) {
|
||||
if (brightness > 100) {
|
||||
m_brightness = 100;
|
||||
} else if (brightness < 0) {
|
||||
m_brightness = 0;
|
||||
} else {
|
||||
m_brightness = brightness;
|
||||
}
|
||||
m_needSettingsUpdate = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the m_brightness, as a percentage (0-100).
|
||||
*/
|
||||
public synchronized int getBrightness() {
|
||||
return m_brightness;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the white balance to auto.
|
||||
*/
|
||||
public synchronized void setWhiteBalanceAuto() {
|
||||
m_whiteBalance = "auto";
|
||||
m_whiteBalanceValue = -1;
|
||||
m_needSettingsUpdate = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the white balance to hold current.
|
||||
*/
|
||||
public synchronized void setWhiteBalanceHoldCurrent() {
|
||||
m_whiteBalance = "manual";
|
||||
m_whiteBalanceValue = -1;
|
||||
m_needSettingsUpdate = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the white balance to manual, with specified color temperature.
|
||||
*/
|
||||
public synchronized void setWhiteBalanceManual(int value) {
|
||||
m_whiteBalance = "manual";
|
||||
m_whiteBalanceValue = value;
|
||||
m_needSettingsUpdate = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the m_exposure to auto aperature.
|
||||
*/
|
||||
public synchronized void setExposureAuto() {
|
||||
m_exposure = "auto";
|
||||
m_exposureValue = -1;
|
||||
m_needSettingsUpdate = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the m_exposure to hold current.
|
||||
*/
|
||||
public synchronized void setExposureHoldCurrent() {
|
||||
m_exposure = "manual";
|
||||
m_exposureValue = -1;
|
||||
m_needSettingsUpdate = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the m_exposure to manual, as a percentage (0-100).
|
||||
*/
|
||||
public synchronized void setExposureManual(int value) {
|
||||
m_exposure = "manual";
|
||||
if (value > 100) {
|
||||
m_exposureValue = 100;
|
||||
} else if (value < 0) {
|
||||
m_exposureValue = 0;
|
||||
} else {
|
||||
m_exposureValue = value;
|
||||
m_needSettingsUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the image from the camera.
|
||||
*
|
||||
* @param image The image to store the data into
|
||||
*/
|
||||
public synchronized void getImage(NIVision.Image image) {
|
||||
if (m_needSettingsUpdate || m_useJpeg) {
|
||||
m_needSettingsUpdate = false;
|
||||
m_useJpeg = false;
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
NIVision.IMAQdxGrab(m_id, image, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the image data from the camera.
|
||||
*
|
||||
* @param data Where to put the data from the image
|
||||
*/
|
||||
public synchronized void getImageData(ByteBuffer data) {
|
||||
if (m_needSettingsUpdate || !m_useJpeg) {
|
||||
m_needSettingsUpdate = false;
|
||||
m_useJpeg = true;
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
NIVision
|
||||
.IMAQdxGetImageData(m_id, data, NIVision.IMAQdxBufferNumberMode.BufferNumberModeLast, 0);
|
||||
data.limit(data.capacity() - 1);
|
||||
data.limit(getJpegSize(data));
|
||||
}
|
||||
|
||||
private static int getJpegSize(ByteBuffer data) {
|
||||
if (data.get(0) != (byte) 0xff || data.get(1) != (byte) 0xd8) {
|
||||
throw new VisionException("invalid image");
|
||||
}
|
||||
int pos = 2;
|
||||
while (true) {
|
||||
try {
|
||||
byte byteAtIndex = data.get(pos);
|
||||
if (byteAtIndex != (byte) 0xff) {
|
||||
throw new VisionException("invalid image at pos " + pos + " (" + data.get(pos) + ")");
|
||||
}
|
||||
byteAtIndex = data.get(pos + 1);
|
||||
if (byteAtIndex == (byte) 0x01
|
||||
|| (byteAtIndex >= (byte) 0xd0 && byteAtIndex <= (byte) 0xd7)) { // various
|
||||
pos += 2;
|
||||
} else if (byteAtIndex == (byte) 0xd9) { // EOI
|
||||
return pos + 2;
|
||||
} else if (byteAtIndex == (byte) 0xd8) { // SOI
|
||||
throw new VisionException("invalid image");
|
||||
} else if (byteAtIndex == (byte) 0xda) { // SOS
|
||||
int len = ((data.get(pos + 2) & 0xff) << 8) | (data.get(pos + 3) & 0xff);
|
||||
pos += len + 2;
|
||||
// Find next marker. Skip over escaped and RST markers.
|
||||
while (data.get(pos) != (byte) 0xff || data.get(pos + 1) == (byte) 0x00
|
||||
|| (data.get(pos + 1) >= (byte) 0xd0 && data.get(pos + 1) <= (byte) 0xd7)) {
|
||||
pos += 1;
|
||||
}
|
||||
} else { // various
|
||||
int len = ((data.get(pos + 2) & 0xff) << 8) | (data.get(pos + 3) & 0xff);
|
||||
pos += len + 2;
|
||||
}
|
||||
} catch (IndexOutOfBoundsException ex) {
|
||||
throw new VisionException("invalid image: could not find jpeg end " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user