ColorChannel::ColorChannel(const cv::Mat& Image) { // cv::imshow("To Convert", Image); // cv::waitKey(0); // Should check on width and height compatible with shrinking ... //Convert from bgr to rgb cv::Mat I_rgbO = Image.clone(); cv::Mat I_rgb; cv::cvtColor(I_rgbO, I_rgb, CV_BGR2RGB); //Convert to float-image cv::Mat doubleImage; I_rgb.convertTo(doubleImage, CV_32FC3, 1 / 255.0); float* MImage = Convert_ToMatlab(doubleImage, 1.0f); //r is radius int r = 1; float RR = 12.0 / (r * (r + 2)) - 2; float* rgbImage = rgbConvert(MImage, Image.rows * Image.cols, Image.channels(), 2, 1.0f); this->setColorSpace("luv"); float* rgbImage_smooth = (float*)malloc(sizeof(float) * Image.cols * Image.rows * I_rgb.channels()); // Last argument was 1 for Inria-model, is 0 for CalltechModel convTri1(rgbImage, rgbImage_smooth, Image.rows, Image.cols, Image.channels(), RR, 1); free(MImage); free(rgbImage); setChanneldata(rgbImage_smooth, Image.cols, Image.rows, Image.channels()); }
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; }