aruco_selectoptimalmarkers.cpp
Go to the documentation of this file.
00001 /*****************************
00002 Copyright 2011 Rafael Muñoz Salinas. All rights reserved.
00003 
00004 Redistribution and use in source and binary forms, with or without modification, are
00005 permitted provided that the following conditions are met:
00006 
00007    1. Redistributions of source code must retain the above copyright notice, this list of
00008       conditions and the following disclaimer.
00009 
00010    2. Redistributions in binary form must reproduce the above copyright notice, this list
00011       of conditions and the following disclaimer in the documentation and/or other materials
00012       provided with the distribution.
00013 
00014 THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED
00015 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
00016 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR
00017 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00018 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00019 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00020 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00021 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00022 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00023 
00024 The views and conclusions contained in the software and documentation are those of the
00025 authors and should not be interpreted as representing official policies, either expressed
00026 or implied, of Rafael Muñoz Salinas.
00027 ********************************/
00028 /****
00029  * Select the n best markers according to their distance. In other words, selects the n farthert markers in terms of hamming distance
00030  *
00031  *
00032  *
00033  *****/
00034 
00035 #include <opencv2/highgui/highgui.hpp>
00036 #include <aruco/aruco.h>
00037 #include <iostream>
00038 #include <aruco/arucofidmarkers.h>
00039 using namespace cv;
00040 using namespace std;
00041 
00042 int HammDist_(const cv::Mat &m1,const cv::Mat & m2)
00043 {
00044   
00045     int dist=0;
00046     for (int y=0;y<5;y++)
00047         for (int x=0;x<5;x++)
00048             if (m1.at<uchar>(y,x)!=m2.at<uchar>(y,x)) dist++;
00049     return dist;
00050 
00051 }
00052 Mat rotate(Mat  in)
00053 {
00054     Mat out;
00055     in.copyTo(out);
00056     for (int i=0;i<in.rows;i++)
00057     {
00058         for (int j=0;j<in.cols;j++)
00059         {
00060             out.at<uchar>(i,j)=in.at<uchar>(in.cols-j-1,i);
00061         }
00062     }
00063     return out;
00064 }
00065 
00066 
00067 int HammDist(const cv::Mat &m1,const cv::Mat & m2)
00068 {
00069     cv::Mat mc=m1.clone();
00070     int minD=std::numeric_limits<int>::max();
00071     for(int i=0;i<4;i++){
00072       int dist=HammDist_(mc,m2);
00073       if( dist<minD) minD=dist;
00074       mc= rotate(mc);
00075     }
00076     return minD;
00077 
00078 }
00079 
00080 int entropy(const cv::Mat &marker)
00081 {
00082   
00083   //the entropy is calcualte for each bin as the number of elements different from it in its sourroundings
00084   int totalEntropy=0;
00085     for (int y=0;y<5;y++)
00086         for (int x=0;x<5;x++){
00087             int minX=max(x-1,0);
00088             int maxX=min(x+1,5);
00089             int minY=max(y-1,0);
00090             int maxY=min(y+1,5);
00091             
00092             for(int yy=minY;yy<maxY;yy++)
00093               for(int xx=minX;xx<maxX;xx++)
00094                   if (marker.at<uchar>(y,x)!=marker.at<uchar>(yy,xx)) totalEntropy++;
00095         }
00096      
00097     return totalEntropy;
00098 }
00099 
00100 int main(int argc,char **argv)
00101 {
00102     try {
00103         if (argc<4) {
00104 
00105             //You can also use ids 2000-2007 but it is not safe since there are a lot of false positives.
00106             cerr<<"Usage: nofMarkers outbasename size [minimum_entropy(9,25)]"<<endl;
00107             return -1;
00108         }
00109         
00110       
00111         //create a vector with all markers
00112         int minimimEntropy=0;
00113         if(argc>=5) minimimEntropy=atoi(argv[4]);
00114         vector<cv::Mat> markers;
00115         vector<int> ventropy;
00116         for (int i=0;i<1024;i++){
00117             markers.push_back(aruco::FiducidalMarkers::getMarkerMat(i) );
00118             ventropy.push_back(entropy( aruco::FiducidalMarkers::getMarkerMat(i) ));
00119         }
00120           cout<<"Calculating distance matrix"<<endl;
00121         //create a matrix with all distances
00122         cv::Mat distances=cv::Mat::zeros(1024,1024,CV_32SC1);
00123         for (int i=0;i<1024;i++)
00124             for (int j=i+1;j<1024;j++)
00125                 distances.at<int>(i,j)=distances.at<int>(j,i)= HammDist (  markers[i],markers[j]);
00126         cout<<"done"<<endl;
00127             //
00128         int nMarkers=atoi(argv[1]);
00129         //select the first marker
00130         vector<bool> usedMarkers(1024,false);
00131  
00132         
00133         
00134         vector<int> selectedMarkers;
00135         //select the masker with higher entropy first
00136         int bestEntr=0;
00137         for(size_t i=0;i<ventropy.size();i++)
00138           if (ventropy[i]>ventropy[bestEntr]) bestEntr=i;
00139         selectedMarkers.push_back(bestEntr);
00140         usedMarkers[bestEntr]=true;
00141         
00142         //remove these with low entropy. Not very elegnat. Other day I will improve the algorithm
00143         //to make it multiobjective
00144         for(size_t i=0;i<ventropy.size();i++)
00145           if (ventropy[i]<minimimEntropy) usedMarkers[i]=true;
00146           
00147         cout<<"Max Entroy in ="<<bestEntr<<" "<<ventropy[bestEntr]<<endl;
00148         //add new markers according to the distance added to the global
00149         for (int i=1;i<nMarkers;i++) {
00150           int bestMarker=-1;
00151           int shorterDist=0;
00152             //select as new marker the one that maximizes mean distance to
00153             for (int j=0;j<distances.cols;j++) {
00154                 if (!usedMarkers[j]) {
00155                     int minDist=std::numeric_limits< int >::max();
00156                     for (size_t k=0;k<selectedMarkers.size();k++)
00157                         if (distances.at<int> ( selectedMarkers[k], j)<minDist) minDist=distances.at<int> ( selectedMarkers[k], j);
00158 //                  cout<<"j="<<j<<" "<<distSum<<"|"<<flush;
00159                     if (minDist>shorterDist){ 
00160                       shorterDist=minDist;
00161                       bestMarker=j;
00162                     }
00163                 }
00164             }
00165             if (bestMarker!=-1 && shorterDist>1 ){
00166               selectedMarkers.push_back(bestMarker);
00167               usedMarkers[bestMarker]=true;
00168 //            cout<<"Best id="<<bestMarker<<" dist="<<farthestDist<< endl;
00169             }
00170             else {cerr<<"COUDL NOT ADD ANY MARKER"<<endl;exit(0);}
00171 //             char c;cin>>c;
00172         }
00173         
00174         sort(selectedMarkers.begin(),selectedMarkers.end());
00175         for(size_t i=0;i<selectedMarkers.size();i++){
00176           char name[1024];
00177           sprintf(name,"%s%d.png",argv[2],selectedMarkers[i]);
00178 //        cout<<"name="<<name<<endl;
00179           cout<<selectedMarkers[i]<<" "<<flush;
00180           Mat markerImage=aruco::FiducidalMarkers::createMarkerImage(selectedMarkers[i],atoi(argv[3]));
00181           imwrite(name,markerImage);
00182         }
00183         cout<<endl;
00184         //print the minimim distance between any two  elements
00185         int minDist=std::numeric_limits<int>::max();
00186         for(size_t i=0;i<selectedMarkers.size()-1;i++)
00187           for(size_t j=i+1;j<selectedMarkers.size();j++){
00188 //          cout<<" d=" << selectedMarkers[i]<<" "<<selectedMarkers[j]<<"->"<<distances.at<int> ( selectedMarkers[i], selectedMarkers[j])<<endl;
00189             if (distances.at<int> ( selectedMarkers[i], selectedMarkers[j]) < minDist) minDist=distances.at<int> ( selectedMarkers[i], selectedMarkers[j]);
00190             
00191           }
00192             
00193         
00194    cout<<"Min Dist="<<minDist<<endl;
00195 
00196     }
00197     catch (std::exception &ex)
00198     {
00199         cout<<ex.what()<<endl;
00200     }
00201 
00202 }
00203 


aruco
Author(s): Rafael Muñoz Salinas , Bence Magyar
autogenerated on Thu Aug 27 2015 12:26:19