📄 sfcapproc.cpp
字号:
/******************************************************************************/
/* */
/* Name: SFcapProc.c - S-Function which reads the framegrabber card and */
/* outputs a pair of coordinates of an object with a */
/* user specified colour profile */
/* */
/******************************************************************************/
/****************************************************************************************/
//
// fw-01-08
//
// captures images from the firewire camera and processes them
//
/****************************************************************************************/
// =============================================================================
// fw-04-05
//
// level 2 s-function
//
// Compile: At the MATLAB prompt type: 'cc'
//
// =============================================================================
// =============================================================================
// fw-02-06 : fire-i interface
// =============================================================================
// =============================================================================
// fw-01-08 : CMU firewire driver (V6.4.4)
// =============================================================================
#define S_FUNCTION_NAME SFcapProc
#define S_FUNCTION_LEVEL 2
/* includes --------------------------------------------------------------------- */
#include <windows.h>
#include <string.h> // strcmpi, strcpy
#include "1394camera.h"
#include "cmvision.h"
#include "mex.h"
#include "matrix.h"
// Simulink
#include <simstruc.h>
// -------------------------------------------------------------------------------
// Number of S-function Parameters and macros to access from the SimStruct
// -------------------------------------------------------------------------------
#define COLFILE_ARG ssGetSFcnParam(S,0) /* colour definition file (filename) */
#define COLFLEN_ARG ssGetSFcnParam(S,1) /* length of the colour definition filename */
#define NUMCOLS_ARG ssGetSFcnParam(S,2) /* number of colours to be scanned for */
#define DISPIMG_ARG ssGetSFcnParam(S,3) /* flag: display camera image (yes = 1, no = 0) */
#define DISPMOD_ARG ssGetSFcnParam(S,4) /* flag: display RGB image (1) or classified image (2) */
#define CAMMODE_ARG ssGetSFcnParam(S,5) /* camera mode */
#define ACQMODE_ARG ssGetSFcnParam(S,6) /* acquisition mode: capImage (1) or acqImage (2) */
#define NUMBER_OF_ARG 7 /* Number of input arguments */
// -------------------------------------------------------------------------------
// Macros to access the S-function parameter values
// -------------------------------------------------------------------------------
#define COLFILE ((char_T *) mxGetPr (COLFILE_ARG))
#define COLFLEN ((uint_T) mxGetPr (COLFLEN_ARG)[0])
#define NUMCOLS ((uint_T) mxGetPr (NUMCOLS_ARG)[0])
#define DISPIMG ((uint_T) mxGetPr (DISPIMG_ARG)[0])
#define DISPMOD ((uint_T) mxGetPr (DISPMOD_ARG)[0])
#define CAMMODE ((uint_T) mxGetPr (CAMMODE_ARG)[0])
#define ACQMODE ((uint_T) mxGetPr (ACQMODE_ARG)[0])
// ----------------------------------------------------------------------------------------------------
// global variables
// ----------------------------------------------------------------------------------------------------
/* (static) global variables ---------------------------------------------------- */
C1394Camera theCamera;
C1394CameraControl *pControl;
/* camera display modes */
// mode table (supported by the CMU driver, format '0' only):
//
// 0: {160 ,120 ,COLOR_CODE_YUV444},
// 1: {320 ,240 ,COLOR_CODE_YUV422},
// 2: {640 ,480 ,COLOR_CODE_YUV411},
// 3: {640 ,480 ,COLOR_CODE_YUV422},
// 4: {640 ,480 ,COLOR_CODE_RGB8},
// 5: {640 ,480 ,COLOR_CODE_Y8},
// 6: {640 ,480 ,COLOR_CODE_Y16},
//
// NOTE: mode enumeration now in line with camera modes
// (formerly: 0 = RGB, 1 = YUV)
//
// fw-12-07
//
#define numMYCAMERAMODES 7
typedef enum {
CAMERA_STOP = -1,
CAMERA_YUV444_160x120,
CAMERA_YUV422_320x240,
CAMERA_YUV411_640x480,
CAMERA_YUV422_640x480,
CAMERA_RGB8_640x480,
CAMERA_Y8_640x480,
CAMERA_Y16_640x480
} myCameraModes;
// now static global...
static myCameraModes mode;
/* camera features to be controlled manually */
#define numMYFEATURES 7
static const struct feature_description {
LPCSTR name;
LPCSTR unit;
} myFeatures[numMYFEATURES] =
{
{"Brightness","%"},
{"Auto Exposure","eV"},
{"Sharpness",""},
{"White Balance", "K"},
{"Saturation","%"},
{"Shutter","sec"},
{"Gain","dB"},
};
static unsigned char *MATbuf; /* pointer to MATLAB memory */
#define NDIMS 3 // (maximum) dimension of the output data (RGB)
static unsigned int dims[NDIMS];
static unsigned long frameWidth, frameHeight;
static unsigned int origX, origY;
/* these variables control the reduction from the maximum frame size to a smaller window */
static unsigned int pixPerPacket; // number of pixels per camera packet (eg. 2 in YUYV, 1 in RGB, etc.)
static unsigned int packetSize; // camera packet size (4 for YUYV, 6 for UYYVYY, etc.)
static unsigned int firstPacketStart; // integer multiple of the size of a pixel packet
static unsigned int lastPacketStart; // integer multiple of the size of a pixel packet
static unsigned int processFrameWidth; // integer multiple of the size of a pixel packet
static unsigned int processFrameNumPix; // adjusted width (dims[1])
static unsigned int packetOffsetX; // return image might not start on a packet boundary...
/* this variable is set to one when the grabber object has been initialized */
static unsigned int initCamera = 0;
/* this variable is set according to the 'mode' call-up parameter */
static myCameraModes currentMode = CAMERA_STOP; // start with CAMERA_STOP mode (required for correct function)
// ######### CMVision ##########
static CMVision vision; /* CMVision class */
CMVision::region *reg;
static rgb *img = NULL; /* dynamically allocated buffer... used by 'testClassify' */
static image_pixel *yuyvBuf = NULL; /* pointer to converted input image (image_pixel, yuv422) */
#define colourFilenameLength 100
static char colourFilename[colourFilenameLength];
// results of vision processing (struct myREG)
#define defCOL 1 // default number of colours to be scanned for
#define maxCOLS 10 // maximum number of colours to be scanned for
#define maxREG 10 // maximum number of regions to be recogniced per colour
#define minAREA 16 // minimum area of 'valid' regions
struct myREG {
rgb colour;
unsigned int nREG;
unsigned int cen_x[maxREG];
unsigned int cen_y[maxREG];
unsigned int x1[maxREG];
unsigned int y1[maxREG];
unsigned int x2[maxREG];
unsigned int y2[maxREG];
} *retREG[CMV_MAX_COLORS];
static int cen_av_x[maxCOLS]; // output variables (x)
static int cen_av_y[maxCOLS]; // output variables (y)
static unsigned int retIMG, IMGmod, ACQmod; // flags: display image (y/n), image mode (regular/classified), acquisition mode (cap/acq)
static unsigned int numCOLS; // number of colours to be scanned for
/* visual feedback (optional) */
static mxArray *FGretIMG; /* optional display of image data -> need to create workspace variable */
static mxArray *FGretIMGhandle; /* optional display of image data -> now updating display via its handle */
static mxArray *FGretIMGfigureHdl; /* figure window handle */
static mxArray *FGretCEN[maxREG]; /* optional display of centroid info -> need to create workspace variable */
static mxArray *FGretBOX[maxREG]; /* optional display of boundary box -> need to create workspace variable */
static double myNaN; // IEEE representation of 'NaN'
static double *pVect5ArgData[2];
static double *pVect3ArgData;
static mxArray *SetPropStrings[8]; /* set command properties: 'XData', 'YData', 'FaceColor', 'CData', 'CloseRequestFcn', '', 'closereq', 'w-' */
static mxArray *Vect5U16Arg[2]; /* [NaN NaN NaN NaN NaN], [1 2 3 4 5] */
static mxArray *Vect3U16Arg; /* [0.3 0.7 0.1] */
static mxArray *SetArgsXData[3]; /* set(someHndl, 'XData', [1 2 3 4 5]) */
static mxArray *SetArgsYData[3]; /* set(someHndl, 'YData', [1 2 3 4 5]) */
static mxArray *SetArgsXDataNaN[3]; /* set(someHndl, 'XData', [NaN NaN NaN NaN NaN]) */
static mxArray *SetArgsYDataNaN[3]; /* set(someHndl, 'YData', [NaN NaN NaN NaN NaN]) */
static mxArray *SetArgsCData[3]; /* set(FGretIMGhandle, 'CData', MATbuf) */
static mxArray *SetArgsFaceColor[3]; /* set(someHndl, 'FaceColor', [1 2 3]) */
static mxArray *SetArgsCloseRequestFcnOff[3]; /* set(someHndl, 'CloseRequestFcn', '') */
static mxArray *SetArgsCloseRequestFcnOn[3]; /* set(someHndl, 'CloseRequestFcn', 'closereq') */
static mxArray *PlotArgs[3]; /* plot([NaN NaN NaN NaN NaN], [NaN NaN NaN NaN NaN], 'w-') */
// ----------------------------------------------------------------------------------------------------
// local methods
// ----------------------------------------------------------------------------------------------------
//----------------------------------------------------------
// additional CMVision functions
//----------------------------------------------------------
// taken from CMU driver: ...\1394CamRGB.cpp
#define CLAMP_TO_UCHAR(a) ((unsigned char)((a) < 0 ? 0 : ((a) > 255 ? 255 : (a))))
//----------------------------------------------------------
yuv rgb_to_yuv(int r, int g, int b) {
yuv c;
c.y = CLAMP_TO_UCHAR((int)(0.3*r + 0.5881*g + 0.1118*b));
c.u = CLAMP_TO_UCHAR((int)(-0.15*r - 0.2941*g + 0.3882*b + 128));
c.v = CLAMP_TO_UCHAR((int)(0.35*r - 0.2941*g - 0.0559*b + 128));
return c;
}
//----------------------------------------------------------
//----------------------------------------------------------
rgb yuv_to_rgb(unsigned char y, unsigned char u, unsigned char v) {
#ifdef ERASE________________________________________________
/*
* replaced by the equivalent calculation found in the CMU driver which
* uses integer maths only (-> higher performance)
* fw-01-08
*/
int U, V;
rgb c;
U = (int)(2*u - 256);
V = (int)(2*v - 256);
c.red = CLAMP_TO_UCHAR(y + V);
c.green = CLAMP_TO_UCHAR((int)(y - 0.51*V - 0.19*U));
c.blue = CLAMP_TO_UCHAR(y + U);
#endif /* ERASE_____________________________________________ */
/*
* in line with the CMU driver...
*/
long U, V, deltaG;
rgb c;
U = u - 128;
V = v - 128;
deltaG = (12727 * U + 33384 * V);
deltaG += (deltaG > 0 ? 32768 : -32768);
deltaG >>= 16;
c.red = CLAMP_TO_UCHAR( y + V );
c.green = CLAMP_TO_UCHAR( y - deltaG );
c.blue = CLAMP_TO_UCHAR( y + U );
return c;
}
//----------------------------------------------------------
//----------------------------------------------------------
void convYUYV_2_RGB(rgb *dest, yuv422 *src) {
unsigned long i;
yuv422 p;
//unsigned long size = dims[0]*processFrameNumPix/2; // 2 pixels per yuv422 packet (YUYV)
unsigned long size = frameHeight*frameWidth/2; // 2 pixels per yuv422 packet (YUYV)
for(i=0; i<size; i++) {
p = src[i];
dest[2*i + 0] = yuv_to_rgb(p.y1, p.u, p.v);
dest[2*i + 1] = yuv_to_rgb(p.y2, p.u, p.v);
}
}
//----------------------------------------------------------
//----------------------------------------------------------
void convY8_2_YUYV(image_pixel *dst, unsigned char *src) {
unsigned int row, col, k;
unsigned int BytesPerRow = (unsigned int)(frameWidth);
yuv myYUV[2]; // intermediate result
k = 0;
for(row=0; row<dims[0] /* height */; row++) {
for(col = 0; col<processFrameWidth; col+=2, k++) {
/* Y8 -> YUV */
myYUV[0] = rgb_to_yuv(src[(origY+row)*BytesPerRow + firstPacketStart+col ], \
src[(origY+row)*BytesPerRow + firstPacketStart+col ], \
src[(origY+row)*BytesPerRow + firstPacketStart+col ] );
myYUV[1] = rgb_to_yuv(src[(origY+row)*BytesPerRow + firstPacketStart+col + 1], \
src[(origY+row)*BytesPerRow + firstPacketStart+col + 1], \
src[(origY+row)*BytesPerRow + firstPacketStart+col + 1] );
/* YUV -> YUYV */
dst[k].u = (unsigned char)((myYUV[0].u + myYUV[1].u) >> 1); // u
dst[k].y1 = myYUV[0].y; // y1
dst[k].v = (unsigned char)((myYUV[0].v + myYUV[1].v) >> 1); // u
dst[k].y2 = myYUV[1].y; // y1
}
}
//mexPrintf("yuyv buffer contains %d elements\n", k);
}
//----------------------------------------------------------
//----------------------------------------------------------
void convY16_2_YUYV(image_pixel *dst, unsigned char *src) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -