// Fit model to this random selection of data points. void vpHomography::computeTransformation(vpColVector &x, unsigned int *ind, vpColVector &M) { unsigned int i ; unsigned int n = x.getRows()/4 ; std::vector<double> xa(4), xb(4); std::vector<double> ya(4), yb(4); unsigned int n2 = n * 2; unsigned int ind2; for(i=0 ; i < 4 ; i++) { ind2 = 2 * ind[i]; xb[i] = x[ind2] ; yb[i] = x[ind2+1] ; xa[i] = x[n2+ind2] ; ya[i] = x[n2+ind2+1] ; } vpHomography aHb ; try { vpHomography::HLM(xb, yb, xa, ya, true, aHb); } catch(...) { aHb.setIdentity(); } M.resize(9); for (i=0 ; i <9 ; i++) { M[i] = aHb.data[i] ; } aHb /= aHb[2][2] ; }
void OrganizedData::process(RawData* raw, int nBlock, double pTest, int nSupport) { int nData = raw->nData, nDim = raw->nDim - 1; this->nSupport = nSupport; this->nBlock = nBlock; this->nDim = nDim; train = field<mat>(nBlock,2); test = field<mat>(nBlock,2); support = field<mat>(1,2); mat xm(nSupport,nDim), ym(nSupport,1); vec mark(nData); mark.fill(0); printf("Randomly selecting %d supporting point ...\n", nSupport); for (int i = 0; i < nSupport; i++) { int pos = IRAND(0, nData - 1); while (mark[pos] > 0) pos = IRAND(0, nData - 1); mark[pos] = 1; for (int j = 0; j < nDim; j++) xm(i, j) = raw->X(pos,j); ym(i,0) = raw->X(pos,nDim); } support(0,0) = xm; xm.clear(); support(0,1) = ym; ym.clear(); cout << "Partitioning the remaining data into " << nBlock << " cluster using K-Mean ..." << endl; vvd _remain; for (int i = 0; i < nData; i++) if (!mark(i)) { rowvec R = raw->X.row(i); _remain.push_back(r2v(R)); } mat remaining = v2m(_remain); mark.clear(); RawData* remain = new RawData(remaining); KMean* partitioner = new KMean(remain); Partition* clusters = partitioner->cluster(nBlock); cout << "Packaging training/testing data points into their respective cluster" << endl; for (int i = 0; i < nBlock; i++) { cout << "Processing block " << i + 1 << endl; int bSize = (int) clusters->member[i].size(), tSize = (int) floor(bSize * pTest), pos = 0, counter = 0; mark = vec(bSize); mark.fill(0); if (bSize > tSize) // if we can afford to draw tSize test points from this block without depleting it ... { mat xt(tSize,nDim), yt(tSize,1); for (int j = 0; j < tSize; j++) { pos = IRAND(0, bSize - 1); while (mark[pos] > 0) pos = IRAND(0, bSize - 1); mark[pos] = 1; pos = clusters->member[i][pos]; for (int t = 0; t < nDim; t++) xt(j, t) = remain->X(pos,t); yt(j,0) = remain->X(pos,nDim); } bSize -= tSize; nTest += tSize; test(i,0) = xt; xt.clear(); test(i,1) = yt; yt.clear(); } nTrain += bSize; mat xb(bSize,nDim), yb(bSize,1); //cout << remain->X.n_rows << endl; for (int j = 0; j < (int)mark.n_elem; j++) if (mark[j] < 1) { for (int t = 0; t < nDim; t++) { xb(counter,t) = remain->X(clusters->member[i][j],t); } yb(counter++,0) = remain->X(clusters->member[i][j],nDim); } train(i,0) = xb; xb.clear(); train(i,1) = yb; yb.clear(); mark.clear(); printf("Done ! nData[%d] = %d, nTrain[%d] = %d, nTest[%d] = %d .\n", i, (int) clusters->member[i].size(), i, train(i,0).n_rows, i, (int) test(i,0).n_rows); } }
/** * With the critical edge selection, initial kernel erstimation can be accomplished quickly. * Objective function: E(k) = ||∇I^s ⊗ k - ∇B||² + γ||k||² * * @param selectionGrads array of x and y gradients of final selected edges (∇I^s) [-1, 1] * @param blurredGrads array of x and y gradients of blurred image (∇B) [-1, 1] * @param kernel energy preserving kernel (k) */ void fastKernelEstimation(const array<Mat,2>& selectionGrads, const array<Mat,2>& blurredGrads, Mat& kernel, const float weight = 1e-2) { assert(selectionGrads[0].rows == blurredGrads[0].rows && "matrixes have to be of same size!"); assert(selectionGrads[0].cols == blurredGrads[0].cols && "matrixes have to be of same size!"); // based on Perseval's theorem, perform FFT // __________ __________ // ( F(∂_x I^s) * F(∂_x B) + F(∂_y I^s) * F(∂_y B) ) // k = F^-1 * ( ---------------------------------------------- ) // ( F(∂_x I^s)² + F(∂_y I^s)² + γ ) // where * is pointwise multiplication // __________ // and F(∂_x I^s)² = F(∂_x I^s) * F(∂_x I^s) ! because they mean the norm // // here: F(∂_x I^s) = xS // F(∂_x B) = xB // F(∂_y I^s) = yS // F(∂_y B) = yB // compute FFTs // the result are stored as 2 channel matrices: Re(FFT(I)), Im(FFT(I)) Mat xS, xB, yS, yB; deblur::dft(selectionGrads[0], xS); deblur::dft(blurredGrads[0], xB); deblur::dft(selectionGrads[1], yS); deblur::dft(blurredGrads[1], yB); complex<float> we(weight, 0.0); // kernel in Fourier domain Mat K = Mat::zeros(xS.size(), xS.type()); // pixelwise computation of kernel for (int y = 0; y < K.rows; y++) { for (int x = 0; x < K.cols; x++) { // complex entries at the current position complex<float> xs(xS.at<Vec2f>(y, x)[0], xS.at<Vec2f>(y, x)[1]); complex<float> ys(yS.at<Vec2f>(y, x)[0], yS.at<Vec2f>(y, x)[1]); complex<float> xb(xB.at<Vec2f>(y, x)[0], xB.at<Vec2f>(y, x)[1]); complex<float> yb(yB.at<Vec2f>(y, x)[0], yB.at<Vec2f>(y, x)[1]); // kernel entry in the Fourier space complex<float> k = (conj(xs) * xb + conj(ys) * yb) / (conj(xs) * xs + conj(ys) * ys + we); // (abs(xs) * abs(xs) + abs(ys) * abs(ys) + we); // equivalent K.at<Vec2f>(y, x) = { real(k), imag(k) }; } } // only use the real part of the complex output Mat kernelBig; dft(K, kernelBig, DFT_INVERSE | DFT_REAL_OUTPUT); // FIXME: find kernel inside image (kind of bounding box) instead of force user to // approximate a correct kernel-width (otherwise some information are lost) // cut of kernel in middle of the temporary kernel int x = kernelBig.cols / 2 - kernel.cols / 2; int y = kernelBig.rows / 2 - kernel.rows / 2; swapQuadrants(kernelBig); Mat kernelROI = kernelBig(Rect(x, y, kernel.cols, kernel.rows)); // copy the ROI to the kernel to avoid that some OpenCV functions accidently // uses the information outside of the ROI (like copyMakeBorder()) kernelROI.copyTo(kernel); // threshold kernel to erease negative values threshold(kernel, kernel, 0.0, -1, THRESH_TOZERO); // // kernel has to be energy preserving // // this means: sum(kernel) = 1 kernel /= sum(kernel)[0]; }