Removes NiVision from allwpilib (#305)

This commit is contained in:
Thad House
2016-11-18 20:04:21 -08:00
committed by Peter Johnson
parent ecb873ff45
commit ac50d7cf8a
57 changed files with 0 additions and 65539 deletions

View File

@@ -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

View File

@@ -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___

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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,
&currentMode);
auto modes = std::make_unique<IMAQdxVideoMode[]>(count);
SAFE_IMAQ_CALL(IMAQdxEnumerateVideoModes, m_id, modes.get(), &count,
&currentMode);
// 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);
}

View File

@@ -17,7 +17,6 @@
#include "ErrorBase.h"
#include "HAL/HAL.h"
#include "nivision.h"
using namespace frc;

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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");
}

View File

@@ -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; }

View File

@@ -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;
}

View File

@@ -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");
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -1,5 +0,0 @@
[IMAQdxGetAttributeString]
outparams=value
[Block Comment]
exclude=

View File

@@ -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

View File

@@ -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)

View File

@@ -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/

View File

@@ -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()

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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() + "]";
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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";
}
}

View File

@@ -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);
}
}

View File

@@ -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>

View File

@@ -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() + '}';
}
}

View File

@@ -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());
}
}
}
}