intrinsics.cpp
Go to the documentation of this file.
00001 
00005 #include "intrinsics.hpp"
00006 
00007 double calculateERE( Size imSize,
00008                      cv::vector<Point3f>& physicalPoints,
00009                      cv::vector< cv::vector<Point2f> >& corners,
00010                      const Mat& cameraMatrix,
00011                      const Mat& distCoeffs,
00012                      bool removeSpatialBias, 
00013                      bool generateFigure, 
00014                      bool useUndistortedLocations)
00015 {
00016         
00017         bool debug = false;
00018         
00019         
00020         if (debug) { printf("%s << physicalPoints.size() = (%d)\n", __FUNCTION__, physicalPoints.size()); }
00021         if (debug) { printf("%s << corners.size() = (%d)\n", __FUNCTION__, corners.size()); }
00022         
00023     int total_points = corners.size() * corners.at(0).size();
00024     
00025     Mat newCamMat;
00026     Mat identity = Mat::eye(3,3,CV_64FC1);
00027     
00028     if (useUndistortedLocations) {
00029                 newCamMat = getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imSize, 0.0);
00030                 newCamMat = newCamMat.inv();
00031         }
00032         
00033     double *errValues;
00034     
00035     errValues = new double[total_points];
00036     
00037     Mat projectionCountGrid, cumulativeErrorGrid;
00038     
00039     if (debug) { printf("%s << REACHED (%d)\n", __FUNCTION__, 0); }
00040     
00041     if (1) { // (removeSpatialBias) {
00042                 // Create two grid matrices, one for counts and one for cumulative errors
00043                 
00044                 double ratio = double(imSize.width) / double(imSize.height);
00045                 
00046                 //printf("%s << image size = (%d, %d)\n", __FUNCTION__, imSize.height, imSize.width);
00047                 
00048                 int desiredBins = min(MAX_BINS, max(MIN_BINS,total_points));
00049                 
00050                 double numRows, numCols;
00051                 
00052                 numRows = pow(desiredBins / ratio , 0.5);
00053                 numCols = ratio * numRows;
00054                 
00055                 // Divide major axis into 16
00056                 
00057                 projectionCountGrid = Mat::zeros(int(ceil(numRows)), int(ceil(numCols)), CV_16UC1);
00058                 cumulativeErrorGrid = Mat::zeros(int(ceil(numRows)), int(ceil(numCols)), CV_32FC1);
00059                 
00060                 //printf("%s << grid size = (%d, %d) [%d]\n", __FUNCTION__, projectionCountGrid.rows, projectionCountGrid.cols, total_points);
00061                 
00062         }
00063 
00064     if (debug) { printf("%s << REACHED (%d)\n", __FUNCTION__, 1); }
00065     
00066 
00067 
00068     Mat fsRvec, fsTvec;
00069     cv::vector<Point2f> cornerSet;
00070     cornerSet.resize(physicalPoints.size());
00071 
00072     double err = 0.0, xSum = 0, ySum = 0, tSum = 0, xMean = 0, yMean = 0, tMean = 0, xDev = 0, yDev = 0, tDev = 0;
00073 
00074     Point2f imLoc, imageDec, predictedDec;
00075 
00076         //printf("%s << A\n",__FUNCTION__);
00077     
00078     for (unsigned int i = 0; i < corners.size(); i++) {
00079 
00080                 if (debug) { printf("%s << Set (%d) Solving PnP...\n", __FUNCTION__, i); }
00081                 
00082                 if (debug) { printf("%s << corners.at(%d).size() = (%d)\n", __FUNCTION__, i, corners.at(i).size()); }
00083                 
00084         // Estimate pose of board
00085         solvePnP(Mat(physicalPoints), Mat(corners.at(i)), cameraMatrix, distCoeffs, fsRvec, fsTvec, false);
00086 
00087                 //cout << "fsRvec = " << endl << fsRvec << endl;
00088                 //cout << "fsTvec = " << endl << fsTvec << endl;
00089 
00090                 if (debug) { printf("%s << Projecting points...\n", __FUNCTION__); }
00091 
00092         // Reproject the object points using estimated rvec/tvec
00093         projectPoints(Mat(physicalPoints), fsRvec, fsTvec, cameraMatrix, distCoeffs, cornerSet);
00094         // do we want distortion vector or not? (noDistVector) it would make undistorted comparison better..
00095 
00096         //image.copyTo(debugImage);
00097         
00098         if (debug) { printf("%s << About to start loop through points...\n",__FUNCTION__); }
00099         
00100         vector<Point2f> undistortedPoints;
00101         
00102         if (useUndistortedLocations) {
00103                         undistortPoints(corners.at(i), undistortedPoints, cameraMatrix, distCoeffs, identity, newCamMat);
00104                 }
00105 
00106         // Find the mean and standard deviations for differences between results (conventional)
00107         for (unsigned int j = 0; j < cornerSet.size(); j++) {
00108                         
00109                         if (debug) { printf("%s << Point loop (%d)\n", __FUNCTION__, j); }
00110 
00111             imageDec = Point2f(corners.at(i).at(j).x, corners.at(i).at(j).y);
00112             predictedDec = Point2f(cornerSet.at(j).x, cornerSet.at(j).y);
00113             
00114             double ptError = pow(pow(imageDec.x-predictedDec.x, 2)+pow(imageDec.y-predictedDec.y, 2), 0.5);
00115 
00116                         
00117 
00118                         //printf("%s << Error between (%f, %f) and (%f, %f) is (%f)\n", __FUNCTION__, imageDec.x, imageDec.y, predictedDec.x, predictedDec.y, ptError);
00119 
00120                         
00121 
00122                         //if (ptError > 10.0) {
00123                         //      cin.get();
00124                         //}
00125 
00126             if (errValues)
00127             {
00128                                 
00129                                 //printf("%s << Updating error (%d / %d) with (%f)\n", __FUNCTION__, i*cornerSet.size()+j, total_points, ptError);
00130                                 
00131                 errValues[i*cornerSet.size()+j] = ptError;
00132                 
00133                 //printf("%s << errValues[%d] = %f\n", __FUNCTION__, i*cornerSet.size()+j, errValues[i*cornerSet.size()+j]);
00134             }
00135             
00136             
00137             
00138             if (1) { // (removeSpatialBias) {
00139                                 
00140                                 if (debug) { printf("%s << Removing spatial bias...\n",__FUNCTION__); }
00141                                 
00142                                 Point2f testPoint;
00143                                 
00144                                 
00145                                 
00146                                 if (useUndistortedLocations) {
00147                                         testPoint = Point2f(undistortedPoints.at(j).x, undistortedPoints.at(j).y);
00148                                         
00149                                         //printf("%s << Point moved from (%f, %f) to (%f, %f)\n", __FUNCTION__, imageDec.x, imageDec.y, undistortedPoints.at(j).x, undistortedPoints.at(j).y);
00150                                         
00151                                 } else {
00152                                         testPoint = imageDec;
00153                                 }
00154                                 
00155                                 
00156                                 if ((testPoint.x > 0.0) && (testPoint.x < imSize.width) && (testPoint.y > 0.0) && (testPoint.y < imSize.height)) {
00157                                         
00158                                         //printf("%s << Test point (%f, %f) within bounds (%f, %f)\n",__FUNCTION__, testPoint.x, testPoint.y, imSize.width, imSize.height);
00159                                         
00160                                         // Determine the appropriate bin for the original image location
00161                                         
00162                                         int gridRow = round( ( testPoint.y / imSize.height ) * float(projectionCountGrid.rows) - 0.5 );
00163                                         int gridCol = round( ( testPoint.x / imSize.width ) * float(projectionCountGrid.cols) - 0.5 ); 
00164                                         
00165                                         //printf("%s << [x,y] point(%f, %f) binned to (%d, %d)\n", __FUNCTION__, imageDec.x, imageDec.y, gridCol, gridRow);
00166                                         
00167                                         projectionCountGrid.at<unsigned short>(gridRow, gridCol) += 1;
00168                                         cumulativeErrorGrid.at<float>(gridRow, gridCol) += ptError;
00169                                         
00170                                         //printf("%s << Updating grid (%d, %d) of (%d, %d)\n", __FUNCTION__, gridRow, gridCol, projectionCountGrid.rows, projectionCountGrid.cols);
00171                                         
00172                                         // Update the bins
00173                                         
00174                                 } else {
00175                                         //printf("%s << Test point (%f, %f) out of bounds (%f, %f)\n",__FUNCTION__, testPoint.x, testPoint.y, imSize.width, imSize.height);
00176                                 }
00177                                 
00178                         }
00179 
00180                         
00181                         if (debug) { printf("%s << A6\n",__FUNCTION__); }
00182 
00183             
00184         }
00185         
00186         
00187 
00188                 if (debug) { printf("%s << A8\n",__FUNCTION__); }
00189 
00190     }
00191     
00192     
00193     
00194     if (debug) { printf("%s << B\n",__FUNCTION__); }
00195     
00196     if (1) { // (removeSpatialBias) {
00197                 
00198                 //printf("%s << B1\n",__FUNCTION__);
00199                 
00200                 tSum = 0.0;
00201                 float maxAverageError = 0.0;
00202                 
00203                 Mat heatMap, heatMapCol;
00204                 
00205                 if (generateFigure) {
00206                         heatMap = Mat::ones(imSize, CV_8UC1);
00207                         heatMapCol = Mat::ones(imSize, CV_8UC3);
00208                 }
00209                 
00210                 //printf("%s << B2\n",__FUNCTION__);
00211                         
00212                 // Convert sums to averages, and determine maximum average error for occupied cells
00213                 for (unsigned int iii = 0; iii < projectionCountGrid.rows; iii++) {
00214                         for (unsigned int jjj = 0; jjj < projectionCountGrid.cols; jjj++) {
00215                                 
00216                                 if (projectionCountGrid.at<unsigned short>(iii, jjj) > 0) {
00217                                         cumulativeErrorGrid.at<float>(iii, jjj) /= float(projectionCountGrid.at<unsigned short>(iii, jjj));
00218                                         
00219                                         //printf("%s << cell (%d, %d) corrected error = (%f)\n", __FUNCTION__, iii, jjj, cumulativeErrorGrid.at<float>(iii, jjj));
00220                                         
00221                                         tSum += cumulativeErrorGrid.at<float>(iii, jjj);
00222                                         
00223                                         if (cumulativeErrorGrid.at<float>(iii, jjj) > maxAverageError) {
00224                                                 maxAverageError = cumulativeErrorGrid.at<float>(iii, jjj);
00225                                         }
00226                                         
00227                                 } else {
00228                                         
00229                                         // Mark as zero on heatmap if no points in here, to preserve emptiness
00230                                         
00231                                         if (generateFigure) {
00232                                                 unsigned int startRow = round((float(iii) / float(cumulativeErrorGrid.rows)) * float(heatMap.rows));
00233                                                 unsigned int endRow = ceil((float(iii+1) / float(cumulativeErrorGrid.rows)) * float(heatMap.rows));
00234                                                 unsigned int startCol = round((float(jjj) / float(cumulativeErrorGrid.cols)) * float(heatMap.cols));
00235                                                 unsigned int endCol = ceil((float(jjj+1) / float(cumulativeErrorGrid.cols)) * float(heatMap.cols));
00236                                         
00237                                                 for (unsigned int aaa = startRow; aaa < endRow; aaa++) {
00238                                                         for (unsigned int bbb = startCol; bbb < endCol; bbb++) {
00239                                                                 heatMap.at<unsigned char>(aaa,bbb) = 0;
00240                                                                 heatMapCol.at<Vec3b>(aaa,bbb)[0] = 0;
00241                                                                 heatMapCol.at<Vec3b>(aaa,bbb)[1] = 0;
00242                                                                 heatMapCol.at<Vec3b>(aaa,bbb)[2] = 255;
00243                                                         }
00244                                                 }
00245                                         }
00246                                         
00247                                         
00248                                 }
00249                                 
00250                                 
00251                         }
00252                 }
00253                 
00254                 //printf("%s << B3\n",__FUNCTION__);
00255                 
00256                 //printf("%s << max corrected error = (%f)\n", __FUNCTION__, maxAverageError);
00257                 
00258                 // Assign unoccupied cells the maximum error (to penalize for not having them occupied!)
00259                 for (unsigned int iii = 0; iii < projectionCountGrid.rows; iii++) {
00260                         for (unsigned int jjj = 0; jjj < projectionCountGrid.cols; jjj++) {
00261                                 
00262                                 if (projectionCountGrid.at<unsigned short>(iii, jjj) == 0) {
00263                                         cumulativeErrorGrid.at<float>(iii, jjj) = maxAverageError;
00264                                         tSum += maxAverageError;
00265                                 }
00266                                 
00267                         }
00268                 }
00269                 
00270                 //printf("%s << B4\n",__FUNCTION__);
00271                 
00272                 err = tSum / (projectionCountGrid.rows*projectionCountGrid.cols);
00273                 
00274                 //printf("%s << err with de-biasing: (%f)\n", __FUNCTION__, err);
00275                 
00276                 if (generateFigure) {
00277                         
00278                         double lim = (1.0/5.0)*ceil(maxAverageError*5.0);
00279                         
00280                         lim = 1.0;
00281                         
00282                         //printf("%s << lim = (%f -> %f)\n", __FUNCTION__, maxAverageError, lim);
00283                 
00284                         for (unsigned int iii = 0; iii < heatMap.rows; iii++) {
00285                                 for (unsigned int jjj = 0; jjj < heatMap.cols; jjj++) {
00286                                         
00287                                         unsigned int quantRow = floor((float(iii+0) / float(heatMap.rows)) * float(cumulativeErrorGrid.rows));
00288                                         unsigned int quantCol = floor((float(jjj+0) / float(heatMap.cols)) * float(cumulativeErrorGrid.cols));
00289                                         
00290                                         // zero value reserved for cells which contain no points
00291                                         if (heatMap.at<unsigned char>(iii,jjj) != 0) {
00292                                                 heatMap.at<unsigned char>(iii,jjj) = round(1.0 + 254.0 * (cumulativeErrorGrid.at<float>(quantRow, quantCol) / lim));
00293                                                 
00294                                                 heatMapCol.at<Vec3b>(iii,jjj)[0] = heatMap.at<unsigned char>(iii,jjj);
00295                                                 heatMapCol.at<Vec3b>(iii,jjj)[1] = heatMap.at<unsigned char>(iii,jjj);
00296                                                 heatMapCol.at<Vec3b>(iii,jjj)[2] = heatMap.at<unsigned char>(iii,jjj);
00297                                         }
00298                                         
00299                                         
00300                                         
00301                                         
00302                                         
00303                                 }
00304                         }
00305                         
00306                         //imshow("heatMap", heatMap);
00307                         //waitKey();
00308                         
00309                         cScheme colourMap;
00310                         colourMap.load_standard(300, 1);
00311                         colourMap.falsify_image(heatMap, heatMapCol);
00312                 
00313                         for (unsigned int iii = 0; iii < heatMap.rows; iii++) {
00314                                 for (unsigned int jjj = 0; jjj < heatMap.cols; jjj++) {
00315                                         if (heatMap.at<unsigned char>(iii,jjj) == 0) {
00316                                                 heatMapCol.at<Vec3b>(iii,jjj)[0] = 196;
00317                                                 heatMapCol.at<Vec3b>(iii,jjj)[1] = 196;
00318                                                 heatMapCol.at<Vec3b>(iii,jjj)[2] = 196;
00319                                         }
00320                                 }
00321                         }
00322                 
00323                         char imageName[256];
00324                         sprintf(imageName, "/home/steve/Dropbox/Steve-Peyman/jfr2013/draft/figures/intrinsics/heatmap-%3.3f.jpg", lim);
00325                         imwrite(imageName, heatMapCol);
00326                                 
00327                         //imshow("heatMap", heatMapCol);
00328                         //waitKey();
00329                         
00330                         //printf("%s << B5\n",__FUNCTION__);
00331                 
00332                 }
00333                 
00334                 if (debug) { printf("%s << B6\n",__FUNCTION__); }
00335                 
00336         }
00337         
00338          
00339         
00340         if (!removeSpatialBias) {
00341                 
00342                 tSum = 0.0;
00343                 // Calculate means
00344                 for (unsigned int i = 0; i < corners.size(); i++)       {
00345                         for (unsigned int j = 0; j < cornerSet.size(); j++) {
00346 
00347                                 if (errValues)
00348                                 {
00349                                         tSum += errValues[i*cornerSet.size()+j];
00350                                 }
00351 
00352                         }
00353                 }
00354                 
00355                 err = tSum / (corners.size()*cornerSet.size());
00356                 
00357                 //printf("%s << err without de-biasing: (%f)\n", __FUNCTION__, err);
00358 
00359         }
00360         
00361 
00362     if (errValues) { delete[] errValues; }
00363     
00364     return err;
00365     
00366 }
00367 
00368 void optimizeCalibrationSet(Size imSize,
00369                             cv::vector< cv::vector<Point2f> >& candidatePatterns,
00370                             cv::vector< cv::vector<Point2f> >& testPatterns,
00371                             cv::vector<Point3f> row,
00372                             vector<int>& selectedTags,
00373                             int selection,
00374                             int num,
00375                             bool debugMode,
00376                             bool removeSpatialBias,
00377                             bool generateFigure,
00378                             bool useUndistortedLocations,
00379                             int intrinsicsFlags) 
00380 {
00381         
00382         if (debugMode) { printf("%s << ENTERED.\n", __FUNCTION__); }
00383                                                         
00384     selectedTags.clear();
00385     
00386     Mat distributionMap;
00387     
00388     if (debugMode) {
00389                 distributionMap = Mat::zeros(imSize, CV_8UC1);
00390         }
00391 
00392     // If no optimization is desired
00393     if (selection == 0) {
00394         return;
00395     }
00396 
00397     // Initialize Random Number Generator
00398     srand ( (unsigned int)(time(NULL)) );
00399 
00400     // Calibration Variables
00401     cv::vector< cv::vector<Point3f> > objectPoints;
00402     Mat cameraMatrix = Mat::eye(3, 3, CV_64F);
00403     
00404     cameraMatrix.at<double>(0,2) = (double(imSize.width)-1.0)/2.0;
00405     cameraMatrix.at<double>(1,2) = (double(imSize.height)-1.0)/2.0;
00406     Mat distCoeffs = cv::Mat::zeros(1, 8, CV_64F);
00407     cv::vector<Mat> rvecs, tvecs;
00408 
00409     // Pointset Variables
00410     cv::vector< cv::vector<Point2f> > candidatePatternsCpy;
00411     candidatePatternsCpy.assign(candidatePatterns.begin(), candidatePatterns.end());     // So all corners are preserved for ERE calculation/s
00412     cv::vector< cv::vector<Point2f> > fullSetCorners;
00413     fullSetCorners.assign(testPatterns.begin(), testPatterns.end());     // So all corners are preserved for ERE calculation/s
00414     cv::vector< cv::vector<Point2f> > selectedFrames;
00415     cv::vector< cv::vector<Point2f> > tempFrameTester;
00416     cv::vector< cv::vector<Point2f> > newCorners;
00417 
00418     // Error Measurement Variables
00419     double err;
00420     Mat optimalResults(10, ABSOLUTE_MAX_FRAMES_TO_STORE, CV_64FC1);  // Raw results
00421     Mat rankedScores(10, ABSOLUTE_MAX_FRAMES_TO_STORE, CV_64FC1);    // Reordered results
00422     Mat rankedIndices(10, ABSOLUTE_MAX_FRAMES_TO_STORE, CV_8UC1);    // Indices in order - to correspond with 'rankedScores'
00423 
00424     // Display and Debugging Variables
00425     Mat distributionDisplay(distributionMap.size(), CV_8UC1);
00426 
00427     // Optimization Variables
00428     Mat binMap(30, 40, CV_32SC1);
00429     Mat binTemp(binMap.size(), CV_8UC1);
00430     binMap.setTo(0);
00431 
00432     // Scoring Variables
00433     double score, maxScore = 0.0;
00434     int maxIndex = 0;
00435     int rankedFrames[ABSOLUTE_MAX_FRAMES_TO_STORE];
00436     double rankedScoreVector[ABSOLUTE_MAX_FRAMES_TO_STORE];
00437     double *unrankedScores; // [MAX_FRAMES_TO_LOAD];
00438     //int addedIndices[MAX_FRAMES_TO_LOAD];
00439     vector<int> addedIndices;
00440     double bestScore = 0.0, topScore = 0.0;
00441     int bestIndex;
00442 
00443     vector<unsigned int> currentIndices, topIndices, bestIndices;
00444 
00445     // For optimum number of frames
00446     double prevBestScore = 9e99;
00447     int optimumNum = 0;
00448     unsigned long int possibleCombos;
00449 
00450     // Gaussian Variables
00451     Mat gaussianMat(binMap.size().height, binMap.size().width, CV_64FC1);
00452     createGaussianMatrix(gaussianMat, 0.3);
00453 
00454     // Other Variables
00455     int randomNum = 0;
00456     double testingProbability = 1.00;
00457 
00458     double bestErr = 9e99;
00459 
00460     // Random trials code
00461     int nTrials = 20;
00462 
00463     double median, p90, p99;
00464 
00465     double *values;
00466     
00467     //printf("%s << ENTERED. (%d)\n", __FUNCTION__, 0);
00468 
00469     values = new double[num*nTrials];
00470 
00471     /*
00472     for (int i = 0; i < num; i++) {
00473         values[i] = new double[nTrials];
00474     }
00475     */
00476 
00477     num = min((int)num, (int)candidatePatterns.size());
00478 
00479     // SEED VARIABLES
00480     int nSeeds = 5;
00481     int nSeedTrials = 500;
00482 
00483     int *bestSeedSet, *currentSeedSet;
00484 
00485     double bestSeedScore = 9e50, currentSeedScore;
00486 
00487     bool alreadyUsed;
00488 
00489     int newRandomNum;
00490     
00491     double radialDistribution[RADIAL_LENGTH];
00492     
00493     vector<int> tagNames;
00494     
00495     for (unsigned int iii = 0; iii < candidatePatterns.size(); iii++) {
00496                 tagNames.push_back(iii);
00497         }
00498 
00499     // Clear radial distribution array
00500     for (int i = 0; i < RADIAL_LENGTH; i++)
00501     {
00502         radialDistribution[i] = 0.0;
00503     }
00504     
00505     //printf("%s << ENTERED. (%d)\n", __FUNCTION__, 1);
00506 
00507         if (debugMode) { printf("%s << About to enter switch...\n", __FUNCTION__); }
00508         
00509     switch (selection)
00510     {
00511         // ==================================================
00512     case SCORE_BASED_OPTIMIZATION_CODE:     //        SCORE-BASED OPTIMAL FRAME SELECTION
00513         // ==================================================
00514         // Until you've sufficiently filled the newCorners vector
00515         while (newCorners.size() < (unsigned int)(num))
00516         {
00517             maxScore = 0.0;
00518             maxIndex = 0;
00519 
00520             // For each corner remaining
00521             for (unsigned int i = 0; i < candidatePatterns.size(); i++)
00522             {
00523                 score =  obtainSetScore(distributionMap, binMap, gaussianMat, candidatePatterns.at(i), radialDistribution);
00524                 //printf("%s << Frame [%d] scores %f\n", __FUNCTION__, i, score);
00525                 if (score > maxScore)
00526                 {
00527                     maxScore = score;
00528                     maxIndex = i;
00529                 }
00530                 else if (score < 0)
00531                 {
00532                     printf("%s << ERROR. Negative score. Returning.\n", __FUNCTION__);
00533                     return;
00534                 }
00535             }
00536 
00537             //printf("%s << Top scoring frame #%d gets %f\n", __FUNCTION__, maxIndex, maxScore);
00538             //cin.get();
00539 
00540             newCorners.push_back(candidatePatterns.at(maxIndex));    // Push highest scorer onto new vector
00541 
00542             addToDistributionMap(distributionMap, newCorners.at(newCorners.size()-1));  // update distribution
00543             addToRadialDistribution(radialDistribution, newCorners.at(newCorners.size()-1), distributionMap.size());
00544 
00545             prepForDisplay(distributionMap, distributionDisplay);
00546             imshow("distributionMap", distributionDisplay);
00547 
00548             addToBinMap(binMap, newCorners.at(newCorners.size()-1), distributionMap.size()); // update binned mat
00549             convertScaleAbs(binMap, binTemp);
00550             simpleResize(binTemp, distributionDisplay, Size(480, 640));
00551             equalizeHist(distributionDisplay, distributionDisplay);
00552             //imshow("binMap", distributionDisplay);
00553 
00554             waitKey( 0 );
00555 
00556             candidatePatterns.erase(candidatePatterns.begin()+maxIndex);    // Erase it from original vector
00557         }
00558 
00559         candidatePatterns.clear();
00560         newCorners.swap(candidatePatterns);
00561         break;
00562         // ==================================================
00563     case RANDOM_SET_OPTIMIZATION_CODE:     //              RANDOM FRAME SELECTION
00564         // ==================================================
00565         for (int i = 0; i < num; i++)
00566         {
00567             randomNum = rand() % int(candidatePatterns.size());
00568             newCorners.push_back(candidatePatterns.at(randomNum));
00569             candidatePatterns.erase(candidatePatterns.begin()+randomNum);
00570             selectedTags.push_back(tagNames.at(randomNum));
00571 
00572             addToDistributionMap(distributionMap, newCorners.at(i));
00573             prepForDisplay(distributionMap, distributionDisplay);
00574             imshow("distributionMap", distributionDisplay);
00575             waitKey(40);
00576         }
00577 
00578         candidatePatterns.clear();
00579         newCorners.swap(candidatePatterns);
00580         break;
00581         // ==================================================
00582     case FIRST_N_PATTERNS_OPTIMIZATION_CODE:     //              FIRST N FRAMES SELECTION
00583         // ==================================================
00584         while (candidatePatterns.size() > (unsigned int)(num))
00585         {
00586             candidatePatterns.pop_back();
00587         }
00588 
00589         for (int i = 0; i < num; i++)
00590         {
00591             addToDistributionMap(distributionMap, candidatePatterns.at(i));
00592             selectedTags.push_back(tagNames.at(i));
00593             prepForDisplay(distributionMap, distributionDisplay);
00594             imshow("distributionMap", distributionDisplay);
00595             waitKey(40);
00596         }
00597 
00598         delete[] values;
00599 
00600         return;
00601         // ==================================================
00602     case ENHANCED_MCM_OPTIMIZATION_CODE:     //        MULTIPLE-TRIAL OPTIMAL FRAME SELECTION
00603         // ==================================================
00604 
00605                 if (debugMode) { printf("%s << ENTERED. (%d)\n", __FUNCTION__, 2); }
00606         selectedFrames.clear();
00607 
00608         unrankedScores = new double[candidatePatternsCpy.size()];
00609 
00610         prevBestScore = 9e50;
00611 
00612         //printf("%s << num = %d\n", __FUNCTION__, num);
00613 
00614         for (int N = 0; N < num; N++)
00615         {
00616 
00617                         if (debugMode) { printf("%s << N = (%d / %d)\n", __FUNCTION__, N, num); }
00618                                 
00619             objectPoints.push_back(row);
00620 
00621             //printf("%s << candidatePatternsCpy.size() = %d\n", __FUNCTION__, candidatePatternsCpy.size());
00622 
00623             for (unsigned int i = 0; i < candidatePatternsCpy.size(); i++)
00624             {
00625                                 
00626                                 if (debugMode) { printf("%s << i = (%d / %d)\n", __FUNCTION__, i, candidatePatternsCpy.size()); }
00627 
00628                 tempFrameTester.clear();
00629                 
00630                 if (debugMode) { printf("%s << i = (%d / %d) {%d}\n", __FUNCTION__, i, candidatePatternsCpy.size(), 0); }
00631                 
00632                 tempFrameTester.assign(selectedFrames.begin(), selectedFrames.end());
00633                 
00634                 if (debugMode) { printf("%s << i = (%d / %d) {%d}\n", __FUNCTION__, i, candidatePatternsCpy.size(), 1); }
00635                 
00636                 tempFrameTester.push_back(candidatePatternsCpy.at(i));
00637                 
00638                 if (debugMode) { printf("%s << i = (%d / %d) {%d}\n", __FUNCTION__, i, candidatePatternsCpy.size(), 2); }
00639 
00640                 bool alreadyAdded = false;
00641 
00642                 for (int k = 0; k < addedIndices.size(); k++)
00643                 {
00644                                         
00645                                         if (debugMode) { printf("%s << k = (%d / %d)\n", __FUNCTION__, k, addedIndices.size()); }
00646                                         
00647                     if (i == addedIndices.at(k))       // this was addedIndices[N] before - but that doesn't make sense...
00648                     {
00649                         alreadyAdded = true;
00650                         //printf("%s << WTF?\n", __FUNCTION__);
00651                     }
00652                 }
00653                 
00654                 if (debugMode) { printf("%s << i = (%d / %d) {%d}\n", __FUNCTION__, i, candidatePatternsCpy.size(), 3); }
00655 
00656                 if (alreadyAdded == true)
00657                 {
00658                     err = -1.0;
00659                 }
00660                 else
00661                 {
00662 
00663                     randomNum = rand() % 1000 + 1;  // random number between 1 and 1000 (inclusive)
00664 
00665                     Mat fovMat, errMat;
00666                     double fovScore, errScore;
00667 
00668                     if (randomNum > (1 - testingProbability)*1000.0)
00669                     {
00670                         //printf("%s << Calibrating pattern #%d\n", __FUNCTION__, i);
00671 
00672                         //printf("%s << objectPoints.size() = %d; tempFrameTester.size() = %d\n", __FUNCTION__, objectPoints.size(), tempFrameTester.size());
00673 
00674                                                 //printf("%s << imSize = (%d, %d); objectPoints.at(0).size() = %d; tempFrameTester.at(0).size() = %d\n", __FUNCTION__, imSize.height, imSize.width, objectPoints.at(0).size(), tempFrameTester.at(0).size());
00675 
00676                         calibrateCamera(objectPoints, tempFrameTester, imSize, cameraMatrix, distCoeffs, rvecs, tvecs, intrinsicsFlags);
00677 
00678                         //printf("%s << objectPoints.at(0).size() = %d; fullSetCorners.size() = %d\n", __FUNCTION__, objectPoints.at(0).size(), fullSetCorners.size());
00679                                                 
00680                                                 //for (unsigned int xxx = 0; xxx < fullSetCorners.size(); xxx++) {
00681                                                 //      printf("%s << fullSetCorners.at(%d).size() = %d\n", __FUNCTION__, xxx, fullSetCorners.at(xxx).size());
00682                                                 //}
00683 
00684                         err = calculateERE(imSize, objectPoints.at(0), fullSetCorners, cameraMatrix, distCoeffs, removeSpatialBias, false, useUndistortedLocations);
00685                         //printf("%s << err = %f\n", __FUNCTION__, err);
00686                     }
00687                     else
00688                     {
00689                         // If the frame is not to be tested (more likely with lower testingProbability)
00690                         err = -1.0;
00691                     }
00692 
00693                 }
00694                 
00695                 if (debugMode) { printf("%s << i = (%d / %d) {%d}\n", __FUNCTION__, i, candidatePatternsCpy.size(), 4); }
00696 
00697                 unrankedScores[i] = err;
00698                 //printf("%s << score = %f\n", __FUNCTION__, err);
00699                 
00700                 
00701 
00702             }
00703 
00704             bestScore = 9e50;
00705             bestIndex = 0;
00706             
00707             if (debugMode) { printf("%s << X {%d}\n", __FUNCTION__, 0); }
00708 
00709             for (unsigned int j = 0; j < candidatePatternsCpy.size(); j++)
00710             {
00711                                 
00712                                 if (debugMode) { printf("%s << j = (%d / %d)\n", __FUNCTION__, j, candidatePatternsCpy.size()); }
00713 
00714                 if ((unrankedScores[j] < bestScore) && (unrankedScores[j] > 0))
00715                 {
00716                     bestScore = unrankedScores[j];
00717                     bestIndex = j;
00718                 }
00719             }
00720 
00721             unrankedScores[bestIndex] = 9e50;
00722 
00723             //printf("%s << Best score for %d frame calibration: %f\n", __FUNCTION__, N+1, bestScore);
00724 
00725             selectedFrames.push_back(candidatePatternsCpy.at(bestIndex));
00726 
00727             // Corrupt best frame in 'originalFramesCpy'
00728             for (unsigned int i = 0; i < candidatePatternsCpy.at(bestIndex).size(); i++)
00729             {
00730                                 if (debugMode) { printf("%s << i(%d) = (%d / %d)\n", __FUNCTION__, bestIndex, i, candidatePatternsCpy.at(bestIndex).size()); }
00731                 candidatePatternsCpy.at(bestIndex).at(i) = Point2f(0.0,0.0);
00732             }
00733 
00734             addedIndices.push_back(bestIndex);
00735 
00736             if (bestScore < prevBestScore)
00737             {
00738                 prevBestScore = bestScore;
00739                 optimumNum = N;
00740             }
00741             
00742             
00743                         printf("%s << (%d) frames considered; best generalized error so far = (%f)\n", __FUNCTION__, N+1, prevBestScore);
00744                         
00745 
00746         }
00747 
00748         delete[] unrankedScores;
00749 
00750         if (debugMode) { printf("%s << Optimum number of frames for calibration = %d\n", __FUNCTION__, optimumNum+1); }
00751 
00752         candidatePatterns.clear();
00753         candidatePatterns.assign(selectedFrames.begin(), selectedFrames.begin() + optimumNum+1);
00754 
00755         for (int i = 0; i < optimumNum+1; i++)
00756         {
00757             selectedTags.push_back(tagNames.at(addedIndices.at(i)));
00758         }
00759         
00760         if (debugMode) {
00761                         
00762                         printf("%s << Attempting to add patterns to distribution map..\n", __FUNCTION__);
00763                         
00764                         for (int iii = 0; iii < candidatePatterns.size(); iii++) {
00765                                 printf("%s << Adding pattern (%d)..\n", __FUNCTION__, iii);
00766                                 addToDistributionMap(distributionMap, candidatePatterns.at(iii));
00767                         }
00768                         
00769                         
00770                         
00771                         
00772 
00773                         //addToBinMap(binMap, newCorners.at(newCorners.size()-1), distributionMap.size()); // update binned mat
00774                         //convertScaleAbs(binMap, binTemp);
00775                         //simpleResize(binTemp, distributionDisplay, Size(480, 640));
00776                         //equalizeHist(distributionDisplay, distributionDisplay);
00777                         //imshow("binMap", distributionDisplay);
00778 
00779                         if (generateFigure) {
00780                                 
00781                                 //printf("%s << Patterns added, prepping display\n", __FUNCTION__);
00782                                 prepForDisplay(distributionMap, distributionDisplay);
00783                                 //imshow("distributionMap", distributionDisplay);
00784                                 imwrite("/home/steve/Dropbox/Steve-Peyman/jfr2013/draft/figures/intrinsics/point_distribution.jpg", distributionDisplay);
00785                                 //waitKey( 0 );
00786                         }
00787                         
00788                 }
00789         
00790         
00791         //printf("%s << ENTERED. (%d)\n", __FUNCTION__, 3);
00792 
00793         break;
00794         // ==================================================
00795     case RANDOM_SEED_OPTIMIZATION_CODE:     //        Random N-seed accumulative search
00796         // ==================================================
00797 
00798         selectedFrames.clear();
00799 
00800         unrankedScores = new double[candidatePatternsCpy.size()];
00801 
00802         prevBestScore = 9e50;
00803 
00804         //printf("%s << num = %d\n", __FUNCTION__, num);
00805 
00806 
00807 
00808         bestSeedSet = new int[nSeeds];
00809         currentSeedSet = new int[nSeeds];
00810 
00811 
00812 
00813         for (int iii = 0; iii < nSeedTrials; iii++)
00814         {
00815 
00816             objectPoints.clear();
00817             tempFrameTester.clear();
00818 
00819             randomNum = rand() % candidatePatternsCpy.size();
00820 
00821             currentSeedSet[0] = randomNum;
00822             objectPoints.push_back(row);
00823 
00824 
00825             tempFrameTester.push_back(candidatePatternsCpy.at(currentSeedSet[0]));
00826 
00827             for (int jjj = 1; jjj < nSeeds; jjj++)
00828             {
00829                 do
00830                 {
00831                     alreadyUsed = false;
00832 
00833                     randomNum = rand() % candidatePatternsCpy.size();
00834 
00835                     for (int kkk = 0; kkk < jjj; kkk++)
00836                     {
00837                         if (randomNum == currentSeedSet[kkk])
00838                         {
00839                             alreadyUsed = true;
00840                         }
00841                     }
00842                 }
00843                 while (alreadyUsed);
00844 
00845                 currentSeedSet[jjj] = randomNum;
00846 
00847                 objectPoints.push_back(row);
00848                 tempFrameTester.push_back(candidatePatternsCpy.at(currentSeedSet[jjj]));
00849             }
00850 
00851             calibrateCamera(objectPoints, tempFrameTester, imSize, cameraMatrix, distCoeffs, rvecs, tvecs, intrinsicsFlags);
00852 
00853             currentSeedScore = calculateERE(imSize, objectPoints.at(0), fullSetCorners, cameraMatrix, distCoeffs, removeSpatialBias, false, useUndistortedLocations);
00854 
00855             if (currentSeedScore < bestSeedScore)
00856             {
00857                 bestSeedScore = currentSeedScore;
00858 
00859                 printf("%s << Best seed score [trial = %d]: %f\n", __FUNCTION__, iii, bestSeedScore);
00860 
00861                 for (int jjj = 0; jjj < nSeeds; jjj++)
00862                 {
00863                     bestSeedSet[jjj] = currentSeedSet[jjj];
00864                 }
00865 
00866             }
00867 
00868         }
00869 
00870         for (int jjj = 0; jjj < nSeeds; jjj++)
00871         {
00872             selectedFrames.push_back(candidatePatternsCpy.at(bestSeedSet[jjj]));
00873             unrankedScores[bestSeedSet[jjj]] = 9e50;
00874 
00875             // Corrupt seed frames
00876             for (unsigned int kkk = 0; kkk < candidatePatternsCpy.at(bestSeedSet[jjj]).size(); kkk++)
00877             {
00878                 candidatePatternsCpy.at(bestSeedSet[jjj]).at(kkk) = Point2f(0.0,0.0);
00879             }
00880 
00881             addedIndices.push_back(bestSeedSet[jjj]);
00882         }
00883 
00884         bestScore = bestSeedScore;
00885 
00886         // Subtract 1 because later code is dodgy... :P
00887         optimumNum = nSeeds-1;
00888 
00889         for (int N = nSeeds; N < num; N++)
00890         {
00891 
00892             objectPoints.push_back(row);
00893 
00894             //printf("%s << candidatePatternsCpy.size() = %d\n", __FUNCTION__, candidatePatternsCpy.size());
00895 
00896             for (unsigned int i = 0; i < candidatePatternsCpy.size(); i++)
00897             {
00898 
00899                 tempFrameTester.clear();
00900                 tempFrameTester.assign(selectedFrames.begin(), selectedFrames.end());
00901                 tempFrameTester.push_back(candidatePatternsCpy.at(i));
00902 
00903                 bool alreadyAdded = false;
00904 
00905                 for (int k = 0; k < addedIndices.size(); k++)
00906                 {
00907                     if (i == addedIndices.at(k))       // this was addedIndices[N] before - but that doesn't make sense...
00908                     {
00909                         alreadyAdded = true;
00910                         //printf("%s << WTF?\n", __FUNCTION__);
00911                     }
00912                 }
00913 
00914                 if (alreadyAdded == true)
00915                 {
00916                     err = -1.0;
00917                 }
00918                 else
00919                 {
00920 
00921                     randomNum = rand() % 1000 + 1;  // random number between 1 and 1000 (inclusive)
00922 
00923                     Mat fovMat, errMat;
00924                     double fovScore, errScore;
00925 
00926                     if (randomNum > (1 - testingProbability)*1000.0)
00927                     {
00928                         //printf("%s << Calibrating pattern #%d\n", __FUNCTION__, i);
00929 
00930                         //printf("%s << objectPoints.size() = %d; tempFrameTester.size() = %d\n", __FUNCTION__, objectPoints.size(), tempFrameTester.size());
00931 
00932                         calibrateCamera(objectPoints, tempFrameTester, imSize, cameraMatrix, distCoeffs, rvecs, tvecs, intrinsicsFlags);
00933 
00934                         //printf("%s << objectPoints.at(0).size() = %d; fullSetCorners.size() = %d\n", __FUNCTION__, objectPoints.at(0).size(), fullSetCorners.size());
00935 
00936                         err = calculateERE(imSize, objectPoints.at(0), fullSetCorners, cameraMatrix, distCoeffs, removeSpatialBias, false, useUndistortedLocations);
00937                         //printf("%s << err = %f\n", __FUNCTION__, err);
00938                     }
00939                     else
00940                     {
00941                         // If the frame is not to be tested (more likely with lower testingProbability)
00942                         err = -1.0;
00943                     }
00944 
00945                 }
00946 
00947                 unrankedScores[i] = err;
00948 
00949             }
00950 
00951             bestScore = 9e50;
00952             bestIndex = 0;
00953 
00954             for (unsigned int j = 0; j < candidatePatternsCpy.size(); j++)
00955             {
00956 
00957                 if ((unrankedScores[j] < bestScore) && (unrankedScores[j] > 0))
00958                 {
00959                     bestScore = unrankedScores[j];
00960                     bestIndex = j;
00961                 }
00962             }
00963 
00964             unrankedScores[bestIndex] = 9e50;
00965 
00966             printf("%s << Best score for %d frame calibration: %f\n", __FUNCTION__, N+1, bestScore);
00967 
00968             selectedFrames.push_back(candidatePatternsCpy.at(bestIndex));
00969 
00970             // Corrupt best frame in 'originalFramesCpy'
00971             for (unsigned int i = 0; i < candidatePatternsCpy.at(bestIndex).size(); i++)
00972             {
00973                 candidatePatternsCpy.at(bestIndex).at(i) = Point2f(0.0,0.0);
00974             }
00975 
00976             addedIndices.push_back(bestIndex);
00977 
00978             if (bestScore < prevBestScore)
00979             {
00980                 prevBestScore = bestScore;
00981                 optimumNum = N;
00982             }
00983 
00984         }
00985 
00986         delete[] unrankedScores;
00987 
00988         printf("%s << Optimum number of frames for calibration = %d\n", __FUNCTION__, optimumNum+1);
00989 
00990         candidatePatterns.clear();
00991         candidatePatterns.assign(selectedFrames.begin(), selectedFrames.begin() + optimumNum+1);
00992 
00993         for (int i = 0; i < optimumNum+1; i++)
00994         {
00995             selectedTags.push_back(tagNames.at(addedIndices.at(i)));
00996         }
00997 
00998         break;
00999         // ==================================================
01000     case EXHAUSTIVE_SEARCH_OPTIMIZATION_CODE:     //        EXHAUSTIVE TRUE-OPTIMAL SELECTION
01001         // ==================================================
01002 
01003         if (candidatePatternsCpy.size() > 20)
01004         {
01005             printf("%s << Too many frames for exhaustive approach.\n", __FUNCTION__);
01006             break;
01007         }
01008         else
01009         {
01010             printf("%s << Searching for absolute optimum.\n", __FUNCTION__);
01011         }
01012 
01013         bestScore = 9e99;
01014 
01015         // For each different value of N
01016         for (int N = 0; N < num; N++)
01017         {
01018 
01019             topScore = 9e99;
01020 
01021             printf("%s << N(+1) = %d\n", __FUNCTION__, N+1);
01022 
01023             objectPoints.push_back(row);
01024 
01025             possibleCombos = 1;
01026 
01027             possibleCombos = factorial(candidatePatternsCpy.size()) / (factorial(N+1) * factorial(candidatePatternsCpy.size() - N - 1));
01028 
01029             printf("%s << possibleCombos = %d\n", __FUNCTION__, possibleCombos);
01030 
01031             currentIndices.clear();
01032 
01033             // For each possible combo
01034             for (unsigned int i = 0; i < possibleCombos; i++)
01035             {
01036 
01037                 tempFrameTester.clear();
01038                 getNextCombo(currentIndices, N+1, candidatePatternsCpy.size());
01039 
01040                 for (int j = 0; j < currentIndices.size(); j++)
01041                 {
01042                     //printf("%s << currentIndices.at(%d) = %d\n", __FUNCTION__, j, currentIndices.at(j));
01043                     tempFrameTester.push_back(candidatePatternsCpy.at(currentIndices.at(j)));
01044                 }
01045 
01046                 err = calibrateCamera(objectPoints, tempFrameTester, imSize, cameraMatrix, distCoeffs, rvecs, tvecs, intrinsicsFlags);
01047 
01048                 Mat fovMat, errMat;
01049                 double fovScore, errScore;
01050 
01051                 err = calculateERE(imSize, objectPoints.at(0), fullSetCorners, cameraMatrix, distCoeffs, removeSpatialBias, false, useUndistortedLocations);
01052 
01053                 if (err < topScore)
01054                 {
01055                     topScore = err;
01056                     topIndices.clear();
01057                     topIndices.assign(currentIndices.begin(), currentIndices.end());
01058                 }
01059 
01060                 if (err < bestScore)
01061                 {
01062                     bestScore = err;
01063                     bestIndices.clear();
01064                     bestIndices.assign(currentIndices.begin(), currentIndices.end());
01065                 }
01066 
01067             }
01068 
01069             printf("%s << topScore [(N+1) = %d] = %f\n", __FUNCTION__, N+1, topScore);
01070 
01071             for (int j = 0; j < topIndices.size(); j++)
01072             {
01073                 printf("%s << topIndices.at(%d) = %d\n", __FUNCTION__, j, topIndices.at(j));
01074             }
01075 
01076         }
01077 
01078         candidatePatterns.clear();
01079 
01080         printf("%s << Optimum number of frames for calibration = %d\n", __FUNCTION__, bestIndices.size());
01081         printf("%s << bestScore = %f\n", __FUNCTION__, bestScore);
01082 
01083         for (unsigned int i = 0; i < bestIndices.size(); i++)
01084         {
01085             printf("%s << bestIndices.at(%d) = %d\n", __FUNCTION__, i, bestIndices.at(i));
01086             candidatePatterns.push_back(candidatePatternsCpy.at(bestIndices.at(i)));
01087         }
01088 
01089         break;
01090         // ==================================================
01091     case BEST_OF_RANDOM_PATTERNS_OPTIMIZATION_CODE:     //              MANY RANDOM TRIALS FRAME SELECTION
01092         // ==================================================
01093 
01094         bestErr = 9e99;
01095 
01096         printf("%s << Random trial selection\n", __FUNCTION__);
01097 
01098         for (unsigned int k = 0; k < nTrials; k++)
01099         {
01100 
01101             //printf("%s << Trial #%d.\n", __FUNCTION__, k);
01102 
01103             objectPoints.clear();
01104             candidatePatterns.clear();
01105             currentIndices.clear();
01106             newCorners.clear();
01107 
01108             candidatePatterns.assign(candidatePatternsCpy.begin(), candidatePatternsCpy.end());
01109 
01110             for (int N = 0; N < num; N++)
01111             {
01112 
01113                 objectPoints.push_back(row);
01114                 randomNum = rand() % int(candidatePatterns.size());
01115                 currentIndices.push_back(randomNum);
01116                 newCorners.push_back(candidatePatterns.at(randomNum));
01117                 candidatePatterns.erase(candidatePatterns.begin()+randomNum);
01118                 //printf("%s << oP.size() = %d; nC.size() = %d\n", __FUNCTION__, objectPoints.size(), newCorners.size());
01119 
01120                 err = calibrateCamera(objectPoints, newCorners, imSize, cameraMatrix, distCoeffs, rvecs, tvecs, intrinsicsFlags);
01121 
01122                 Mat fovMat, errMat;
01123                 double fovScore, errScore;
01124                 err = calculateERE(imSize, objectPoints.at(0), fullSetCorners, cameraMatrix, distCoeffs, removeSpatialBias, false, useUndistortedLocations);
01125 
01126                 values[N*nTrials+k] = err;
01127 
01128                 //printf("%s << trial #%d, N = %d, score = %f\n", __FUNCTION__, k, N, err);
01129 
01130                 if (err < bestErr)
01131                 {
01132                     bestErr = err;
01133                     bestIndices.clear();
01134 
01135                     selectedFrames.clear();
01136 
01137                     bestIndices.assign(currentIndices.begin(), currentIndices.end());
01138 
01139                     selectedFrames.assign(newCorners.begin(), newCorners.end());
01140 
01141                     //printf("%s << new bestErr[N = %d] = %f\n", __FUNCTION__, N, bestErr);
01142                 }
01143             }
01144         }
01145 
01146         candidatePatterns.clear();
01147 
01148         for (int N = 0; N < num; N++)
01149         {
01150             median = findEquivalentProbabilityScore(&values[N*nTrials], nTrials, 0.5);
01151             p90 = findEquivalentProbabilityScore(&values[N*nTrials], nTrials, 0.9);
01152             p99 = findEquivalentProbabilityScore(&values[N*nTrials], nTrials, 0.99);
01153 
01154             //printf("%s << Random results for %d frames: median = %f; p90 = %f; p99 = %f\n", __FUNCTION__, N, median, p90, p99);
01155         }
01156 
01157         candidatePatterns.assign(selectedFrames.begin(), selectedFrames.end());
01158 
01159         break;
01160     default:
01161 
01162         delete[] values;
01163 
01164         return;
01165     }
01166 
01167 
01168     delete[] values;
01169 
01170 }


thermalvis
Author(s): Stephen Vidas
autogenerated on Sun Jan 5 2014 11:38:45