sustaining_gazes/matlab_version/face_detection/face_detection_zhu/face-release1.0-basic/reduce.cc

88 lines
2.5 KiB
C++

#include <math.h>
#include <assert.h>
#include <string.h>
#include "mex.h"
#define round(x) ((x-floor(x))>0.5 ? ceil(x) : floor(x))
// reduce(im) resizes im to half its size, using a 5-tap binomial filter for anti-aliasing
// (see Burt & Adelson's Laplacian Pyramid paper)
// reduce each column
// result is transposed, so we can apply it twice for a complete reduction
void reduce1dtran(double *src, int sheight, double *dst, int dheight,
int width, int chan) {
// resize each column of each color channel
//bzero(dst, chan*width*dheight*sizeof(double));
memset(dst, 0, chan*width*dheight*sizeof(double));
int y;
double *s, *d;
for (int c = 0; c < chan; c++) {
for (int x = 0; x < width; x++) {
s = src + c*width*sheight + x*sheight;
d = dst + c*dheight*width + x;
// First row
*d = s[0]*.6875 + s[1]*.2500 + s[2]*.0625;
for (y = 1; y < dheight-2; y++) {
s += 2;
d += width;
*d = s[-2]*0.0625 + s[-1]*.25 + s[0]*.375 + s[1]*.25 + s[2]*.0625;
}
// Last two rows
s += 2;
d += width;
if (dheight*2 <= sheight) {
*d = s[-2]*0.0625 + s[-1]*.25 + s[0]*.375 + s[1]*.25 + s[2]*.0625;
} else {
*d = s[1]*.3125 + s[0]*.3750 + s[-1]*.2500 + s[-2]*.0625;
}
s += 2;
d += width;
*d = s[0]*.6875 + s[-1]*.2500 + s[-2]*.0625;
}
}
}
// main function
// takes a double color image and a scaling factor
// returns resized image
mxArray *reduce(const mxArray *mxsrc) {
double *src = (double *)mxGetPr(mxsrc);
const int *sdims = mxGetDimensions(mxsrc);
if (mxGetNumberOfDimensions(mxsrc) != 3 ||
mxGetClassID(mxsrc) != mxDOUBLE_CLASS)
mexErrMsgTxt("Invalid input");
int ddims[3];
ddims[0] = (int)round(sdims[0]*.5);
ddims[1] = (int)round(sdims[1]*.5);
ddims[2] = sdims[2];
mxArray *mxdst = mxCreateNumericArray(3, ddims, mxDOUBLE_CLASS, mxREAL);
double *dst = (double *)mxGetPr(mxdst);
double *tmp = (double *)mxCalloc(ddims[0]*sdims[1]*sdims[2], sizeof(double));
reduce1dtran(src, sdims[0], tmp, ddims[0], sdims[1], sdims[2]);
reduce1dtran(tmp, sdims[1], dst, ddims[1], ddims[0], sdims[2]);
mxFree(tmp);
return mxdst;
}
// matlab entry point
// dst = resize(src, scale)
// image should be color with double values
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
if (nrhs != 1)
mexErrMsgTxt("Wrong number of inputs");
if (nlhs != 1)
mexErrMsgTxt("Wrong number of outputs");
plhs[0] = reduce(prhs[0]);
}