Ejemplo n.º 1
0
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
  int *ns, ms[3], nCh, nDims, pt, pb, pl, pr, flag, k; double *p;
  void *A, *B; mxClassID id; double val=0; char type[1024];

  // Error checking on arguments
  if( nrhs!=3 ) mexErrMsgTxt("Three inputs expected.");
  if( nlhs>1 ) mexErrMsgTxt("One output expected.");
  nDims=mxGetNumberOfDimensions(prhs[0]); id=mxGetClassID(prhs[0]);
  ns = (int*) mxGetDimensions(prhs[0]); nCh=(nDims==2) ? 1 : ns[2];
  if( (nDims!=2 && nDims!=3) ||
    (id!=mxSINGLE_CLASS && id!=mxDOUBLE_CLASS && id!=mxUINT8_CLASS) )
    mexErrMsgTxt("A should be 2D or 3D single, double or uint8 array.");
  if( !mxIsDouble(prhs[1]) ) mexErrMsgTxt("Input pad must be a double array.");

  // extract padding amounts
  k = (int) mxGetNumberOfElements(prhs[1]);
  p = (double*) mxGetData(prhs[1]);
  if(k==1) { pt=pb=pl=pr=int(p[0]); }
  else if (k==2) { pt=pb=int(p[0]); pl=pr=int(p[1]); }
  else if (k==4) { pt=int(p[0]); pb=int(p[1]); pl=int(p[2]); pr=int(p[3]); }
  else mexErrMsgTxt( "Input pad must have 1, 2, or 4 values.");

  // figure out padding type (flag and val)
  if( !mxGetString(prhs[2],type,1024) ) {
    if(!strcmp(type,"replicate")) flag=1;
    else if(!strcmp(type,"symmetric")) flag=2;
    else if(!strcmp(type,"circular")) flag=3;
    else mexErrMsgTxt("Invalid pad value.");
  } else {
    flag=0; val=(double)mxGetScalar(prhs[2]);
  }
  if( ns[0]==0 || ns[1]==0 ) flag=0;

  // create output array
  ms[0]=ns[0]+pt+pb; ms[1]=ns[1]+pl+pr; ms[2]=nCh;
  if( ms[0]<0 || ns[0]<=-pt || ns[0]<=-pb ) ms[0]=0;
  if( ms[1]<0 || ns[1]<=-pl || ns[1]<=-pr ) ms[1]=0;
  plhs[0] = mxCreateNumericArray(3, (const mwSize*) ms, id, mxREAL);
  if( ms[0]==0 || ms[1]==0 ) return;

  // pad array
  A=mxGetData(prhs[0]); B=mxGetData(plhs[0]);
  if( id==mxDOUBLE_CLASS ) {
    imPad( (double*)A,(double*)B,ns[0],ns[1],nCh,pt,pb,pl,pr,flag,val );
  } else if( id==mxSINGLE_CLASS ) {
    imPad( (float*)A,(float*)B,ns[0],ns[1],nCh,pt,pb,pl,pr,flag,float(val) );
  } else if( id==mxUINT8_CLASS ) {
    imPad( (uchar*)A,(uchar*)B,ns[0],ns[1],nCh,pt,pb,pl,pr,flag,uchar(val) );
  } else {
    mexErrMsgTxt("Unsupported image type.");
  }
}
Ejemplo n.º 2
0
void imPad(CellArray& input, CellArray& output, std::vector<int> &pad, const std::string &type, double val) {
  int ns[3] = {input.rows, input.cols, input.channels}, ms[3];

  // extract padding amounts
  int pt, pb, pl, pr;
  if (pad.size() == 1) pt = pb = pl = pr = pad[0];
  else if (pad.size() == 2) pt = pb = pad[0], pl = pr = pad[1];
  else if (pad.size() == 4) pt = pad[0], pb = pad[1], pl = pad[2], pr = pad[3];
  else wrError("Input pad must have 1, 2, or 4 values.");

  // figure out padding type (flag and val)
  int flag = 0;
  if (type == "") flag = 0;
  else if (type == "replicate") flag = 1;
  else if (type == "symmetric") flag = 2;
  else if (type == "circular") flag = 3;
  else wrError("Invalid pad value");
  if (ns[0] == 0 || ns[1] == 0) flag = 0;

  // create output array
  ms[0] = ns[0] + pt + pb; ms[1] = ns[1] + pl + pr; ms[2] = ns[2];
  if (ms[0] < 0 || ns[0] <= -pt || ns[0] <= -pb ) ms[0] = 0;
  if (ms[1] < 0 || ns[1] <= -pl || ns[1] <= -pr ) ms[1] = 0;
  output.create(ms[0], ms[1], ms[2]);

  // pad array
  float *A = input.data, *B = output.data;
  imPad(A, B, ns[0], ns[1], ns[2], pt, pb, pl, pr, flag, float(val));
}
Ejemplo n.º 3
0
pyrOutput* chnsPyramid(float *image, pyrInput *input){
/*
 * Declaring variables
 */
    float *I;
    int height = input->sz[0],
	    width = input->sz[1],
	    heightO = input->sz[0],
	    widthO = input->sz[1],
	    channels = input->sz[2];

    int heightOriginal = height, widthOriginal = width;
    int misalign = 1;
    int sOfF = sizeof(float);

/*
 * Get default parameters pPyramid
 */
    if ( !input->complete ){
	if(input->nApprox<0)
	    input->nApprox = input->nPerOct - 1;

	input->pchns->pGradHist->binSize = input->shrink;
	input->pad[0] = round(input->pad[0]/input->shrink) * input->shrink;
	input->pad[1] = round(input->pad[1]/input->shrink) * input->shrink;
	input->minDs[0] = max(input->minDs[0], input->shrink * 4);
	input->minDs[1] = max(input->minDs[1], input->shrink * 4);

	input->complete = true;
    }

/*
 * Convert I to appropriate color space (or simply normalize)
 */
    int cs = input->pchns->pColor->colorSpace;
    I = rgbConvert(image, height*width, channels, cs, 1.0f);
    input->pchns->pColor->colorSpace = orig;

/*
 * Get scales at which to compute features and list of real/approx scales
 */
    float *scales = 0;
    float *scaleshw = 0;
    int nScales = getScales(scales, scaleshw, input->nPerOct, input->nOctUp,
		  input->minDs, input->shrink, input->sz);
    
    //TODO :: WARNING :: This was done in the Dollar's Code
    int isRMax;
    if(true)
	isRMax = 0;
    else
	isRMax = 0 + input->nOctUp * input->nPerOct;
    //TODO :: WARNING :: END
    
    int *isR, *isA, *isN;

    //isR Vector Allocation
    int countIsR = 0;
    for ( int i = isRMax; i < nScales; i += (input->nApprox + 1) )
	countIsR++;
    
    isR = new int[countIsR];

    for ( int i = isRMax, j = 0; i < nScales; j++, i += (input->nApprox + 1) )
	isR[j] = i;

    //isA and isN Vector Allocation
    int countIsA = nScales - countIsR;
    int countIsN = nScales;
    isA = new int[countIsA];
    isN = new int[countIsN];

    for ( int i = 0, auxI = 0; i < nScales; i++){
	bool ok = true;
	for (int j = 0; j < countIsR; j++)
	    if(i == isR[j]){
		ok = false;
		break;
	    }

	if (ok){
	    isA[auxI] = i;
	    auxI++;
	}

	isN[i] = i;
    }

    int *auxIsJ;
    auxIsJ = new int[countIsR + 1];

    auxIsJ[0] = 0;
    auxIsJ[countIsR] = nScales;

    for (int i = 0; i < countIsR - 1; i++)
	auxIsJ[i+1] = floor((isR[i] + 1 + isR[i+1] + 1) / 2); 
    // " +1 " because we are in c++ and the vector already assumes the first
    // element to be index 0.

    for (int i = 0; i < countIsR; i++){
	int minJ = auxIsJ[i];
	int maxJ = auxIsJ[i+1];

	for (int j = minJ; j < maxJ; j++)
	    isN[j] = isR[i];
    }

/*
 * Compute image pyramid [real scales]
 */
    int nTypes = 0;
    imgWrap ***data =  (imgWrap ***) wrCalloc(nScales, sizeof(imgWrap**));

    int shrink = input->shrink;
    float shr[3] = { 0, 0, 0};
    for (int it = 0, i = isR[0]; it < countIsR; it++, i=isR[it]){
	float scale = scales[i];
	int newHeight = round((float) heightO * (float) scale /
			(float) shrink) * shrink;

	int newWidth = round((float) widthO * (float) scale /
			(float) shrink) * shrink;
	
	float *I1;
	if ( height == newHeight && width == newWidth){
	    //TODO :: WARNING :: Should I copy it over?
	    I1 = (float*) wrCalloc(height*width*channels + misalign,
		  sOfF) + misalign;

	    int lengthArray = height*width*channels;
	    for (int j = 0; j < lengthArray; j++)
		    I1[j] = I[j];
	}else{
	    I1 = (float*) wrCalloc(newHeight*newWidth*channels + misalign,
		  sOfF) + misalign;

	    //TODO :: WARNING :: Hardcoded value :: 1.f
	    resample(I, I1, height, newHeight, width, newWidth, channels, 1.f);
	}

	if (scale == 0.5f && (input->nApprox > 0 || input->nPerOct == 1)){
	    //TODO :: WARNING :: Should I free "I"?
	    // I replace old I with new I1, as I reduced the image to half size
	    free(I);

	    I = I1;
	    height = newHeight;
	    width = newWidth;
	}

	//TODO :: WARNING :: Hardcoded value :: downsample
	float *I2 = 0;
	int downsample = 1;
	convTriAux(I1, I2, misalign, newHeight, newWidth, channels,
		input->smoothIm, downsample
		);

	/*
	 * Channels Compute for this isR[i] scale
	 */
	infoOut *chns = chnsCompute(I2, newHeight, newWidth, channels,
			input->pchns
			);

	imgWrap **data1 = chns->data;
	wrFree(I2-misalign);
	nTypes = chns->nTypes;

	if (i == isR[0]){
	    /*
	     * This is checking the size of each transformation. By design only
	     * the H channel will have the correct dimensions.
	     */
	    for (int j = 0; j < nTypes; j++){
		shr[j] = data1[j]->height;
		shr[j] = newHeight / shr[j];

		if (shr[j] > shrink || (int)shr[j] % 1 > 0){
		    cout << "Something went wrong with the shrinking."
			<< endl << "Source code line: " << __FILE__ << " @ "
			<< __LINE__ << endl;
		    return NULL; //This should never happen
		}

		shr[j]=shr[j]/shrink;
	    }
	}

	for(int j = 0; j < nTypes; j++){
	    if (shr[j] == 1)
		continue;

	    int nH = newHeight*shr[j],
		nW = newWidth*shr[j],
		chnsTransform = data1[j]->channels;

	    float *chnTypeData = (float*) wrCalloc(nH*nW*channels + misalign,
				sOfF) + misalign;

	    //TODO :: WARNING :: Hardcoded value :: 1.f
	    resample(data1[j]->image, chnTypeData, newHeight, nH, newWidth, nW,
		    chnsTransform, 1.f
		    );

	    data1[j]->height = nH;
	    data1[j]->width = nW;

	    wrFree(data1[j]->image - misalign);
	    data1[j]->image = chnTypeData;
	}

	data[i] = data1;
    }

    // In case I changed it when scale = 0.5f
    height = heightO;
    width = widthO;

/*
 * If lambdas not specified compute image specific lambdas
 */
    int nApprox = input->nApprox;
    float *lambdas = input->lambdas;
    if ( nApprox > 0 && !lambdas){
	int nOctUp = input->nOctUp;
	int nPerOct = input->nPerOct;

	//TODO :: WARNING :: Yet again I start at 0.
	// The is Vector :: is=1 + nOctUp*nPerOct:nApprox+1:nScales;
	int countIs = 0;

	int *isTemp = new int[nScales];
	for (int i = nOctUp*nPerOct; i < nScales; i += nApprox + 1){
	    isTemp[countIs] = i;
	    countIs++;
	}

	if (countIs > 2){
	    isTemp[0] = isTemp[1];
	    isTemp[1] = isTemp[2];
	}else{
	    cout << "Couldn't calculate lambdas. Not enough scales to use."
		<< endl << "Source code line: " << __FILE__ << " @ "
		<< __LINE__ << endl;
	    return NULL;
	}


	float *f0 = new float[nTypes];
	float *f1 = new float[nTypes];

	imgWrap **d0 = data[isTemp[0]];
	imgWrap **d1 = data[isTemp[1]];

	for (int i = 0; i < nTypes; i++){
	    float numElem = (float)
			    (d0[i]->width * d0[i]->height * d0[i]->channels);

	    float sumElem = 0.f;

	    for (int j = 0; j < numElem; j++)
		sumElem += d0[i]->image[j];

	    f0[i] = sumElem / numElem;
	}

	for (int i = 0; i < nTypes; i++){
	    float numElem = (float)
			    (d1[i]->width * d1[i]->height * d1[i]->channels);

	    float sumElem = 0.f;

	    for (int j = 0; j < numElem; j++)
		sumElem += d1[i]->image[j];

	    f1[i] = sumElem / numElem;
	}


	lambdas = new float[nTypes];
	float lambdaValue = log2(scales[isTemp[0]] / scales[isTemp[1]]);
	for (int i = 0; i < nTypes; i++)
	    lambdas[i] = -log2(f0[i] / f1[i]) / lambdaValue;
    }

/*
 * Compute image pyramid [approximated scales]
 */
    shrink = input->shrink;
    for (int it = 0, i = isA[0]; it < countIsA; it++, i=isA[it]){
	int iR = isN[i];

	float scale = scales[i];

	//TODO :: WARNING :: The value height may have been modified to half of
	//                   it, hence using heightOriginal (width)
	int newHeight = round((float) heightOriginal * (float) scale /
			(float) shrink);
	int newWidth = round((float) widthOriginal * (float) scale /
			(float) shrink);

	float scaleRatio = (scale / scales[iR]);
	float *rs = new float[nTypes];

	for (int j = 0; j < nTypes; j++)
	    rs[j] = pow(scaleRatio, -lambdas[j] );

	imgWrap **dataImgA = (imgWrap **) wrCalloc(nTypes, sizeof(imgWrap*));
	imgWrap **dataImgR = data[iR];

	for (int j = 0; j < nTypes; j++){
	    int ijChannels = dataImgR[j]->channels;

	    float *isAimage = (float*) wrCalloc(newHeight*newWidth*ijChannels +
			    misalign, sOfF) + misalign;

	    //TODO :: WARNING :: Hardcoded value
	    resample(dataImgR[j]->image, isAimage, dataImgR[j]->height,
		    newHeight, dataImgR[j]->width, newWidth, ijChannels, rs[j]);

	    dataImgA[j] = new imgWrap(isAimage, newWidth, newHeight,ijChannels);
	}

	data[i] = dataImgA;
	delete [] rs;
    }

/*
 * Smooth channels, optionally pad and concatenate channels
 */
    int downSample = 1; // WARNING : This is the default by dollar
    int s = downSample;

    for (int i = 0; i < nScales; i++){
	for (int j = 0; j < nTypes; j++){
	    float *S;
	    int height = data[i][j]->height;
	    int width = data[i][j]->width;
	    int channel = data[i][j]->channels;

	    /*
	      * Smoothing Channels
	      */
	    convTriAux(data[i][j]->image, S, misalign, height, width, channel,
			input->smoothChns, s
			);

	    wrFree(data[i][j]->image - misalign);

	    /*
	     * Padding according to the scale. Then change the shrink value.
	     */
	    int padTB = input->pad[0] / shrink,
		padLR = input->pad[1] / shrink;

	    if (padTB > 0 || padLR > 0){
		int newHeight = height + padTB * 2;
		int newWidth = width + padLR * 2;

		float *P = (float*) wrCalloc(newHeight*newWidth*channel +
			    misalign, sOfF) + misalign;

		imPad(S, P, height, width, channel, padTB, padTB, padLR, padLR,
		      padvalue, 0.f
		      );

		wrFree(S - misalign);

		data[i][j]->height = newHeight;
		data[i][j]->width = newWidth;

		S = P;
	    }

	    data[i][j]->image = S;
	}
    }

/*
 * Concatenate.
 */
    int totalChannels = 0;
    for (int j = 0; j < nTypes; j++)
	totalChannels += data[0][j]->channels;

    if(input->concat){
	int chnsArr[nTypes];

	for (int j = 0; j < nTypes; j++)
	    chnsArr[j] = data[0][j]->channels;

	for (int i = 0; i < nScales; i++){
	    int height = data[i][0]->height;
	    int width = data[i][0]->width;

	    float *imgC = (float*) wrCalloc(height*width*totalChannels +
			  misalign, sOfF) + misalign;

	    int totalSize = 0;
	    for (int j = 0; j < nTypes; j++){
		float *imgO = data[i][j]->image;

		copy(imgO, imgO + height*width*chnsArr[j], imgC + totalSize);
		totalSize += height*width*chnsArr[j];
	    }

	    for (int j=1; j < nTypes; j++){
		wrFree(data[i][j]->image - misalign);
		wrFree(data[i][j]);
	    }

	    wrFree(data[i][0]->image - misalign);
	    data[i][0]->image = imgC;
	    data[i][0]->channels = totalChannels;
	}
    }


/*
 * Create output struct
 */
    pyrOutput *output = new pyrOutput();
    output->input = input;
    output->chnsPerScale = data;
    output->nScales =  nScales;
    output->scales = scales;
    output->nChannels = totalChannels;

/*
 * Clean Memory
 */
    delete [] isR;
    delete [] isA;
    delete [] isN;
    delete [] lambdas;
    delete [] scaleshw;

/*
 * Output
 */
    return output;
}
Ejemplo n.º 4
0
CellArray imPad(CellArray& input, std::vector<int> &pad, const std::string &type, double val) {
  CellArray output;
  imPad(input, output, pad, type, val);
  return output;
}