void ShapeModel::viewShapeModelUpdate(ModelViewInfo *pInfo) { Mat_< double > paramV; paramV.create(this->nShapeParams, 1); for (int i=0;i<nShapeParams;i++){ paramV(i, 0) = (pInfo->vList[i]/30.0 - 0.5)*6* sqrt(pcaShape->eigenvalues.at<double>(i, 0)); } Mat_<cv::Vec3b> img; ModelImage s; s.setShapeInfo(&shapeInfo); s.loadTrainImage(Mat_<unsigned char>::ones(190*2, 160*2)*255); projectParamToShape(paramV, s.shapeVec); SimilarityTrans st = s.shapeVec.getShapeTransformFitingSize( Size(320, 380)); s.buildFromShapeVec(st, 1000); img = s.show(0, -1, false); imshow("Viewing Shape Model", img); }
void ASMModel::doSearch(const cv::Mat& img, FitResult& fitResult, int verbose) { // Step 2: Ensure it is a grayscale image Mat grayImg; if (img.channels() == 3){ cv::cvtColor(img, grayImg, CV_BGR2GRAY); } else grayImg = img; // Step 3: Resize each face image Mat resizedImg; // Resize the image to proper size double ratio; ratio = sqrt( double(40000) / (grayImg.rows * grayImg.cols)); cv::resize(grayImg, resizedImg, cv::Size(grayImg.cols*ratio, grayImg.rows*ratio)); puts("Start fitting..."); ModelImage curSearch; curSearch.setShapeInfo( &shapeInfo ); curSearch.loadTrainImage(resizedImg); fitResult.params = Mat_<double>::zeros(nShapeParams, 1); ShapeVec &sv = curSearch.shapeVec; ShapeVec shape_old; projectParamToShape(fitResult.params, sv); SimilarityTrans st = sv.getShapeTransformFitingSize(resizedImg.size(), searchScaleRatio, searchInitXOffset, searchInitYOffset); fitResult.transformation = st; curSearch.buildFromShapeVec(st); pyramidLevel = 2; int k=localFeatureRad; ns=4; // sum of offsets of current iteration. int totalOffset; if (verbose >= ASM_FIT_VERBOSE_AT_LEVEL) curSearch.show(); // Update each point vector< Point_< int > > V; for (int l=this->pyramidLevel; l>=0; l--){ if (verbose >= ASM_FIT_VERBOSE_AT_LEVEL) printf("Level %d\n", l); Mat_<double> img=curSearch.getDerivImage(l); // printf("Image size: %dx%d\n", img.cols, img.rows); // at most 5 iterations for each level int runT; double avgMov; // [zl] this number has funky effects and also asjust speed a bit. for (runT=0; runT<3; runT++){ // Backup current shape shape_old.fromPointList(curSearch.points); totalOffset = 0; vector< Point_< int > > bestEP(nMarkPoints); for (int i=0; i<this->nMarkPoints; i++){ if (verbose >= ASM_FIT_VERBOSE_AT_POINT) printf("Dealing point %d...\n", i); Mat_< double > nrmV(2*k+1, 1); double curBest=-1, ct; int bestI = 0; double absSum; for (int e=ns; e>=-ns; e--){ curSearch.getPointsOnNorm(i, k, l, V, 2*searchStepAreaRatio, e); absSum = 0; for (int j=-k;j<=k;j++){ nrmV(j+k, 0) = img(V[j+k]); absSum += fabs(nrmV(j+k, 0)); } nrmV *= 1/absSum; ct = cv::Mahalanobis(nrmV, this->meanG[l][i], this->iCovarG[l][i]); // printf("absSum: %lf, ct: %lf\n", absSum, ct); if (verbose >= ASM_FIT_VERBOSE_AT_POINT) curSearch.show(l, i, true, e); if (ct<curBest || curBest<0){ curBest = ct; bestI = e; bestEP[i] = V[k]; } } // printf("best e: %d\n", bestI); // bestEP[i] = V[bestI+(ns+k)]; totalOffset += abs(bestI); if (verbose >= ASM_FIT_VERBOSE_AT_POINT) curSearch.show(l, i, true, bestI); } for (int i=0;i<nMarkPoints;i++){ curSearch.points[i] = bestEP[i]; curSearch.points[i].x <<= l; if (l>0) curSearch.points[i].x += (1<<(l-1)); curSearch.points[i].y <<= l; if (l>0) curSearch.points[i].y += (1<<(l-1)); } curSearch.shapeVec.fromPointList(curSearch.points); if (verbose >= ASM_FIT_VERBOSE_AT_ITERATION) curSearch.show(l); // Project to PCA model and then back //findParamForShape(curSearch.shapeVec, fitResult); findParamForShapeBTSM(curSearch.shapeVec, shape_old, fitResult, fitResult, l); pcaPyr[l].backProject(fitResult.params, sv); // Reconstruct new shape curSearch.buildFromShapeVec(fitResult.transformation); avgMov = (double)totalOffset/nMarkPoints; if (verbose >= ASM_FIT_VERBOSE_AT_ITERATION){ printf("Iter %d: Average offset: %.3f\n", runT+1, avgMov); curSearch.show(l); } if (avgMov < 1.3){ runT++; break; } } if (verbose == ASM_FIT_VERBOSE_AT_LEVEL){ printf("%d iterations. average offset for last iter: %.3f\n", runT, avgMov); curSearch.show(l); } } SimilarityTrans s2; s2.a = 1/ratio; fitResult.transformation = s2 * fitResult.transformation; }