📄 imgproctest.cpp
字号:
/****************************************************************************************/
// Compile: At the MATLAB prompt type: 'cc'
//
// fw-01-08
//
// processes a YUYV image (YCrCb 4:2:2 or 'yuv422')
//
/****************************************************************************************/
/* includes --------------------------------------------------------------------- */
#include <windows.h>
#include <string.h> // strcmpi, strcpy
#include "cmvision.h"
#include "mex.h"
#include "matrix.h"
#define NDIMS 3 // (maximum) dimension of the output data (RGB)
static unsigned int dims[NDIMS];
static unsigned long frameWidth, frameHeight;
// ######### 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];
static const char *defColourFilename = "testcolors.txt"; /* default colour file name */
// results of vision processing (struct myREG)
#define defCOL 1 // default 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 colourID;
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];
const char *fnames[4] = {"ColourID", "Colour", "nRegions", "Regions"};
int foutdims[] = {0,0}; // dimensions of the output cell array
/* global variables, local to the DLL */
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 *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'
double *pArgs;
static mxArray *PatchArgs[3]; /* patch([NaN NaN NaN NaN NaN], [NaN NaN NaN NaN NaN], [0 0 0]) */
static mxArray *PlotArgs[3]; /* plot([NaN NaN NaN NaN NaN], [NaN NaN NaN NaN NaN], 'w-') */
static mxArray *SetArgStrings[4]; /* set command property: 'XData', 'YData', 'FaceColor', 'CData' */
static mxArray *SetArgs[3];
/* local functions -------------------------------------------------------- */
//----------------------------------------------------------
// 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(unsigned char r, unsigned char g, unsigned char b) {
yuv c;
//c.y = CLAMP_TO_UCHAR(0.3*r + 0.5881*g + 0.1118*b);
//c.u = CLAMP_TO_UCHAR(-0.15*r - 0.2941*g + 0.3882*b + 128);
//c.v = CLAMP_TO_UCHAR(0.35*r - 0.2941*g - 0.0559*b + 128);
c.y = CLAMP_TO_UCHAR((unsigned int)(0.3*r + 0.5881*g + 0.1118*b));
c.u = CLAMP_TO_UCHAR((unsigned int)(-0.15*r - 0.2941*g + 0.3882*b + 128));
c.v = CLAMP_TO_UCHAR((unsigned 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 convRGB_2_YUYV(image_pixel *dst, unsigned char *src) {
unsigned int row, col, k;
yuv myYUV[2]; // intermediate result
k = 0;
for(row=0; row<frameHeight; row++) {
for(col = 0; col<frameWidth-1; col+=2, k++) {
#ifdef ERASE
mexPrintf("row = %-3d | col = %-3d | idx = %-3d | R = %-3d\n", row, col, row + col*frameHeight + 0*frameWidth*frameHeight, src[row + col*frameHeight + 0*frameWidth*frameHeight]);
mexPrintf("row = %-3d | col = %-3d | idx = %-3d | G = %-3d\n", row, col, row + col*frameHeight + 1*frameWidth*frameHeight, src[row + col*frameHeight + 1*frameWidth*frameHeight]);
mexPrintf("row = %-3d | col = %-3d | idx = %-3d | B = %-3d\n", row, col, row + col*frameHeight + 2*frameWidth*frameHeight, src[row + col*frameHeight + 2*frameWidth*frameHeight]);
mexPrintf("row = %-3d | col = %-3d | idx = %-3d | R = %-3d\n", row, col+1, row + (col+1)*frameHeight + 0*frameWidth*frameHeight, src[row + (col+1)*frameHeight + 0*frameWidth*frameHeight]);
mexPrintf("row = %-3d | col = %-3d | idx = %-3d | G = %-3d\n", row, col+1, row + (col+1)*frameHeight + 1*frameWidth*frameHeight, src[row + (col+1)*frameHeight + 1*frameWidth*frameHeight]);
mexPrintf("row = %-3d | col = %-3d | idx = %-3d | B = %-3d\n", row, col+1, row + (col+1)*frameHeight + 2*frameWidth*frameHeight, src[row + (col+1)*frameHeight + 2*frameWidth*frameHeight]);
#endif
/* MATLAB RGB -> YUV */
myYUV[0] = rgb_to_yuv( src[row + col*frameHeight + 0*frameWidth*frameHeight], \
src[row + col*frameHeight + 1*frameWidth*frameHeight], \
src[row + col*frameHeight + 2*frameWidth*frameHeight] );
myYUV[1] = rgb_to_yuv( src[row + (col+1)*frameHeight + 0*frameWidth*frameHeight], \
src[row + (col+1)*frameHeight + 1*frameWidth*frameHeight], \
src[row + (col+1)*frameHeight + 2*frameWidth*frameHeight] );
/* 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);
}
//----------------------------------------------------------
/* mySetupVision ============================================================= */
static void mySetupVision(unsigned int Wx, unsigned int Wy) {
/* ensure that we only allocate memory if it hasn't been done yet... */
if(yuyvBuf == NULL) {
/* dynamically allocate memory for conversion buffers (CMVISION) */
yuyvBuf = new image_pixel[Wx/2*Wy];
//mexPrintf("yuyvBuf = %08x\n", yuyvBuf);
img = new rgb[Wx*Wy];
//mexPrintf("img = %08x\n", img);
// initialize class 'vision' (CMVision)
if(!vision.initialize(Wx, Wy))
mexErrMsgTxt("Vision init failed.\n");
vision.loadOptions(colourFilename);
vision.enable(CMV_DENSITY_MERGE);
} else {
/* CAMERA_STOP request has been issued */
// destroy class 'vision'
vision.close();
/* destroy dynamically allocated buffer for 'yuyv' data */
if(yuyvBuf != NULL) {
delete yuyvBuf;
yuyvBuf = NULL;
//mexPrintf("yuyv buffer destroyed.\n");
}
/* destroy dynamically allocated buffer for 'img' data (output) */
if(img != NULL) {
delete img;
img = NULL;
//mexPrintf("img buffer destroyed.\n");
}
}
} /* mySetupVision ============================================================ */
/* mexFunction ============================================================= */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
mxArray *pArray; /* output data */
unsigned char *MATbuf; /* pointer to MATLAB memory */
int i, j;
// ######### CMVision ##########
int numCOL, maxCOL; // number of detected colours
int numREG;
int COLIDs[CMV_MAX_COLORS]; // list of colour IDs to be scanned for
int COLdetected[CMV_MAX_COLORS]; // list of detected colour IDs
// return detected coordinates in a structure
mxArray *fout;
double *pfout;
int fi; // field index
// input image: rgb
const int *inDims; // dimensions of the input image (rgb)
/************************************************************************/
/* Check for proper number of input and output arguments */
/************************************************************************/
if (!(nlhs==1 && (nrhs==1 || nrhs==2 || nrhs==3))) {
mexErrMsgTxt("Usage: Region_StructureArray = imgProc(RGBimage [, 'colour_filename'][, colour_list])\n " \
" default colour file: testcolors.txt\n" );
}
else {
// defaults
strcpy(colourFilename, defColourFilename);
maxCOL = defCOL; // default: just one colour
COLIDs[0] = 0; // default colour '0'
/* get 'RGBimage' parameter (always required) */
MATbuf = (unsigned char*)mxGetData(prhs[0]);
/* optional RHS: colour file name */
if(nrhs >= 2) {
mxGetString(prhs[1], colourFilename, colourFilenameLength);
//mexPrintf("colour file: %s\n", colourFilename);
}
/* optional RHS: list of colours to be scanned for */
if(nrhs >= 3) {
/* get list of colours */
if(!mxIsEmpty(prhs[2])) {
if(!mxIsNumeric(prhs[2]) && !mxIsComplex(prhs[2]))
mexErrMsgTxt("The specified colour list has to be a vector with up to 16 colour IDs\n");
maxCOL = (unsigned int)mxGetNumberOfElements(prhs[2]);
if(maxCOL > CMV_MAX_COLORS) {
mexWarnMsgTxt("Too many colours specified. Reducing to maximum permitted (32)\n");
maxCOL = CMV_MAX_COLORS;
}
// read colour vector
pfout = mxGetPr(prhs[2]);
for(fi=0; fi<maxCOL; fi++) {
COLIDs[fi] = (unsigned int)(*(pfout+fi))-1;
if((COLIDs[fi] < 0) || (COLIDs[fi] >= CMV_MAX_COLORS))
mexErrMsgTxt("Colour(s) outside the valid range (1 ... 32).\n");
}
}
}
}
/* determine image size */
inDims = mxGetDimensions(prhs[0]);
frameHeight = (unsigned long)inDims[0]; // rows
frameWidth = (unsigned long)inDims[1]; // columns
/* ensure minimum width and height (to avoid crashes) */
if(frameWidth < 2 || frameHeight < 1) {
// input image size is too small
mexErrMsgTxt("Size of provided RGB image is too small (minimum: 2 x 1 pixels).\n");
}
/* vision algorithms are yuyv based -- won't work if 'frameWidth' is an odd number
(need 2 RGB pixels to form one yuyv pixel) -> adjust width, if required */
if((frameWidth%2) == 1) {
mexPrintf("Reducing width by one pixel to make frameWidth become an even number\n");
frameWidth--;
}
//mexPrintf("frameWidth = %d\n", frameWidth);
//mexPrintf("frameHeight = %d\n", frameHeight);
/* allocate necessary memory... */
mySetupVision(frameWidth, frameHeight);
// convert RGB image to YUYV equivalent
convRGB_2_YUYV(yuyvBuf, MATbuf);
//mexPrintf("RGB image converted to yuyv.\n");
// process image data
//mexPrintf("before process.\n");
vision.processFrame(yuyvBuf);
//mexPrintf("after process.\n");
{
unsigned int row, col;
//mexPrintf("Before 'create FGretIMG'...\n");
/* create numeric array FGretIMG (used to display the image) */
dims[0] = frameHeight;
dims[1] = frameWidth;
dims[2] = 3;
/* create a MATLAB array with 'iWidth' columns, 'iHeight' rows, 'real numbers' */
FGretIMG = mxCreateNumericArray(NDIMS, (int const *)&dims[0], mxUINT8_CLASS, mxREAL);
//mexPrintf("After 'create FGretIMG'.\n");
/* ensure that MATLAB doesn't free data associated with FGretIMG (between subsequent calls to mdl-functions) */
//mexMakeArrayPersistent(FGretIMG); /* IMPORTANT!! (for Simulink only, FW-03-03) */
/* get pointer to data area, can reuse pointer variable MATbuf here (input data has already been copied to yuyv buffer...) */
MATbuf = (unsigned char *)mxGetData(FGretIMG);
// convert raw yuv422 image to RGB
convYUYV_2_RGB(img, (yuv422 *)yuyvBuf);
//mexPrintf("image converted to RGB\n");
// copy RGB to the MATLAB buffer...
for(row=0; row<frameHeight; row++) {
for(col=0; col<frameWidth; col++) {
MATbuf[row+col*frameHeight+0*frameWidth*frameHeight] = img[row*frameWidth+col].red;
MATbuf[row+col*frameHeight+1*frameWidth*frameHeight] = img[row*frameWidth+col].green;
MATbuf[row+col*frameHeight+2*frameWidth*frameHeight] = img[row*frameWidth+col].blue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -