ImageForest.cpp
Go to the documentation of this file.
00001 #include <face_contour_detector/ImageForest.h>
00002 
00003 #include <map>
00004 #include <vector>
00005 #include <limits>
00006 #include <face_contour_detector/Bgr8.h>
00007 #include <ros/assert.h>
00008 
00009 namespace face_contour_detector {
00010 
00011         ImageForest::Point::Point(int x, int y) : x(x), y(y) { }
00012         ImageForest::Point::Point(const Point& other) : x(other.x), y(other.y) { }
00013 
00014         ImageForest::Graph::Graph(): id(0), numPixels(0) {}
00015         ImageForest::Graph::Graph(const Graph& other): id(other.id), numPixels(other.numPixels), endPoints(other.endPoints), connectingPoints(other.connectingPoints) {}
00016 
00017         ImageForest::ImageForest() : m_width(0), m_height(0), m_lastId(0), m_values(0)  {
00018 
00019         }
00020 
00021         ImageForest::ImageForest(const cv::Mat& mat, unsigned char threshold) : m_width(0), m_height(0), m_lastId(0), m_values(0) {
00022                 ReadFromImage(mat, threshold);
00023         }
00024 
00025         ImageForest::~ImageForest() {
00026                 delete [] m_values;
00027         }
00028 
00029         void ImageForest::ReadFromImage(const cv::Mat& mat, unsigned char threshold) {
00030                 assert (mat.cols > 0 && mat.rows > 0);
00031                 m_width = mat.cols;
00032                 m_height = mat.rows;
00033                 if (m_values != 0) {
00034                         delete [] m_values;
00035                 }
00036                 m_lastId = 0;
00037 
00038                 m_values = new int[m_width * m_height];
00039 
00040                 //Write all 0 into the array
00041                 for (int y = 0; y < m_height; y++) {
00042                         for(int x = 0; x < m_width; x++) {
00043                                 ROS_ASSERT(y*m_width + x < m_height*m_width);
00044                                 m_values[y*m_width + x] = 0;
00045                         }
00046                 }
00047 
00048                 //Find all the patches
00049                 int m_lastPatchId = 0;
00050                 for (int y = 0; y < mat.rows; y++) {
00051                         for(int x = 0; x < mat.cols; x++) {
00052                                 if (mat.at<unsigned char>(y,x) >= threshold) {
00053 
00054                                         int foundId = 0;
00055                                         int maxY = y == m_height-1?0:1;
00056                                         int maxX = x == m_width-1?0:1;
00057                                         for (int y2 = y==0?0:-1; y2 <= maxY; y2++) {
00058                                                 for (int x2 = x==0?0:-1; x2 <= maxX; x2++) {
00059                                                         ROS_ASSERT((y+y2)*m_width + (x+x2) < m_height*m_width);
00060                                                         if (m_values[(y+y2)*m_width + (x+x2)] != 0) {
00061                                                                 foundId = m_values[(y+y2)*m_width + (x+x2)];
00062                                                                 break;
00063                                                         }
00064                                                 }
00065                                                 if (foundId != 0)
00066                                                         break;
00067                                         }
00068 
00069                                         if (foundId != 0) {
00070                                                 ROS_ASSERT(y*m_width + x < m_height*m_width);
00071                                                 m_values[y*m_width + x] = foundId;
00072                                         } else {
00073                                                 ROS_ASSERT(y*m_width + x < m_height*m_width);
00074                                                 m_lastPatchId++;
00075                                                 m_values[y*m_width + x] = m_lastPatchId;
00076                                         }
00077                                 }
00078                         }
00079                 }
00080 
00081                 //Find the eq classes
00082                 //set up eq classes map
00083                 int* eqMap = new int[m_lastPatchId+1];
00084                 for (int i = 0; i < m_lastPatchId+1; i++) {
00085                         ROS_ASSERT(i < m_lastPatchId+1);
00086                         eqMap[i] = 0;
00087                 }
00088                 //int m_lastId = 0;
00089 
00090                 //finding eq classes
00091                 for (int y = 0; y < m_height; y++) {
00092                         for(int x = 0; x < m_width; x++) {
00093 
00094                                 if (mat.at<unsigned char>(y,x) >= threshold) {
00095 
00096                                         int mainValue = m_values[y*m_width + x];
00097                                         int maxY = y == m_height-1?0:1;
00098                                         int maxX = x == m_width-1?0:1;
00099 
00100                                         for (int y2 = y==0?0:-1; y2 <= maxY; y2++) {
00101                                                 for (int x2 = x==0?0:-1; x2 <= maxX; x2++) {
00102 
00103                                                         int subValue = m_values[(y+y2)*m_width + (x+x2)];
00104                                                         if (subValue != 0 && subValue != mainValue) {
00105                                                                 M_SetEqClass(eqMap, m_lastPatchId+1, subValue, mainValue);
00106                                                         }
00107                                                 }
00108                                         }
00109                                 }
00110                         }
00111                 }
00112 
00113                 //resetting the eq classes id's
00114                 int* finalEqMap = new int[m_lastPatchId+1];
00115                 for (int i = 0; i < m_lastPatchId+1; i++) {
00116                         ROS_ASSERT(i < m_lastPatchId+1);
00117                         finalEqMap[i] = 0;
00118                 }
00119 
00120                 int numEqClasses = 0;
00121                 std::map<int, bool> exist;
00122 
00123                 for (int i = 0; i < m_lastPatchId+1; i++) {
00124                         if (eqMap[i] == 0 || exist.find(eqMap[i]) == exist.end()) {
00125                                 numEqClasses++;
00126                                 if (eqMap[i] != 0) {
00127                                         exist[eqMap[i]] = true;
00128                                         for (int i2 = 0; i2 < m_lastPatchId+1; i2++) {
00129                                                 if (eqMap[i] == eqMap[i2]) {
00130                                                         ROS_ASSERT(i2 < m_lastPatchId+1);
00131                                                         finalEqMap[i2] = numEqClasses;
00132                                                 }
00133                                         }
00134                                 } else {
00135                                         ROS_ASSERT(i < m_lastPatchId+1);
00136                                         finalEqMap[i] = numEqClasses;
00137                                 }
00138 
00139                         }
00140                 }
00141 
00142                 //writting the new class id's to the value array
00143                 for (int y = 0; y < m_height; y++) {
00144                         for(int x = 0; x < m_width; x++) {
00145                                 ROS_ASSERT(y*m_width + x < m_width*m_height);
00146                                 if (m_values[y*m_width + x] != 0) {
00147                                         m_values[y*m_width + x] = finalEqMap[m_values[y*m_width + x]];
00148                                 }
00149                         }
00150                 }
00151 
00152                 m_count = numEqClasses;
00153 
00154                 delete [] finalEqMap;
00155                 delete [] eqMap;
00156         }
00157 
00158 
00159 
00161         cv::Mat ImageForest::GenerateImage() {
00162                 ROS_ASSERT(m_width > 0 && m_height > 0 && m_values != 0);
00163                 cv::Mat re = cv::Mat(m_height, m_width, CV_8UC3);
00164                 GenerateImage(re);
00165                 return re;
00166         }
00167 
00168         void ImageForest::GenerateImage(cv::Mat& mat) {
00169                 ROS_ASSERT(mat.channels() == 3 &&
00170                                 mat.cols == m_width &&
00171                                 mat.rows == m_height);
00172 
00173                 Bgr8 colors[6];
00174                 colors[0].b = 255;
00175                 colors[0].g = 0;
00176                 colors[0].r = 0;
00177 
00178                 colors[1].b = 0;
00179                 colors[1].g = 255;
00180                 colors[1].r = 0;
00181 
00182                 colors[2].b = 0;
00183                 colors[2].g = 0;
00184                 colors[2].r = 255;
00185 
00186                 colors[3].b = 255;
00187                 colors[3].g = 255;
00188                 colors[3].r = 0;
00189 
00190                 colors[4].b = 0;
00191                 colors[4].g = 255;
00192                 colors[4].r = 255;
00193 
00194                 colors[5].b = 255;
00195                 colors[5].g = 0;
00196                 colors[5].r = 255;
00197 
00198                 //first run find eq classes
00199                 for (int y = 0; y < m_height; y++) {
00200                         for (int x = 0; x < m_width; x++) {
00201                                 if (m_values[m_width*y + x] != 0) {
00202                                         ROS_ASSERT(m_values[m_width*y + x]%6 < 6 && m_values[m_width*y + x]%6 >= 0);
00203                                         mat.at<Bgr8>(y,x) = colors[m_values[m_width*y + x]%6];
00204                                 } else {
00205                                         mat.at<Bgr8>(y,x).b = 0;
00206                                         mat.at<Bgr8>(y,x).g = 0;
00207                                         mat.at<Bgr8>(y,x).r = 0;
00208                                 }
00209                         }
00210                 }
00211         }
00212 
00213         std::map<int, ImageForest::Graph> ImageForest::GetGraphs() {
00214                 if (m_count == 0) {
00215                         return std::map<int,ImageForest::Graph>();
00216                 }
00217                 //run thorugh the picture and save an endpoint for all graphids
00218                 std::map<int, ImageForest::Graph> graphs;
00219                 //initiallize the data
00220                 for (int graphId = 0; graphId < m_count; graphId++) {
00221                         graphs[graphId] = ImageForest::Graph();
00222                         graphs[graphId].id = graphId;
00223                         graphs[graphId].numPixels = 0;
00224                 }
00225                 //run through
00226                 for (int y = 0; y < m_height; y++) {
00227                         for (int x = 0; x < m_width; x++) {
00228                                 int graphId = GetGraphId(x,y);
00229                                 if (graphId != 0) {
00230                                         //Add to the length
00231                                         graphs[graphId].numPixels = graphs[graphId].numPixels+1;
00232                                         //Check what kind of point this is
00233                                         int connectingNum = 0;
00234                                         bool found[9];
00235                                         for (int i = 0; i < 9; i++) {
00236                                                 ROS_ASSERT(i < 9);
00237                                                 found[i] = false;
00238                                         }
00239                                         int i = 0;
00240                                         for (int y2 = -1; y2 <= 1; y2++) {
00241                                                 for (int x2 = -1; x2 <= 1; x2++) {
00242                                                         if (!(y2 == 0 && x2 == 0) &&
00243                                                                 x+x2 >= 0 && x+x2 < m_width &&
00244                                                                 y+y2 >= 0 && y+y2 < m_height) {
00245 
00246                                                                 int neiGraphId = GetGraphId(x+x2,y+y2);
00247                                                                 if (neiGraphId == graphId) {
00248                                                                         ROS_ASSERT(i < 9);
00249                                                                         found[i] = true;
00250                                                                         bool check = true;
00251                                                                         if (i == 1 ||
00252                                                                                 i == 2 ||
00253                                                                                 i == 7 ||
00254                                                                                 i == 8) {
00255                                                                                 ROS_ASSERT(i-1 < 9 && i-1 >= 0);
00256                                                                                 check = !found[i-1];
00257                                                                         }
00258                                                                         if (i == 3 ||
00259                                                                                 i == 5 ||
00260                                                                                 i == 6 ||
00261                                                                                 i == 8) {
00262                                                                                 ROS_ASSERT(i-3 < 9 && i-3 >= 0);
00263                                                                                 check = check && !found[i-3];
00264                                                                         }
00265 
00266                                                                         if (check) {
00267                                                                                 connectingNum++;
00268                                                                         }
00269                                                                 } else if (neiGraphId != 0) {
00270                                                                         //this should never happen, but just to be sure if there is not some kind of bug
00271                                                                         ROS_ASSERT(false);
00272                                                                 }
00273                                                         }
00274                                                         i++;
00275                                                 }
00276                                         }
00277                                         if (connectingNum <= 1 ) {
00278                                                 graphs[graphId].endPoints.push_back(Point(x,y));
00279                                         } else if (connectingNum > 2) {
00280                                                 graphs[graphId].connectingPoints.push_back(Point(x,y));
00281                                         }
00282                                 }
00283                         }
00284                 }
00285 
00286                 return graphs;
00287         }
00288 
00289         double ImageForest::CallculateEdgyness() {
00290                 ROS_ASSERT(m_values != 0);
00291                 double re = 0;
00292                 for (int y = 0; y < Height(); y++) {
00293                         for (int x = 0; x < Width(); x++) {
00294                                 if (GetGraphId(x,y) != 0) {
00295                                         std::vector<ImageForest::Point> vecs;
00296                                         M_GetVectors(x, y, vecs);
00297                                         std::vector<ImageForest::Point>::iterator it;
00298                                         double currMin = std::numeric_limits<double>::infinity();
00299                                         for (it = vecs.begin(); it != vecs.end(); it++) {
00300                                                 std::vector<ImageForest::Point>::iterator it2;
00301                                                 double currValue = 0.0;
00302                                                 for (it2 = vecs.begin(); it2 != vecs.end(); it2++) {
00303 
00304                                                         double angle = acos(
00305                                                                         (double(it->x*it2->x + it->y*it2->y))/
00306                                                                         (sqrt(double(it->x*it->x + it->y*it->y))*sqrt(double(it2->x*it2->x + it2->y*it2->y)))
00307                                                                 );
00308                                                         //pi/4
00309                                                         if (angle > 0.1 && angle < (M_PI/4.0)+0.1) {
00310                                                                 currValue += 3.0;
00311                                                         //pi/2
00312                                                         } else if (angle > (M_PI/4.0)+0.1 && angle < (M_PI/2.0)+0.1) {
00313                                                                 currValue += 2.0;
00314                                                         //3*pi/4
00315                                                         } else if (angle > (M_PI/2.0)+0.1 && angle < (3.0*M_PI/4.0)+0.1) {
00316                                                                 currValue += 1.0;
00317                                                         }
00318                                                 }
00319                                                 if (currValue < currMin) {
00320                                                         currMin = currValue;
00321                                                 }
00322                                         }
00323                                         re += currMin;
00324                                 }
00325                         }
00326                 }
00327                 return re;
00328         }
00329 
00330         double ImageForest::CallculateGraphMass() {
00331                 double numGraphPixels = 0.0;
00332                 for (int y = 0; y < Height(); y++) {
00333                         for (int x = 0; x < Width(); x++) {
00334                                 if (GetGraphId(x,y) != 0) {
00335                                         numGraphPixels += 1.0;
00336                                 }
00337                         }
00338                 }
00339                 /*std::cout<<"width*height="<<Width()*Height()<<std::endl;
00340                 std::cout<<"numGraphPixels="<<numGraphPixels<<std::endl;
00341                 std::cout<<"/="<<numGraphPixels / (double(Width()*Height())-numGraphPixels)<<std::endl;*/
00342                 return numGraphPixels / (double(Width()*Height())-numGraphPixels);
00343         }
00344 
00345         void ImageForest::M_SetEqClass(int* eqMap, int size, int a, int b) {
00346                 int target = 0;
00347                 std::vector<int> combine;
00348                 combine.push_back(a);
00349                 combine.push_back(b);
00350                 if (eqMap[a] != 0) {
00351                         target = eqMap[a];
00352                 }
00353                 if (eqMap[b] != 0 && eqMap[b] < target) {
00354                         target = eqMap[b];
00355                 }
00356 
00357                 if (eqMap[a] != 0 || eqMap[b] != 0) {
00358                         for (int i = 0; i < size; i++) {
00359                                 if (a != i && b != i) {
00360                                         if (eqMap[a] != 0 && eqMap[a] == eqMap[i]) {
00361                                                 combine.push_back(i);
00362                                                 if (target == 0 || target > eqMap[a]) {
00363                                                         target = eqMap[a];
00364                                                 }
00365                                         } else if (eqMap[b] != 0 && eqMap[b] == eqMap[i]) {
00366                                                 combine.push_back(i);
00367                                                 if (target == 0 || target > eqMap[b]) {
00368                                                         target = eqMap[b];
00369                                                 }
00370                                         }
00371                                 }
00372                         }
00373                 }
00374 
00375                 if (target == 0) {
00376                         m_lastId++,
00377                         target = m_lastId;
00378                 }
00379 
00380                 for(std::vector<int>::iterator it = combine.begin(); it < combine.end(); it++) {
00381                         ROS_ASSERT(*it < size && *it >= 0);
00382                         eqMap[*it] = target;
00383                 }
00384         }
00385 } //namespace face_contour_detector
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends


face_contour_detector
Author(s): Fabian Wenzelmann and Julian Schmid
autogenerated on Wed Dec 26 2012 16:18:17