segmentation.cc

来自「用于计算矩阵的特征值,及矩阵的其他运算.可以用与稀疏矩阵」· CC 代码 · 共 936 行 · 第 1/2 页

CC
936
字号
// Copyright (C) 2002 Charless C. Fowlkes <fowlkes@eecs.berkeley.edu>// Copyright (C) 2002 David R. Martin <dmartin@eecs.berkeley.edu>//// This program is free software; you can redistribute it and/or// modify it under the terms of the GNU General Public License as// published by the Free Software Foundation; either version 2 of the// License, or (at your option) any later version.//// This program is distributed in the hope that it will be useful, but// WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU// General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA// 02111-1307, USA, or see http://www.gnu.org/copyleft/gpl.html.#include <string.h>#include <iostream>#include <values.h>#include "segmentation.hh"#include "string.hh"#include "exception.hh"#include "util.hh"#include "regex.hh"namespace Util{  //  // create an empty segmentation   //   Segmentation::Segmentation()  {    _map.resize(0,0);    _map.init(0);    _date = NULL;    _image = NULL;    _user = NULL;    _imageID = 0;     _userID = 0;    _presentation = 0;  }  //  // create an empty segmentation of given size  Segmentation::Segmentation(const int width, const int height)  {    _map.resize(width,height);    _map.init(0);    _date = NULL;    _image = NULL;    _user = NULL;    _imageID = 0;     _userID = 0;    _presentation = 0;    _renumber();  }  //  // create a segmentation which uses the  // given partition as a map  //  Segmentation::Segmentation(const Array2D<int> partition)  {    _map = partition;    _date = NULL;    _image = NULL;    _user = NULL;    _imageID = 0;     _userID = 0;    _presentation = 0;    _renumber();  }  //  // cleanup strings if necessary  //  Segmentation::~Segmentation ()  {    if (_date) { free (_date); }    if (_image) { free (_image); }    if (_user) { free (_user); }  }  // Put single-line string into a canonical form that is good for  // pattern-matching.  Caller must free() returned string.  static char*   _cleanupLine (const char* line)  {      static Regex re1 ("#.*$");      static Regex re2 ("[ \t\r\f\v\n]+");      static Regex re3 ("^ ");      static Regex re4 (" $");      char* s = strdup (line);      re1.subst (s, "", false); 	// Remove comment.      re2.subst (s, " ", true);	// Compress whitespace.      re3.subst (s, "", false);	// Remove leading whitespace.      re4.subst (s, "", false);	// Remove trailing whitespace.      return s;  }  //  // read in a segfile   //  void Segmentation::readFile(const char* file)  {      String buf;      int lineNo = 0;      int width = 0;      int height = 0;      FILE* strm = Util::openInputStrm (file);      // Parse file header.      Regex reBlank 	("^$");      Regex reDate 	("^date (.*)$");      Regex reImage 	("^image (.*)$");      Regex reUser 	("^user (.*)$");      Regex reSegments 	("^segments ([0-9]+)$");      Regex reWidth 	("^width ([0-9]+)$");      Regex reHeight 	("^height ([0-9]+)$");      Regex reGray 	("^gray (0|1)$");      Regex reInvert 	("^invert (0|1)$");      Regex reFlipFlop	("^flipflop (0|1)$");      Regex reFormat 	("^format (ascii|binary) (cr|map)$");      Regex reData 	("^data$");      int format = defaultFormat;      int k = 0;      while (buf.nextLine (strm))       {        lineNo++;        char* s = _cleanupLine (buf.text());        char* sub = strdup (s);		// Scratch array for submatches.        if (reBlank.match (s))         {            free (s); free (sub);            continue;        }         else if (reDate.match (s))         {            _date = strdup (reDate.get (1, sub));        }         else if (reImage.match (s))         {            _image = strdup (reImage.get (1, sub));            _imageID = atoi (_image);        }         else if (reUser.match (s))         {            _user = strdup (reUser.get (1, sub));            _userID = atoi (_user);        }         else if (reSegments.match (s))         {            k = atoi (reSegments.get (1, sub));        }         else if (reWidth.match (s))         {            width = atoi (reWidth.get (1, sub));        }         else if (reHeight.match (s))         {            height = atoi (reHeight.get (1, sub));        }         else if (reGray.match (s))         {            int x = atoi (reGray.get (1, sub));            if (x) { _presentation |= presGray; }             else { _presentation &= ~presGray; }        }         else if (reInvert.match (s))         {            int x = atoi (reInvert.get (1, sub));            if (x) { _presentation |= presInvert; }             else { _presentation &= ~presInvert; }        }         else if (reFlipFlop.match (s))         {            int x = atoi (reFlipFlop.get (1, sub));            if (x) { _presentation |= presFlipFlop; }             else { _presentation &= ~presFlipFlop; }        }         else if (reFormat.match (s))         {            format = 0;            if (strcmp (reFormat.get(1,sub), "ascii") == 0) {              format |= ffASCII;            } else {              format &= ~ffASCII;            }            if (strcmp (reFormat.get(2,sub), "cr") == 0) {              format |= ffCr;            } else {              format &= ~ffCr;            }        }         else if (reData.match (s))         {            free (s);            free (sub);            break;        }         else         {            free (s);            free (sub);            throw Exception (String ("Segmentation::readFile: Error parsing header (line %d): %s.",lineNo, buf.text()));        }        free (s);         free (sub);      }      // Make sure we parsed out the critical info from the header.      if (width == 0 || height == 0)       {        throw Exception ("Segmentation::readFile: Image dimensions not specified.");       }      if (k == 0)       {        throw Exception ("Segmentation::readFile: Number of segments not specified.");      }      // We only support ascii/cr format.      if (format != (ffASCII | ffCr)) {        throw Exception ("Segmentation::readFile: Only supported .seg format is ascii/cr.");      }      //initialize segment map      _map.resize(width,height);      _map.init(k);      // Read the data.      Regex reDatum ("^([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)$");      assert (format == (ffASCII | ffCr));      while (buf.nextLine (strm))       {        lineNo++;        char* s = _cleanupLine (buf.text());        char* sub = strdup (s);		// Scratch array for submatches.        if (strcmp (s, "") == 0)         {          free (s); free (sub);          continue;        }        if (!reDatum.match (s))         {          free (s); free (sub);          throw Exception (String ("Segmentation::_init: Parse error (line %d): %s.",lineNo, buf.text()));        }        int seg = atoi (reDatum.get (1, sub));        int y = atoi (reDatum.get (2, sub));        int x1 = atoi (reDatum.get (3, sub));        int x2 = atoi (reDatum.get (4, sub));        free (s); free (sub);        if (seg >= k)         {          throw Exception (String (          "Segmentation::_init: Line %d: %d > num segments (%d).",           lineNo, seg, k));        }        if (y >= height || x1 >= width || x2 >= width)         {          throw Exception (String (          "Segmentation::_init: Line %d: pixels [%d..%d,%d] "          "is out of range [%d,%d].",          lineNo, x1, x2, y, width, height));        }        for (int x = x1; x <= x2; x++)         {          if (_map(x,y) < k)           {            throw Exception (String (              "Segmentation::_init: Line %d: pixel [%d,%d] "              "assigned to 2 segments.",              lineNo, x, y));          }          _map(x,y) = seg;        }      }          // Check that all pixels were assigned to a segment.      for (int x = 0; x < width; x++)       {        for (int y = 0; y < height; y++)         {          if (_map(x,y) == k)           {            throw Exception (String (            "Segmentation::_init: pixel [%d,%d] not assigned "            "to a segment.", x,y));          }        }      }      fclose (strm);      _renumber();  }  //  // write out to a segfile  //  void   Segmentation::writeFile (const char* file, int format) const  {    FILE* strm = Util::openOutputStrm (file);    if (format != (ffASCII | ffCr)) // Check format.    {      throw Exception ("Segmentation::writeFile: Only supported .seg format is ascii/cr.");    }    assert (format == (ffASCII | ffCr));    fprintf (strm, "format ascii cr\n");    if (_date != NULL && strcmp (_date, "") != 0)     {       fprintf (strm, "date %s\n", _date);     }    if (_image != NULL) { fprintf (strm, "image %s\n", _image); }     else if (_imageID > 0) { fprintf (strm, "image %d\n", _imageID); }    if (_user != NULL) { fprintf (strm, "user %s\n", _user); }    else if (_userID > 0) { fprintf (strm, "user %d\n", _userID); }    fprintf (strm, "width %d\n", _map.size(0));    fprintf (strm, "height %d\n", _map.size(1));    fprintf (strm, "segments %d\n", _numSegments);    fprintf (strm, "gray %d\n", isGray() ? 1 : 0);    fprintf (strm, "invert %d\n", isInverted() ? 1 : 0);    fprintf (strm, "flipflop %d\n", isFlipFloped() ? 1 : 0);    fprintf (strm, "data\n");    //write out in scanline order    for (int row = 0; row < _map.size(1); row++)     {      int prevSeg = _map(0,row);      int start = 0;      for (int col = 1; col < _map.size(0); col++)       {        int seg = _map(col,row);        if (seg == prevSeg) { continue; }        fprintf (strm, "%u %u %u %u\n", prevSeg, row, start, col - 1);        start = col;        prevSeg = seg;      }      fprintf (strm, "%u %u %u %u\n", prevSeg, row, start, _map.size(0)-1);    }    fclose (strm);  }  ///////////////////////////////////////////////////////////////////////////////////////////  //  // connectedness and merging small segments  //  class Node {    public:      Node (int x, int y, Node* next)       {        _x = x;        _y = y;        _next = next;      }      int _x;      int _y;      Node* _next;  };  //  // breadth-first flood fill starting at (x,y), replacing oldId  // with newId.  //  void  Segmentation::_replace(int x, int y, int oldId, int newId, float radius)  {      assert (x < _map.size(0));      assert (y < _map.size(1));      assert (_map(x,y) == oldId);      Node* oldList = new Node (x, y, NULL);      _map(x,y) = newId;      int window = (int) ceil (radius);      float radiusSqr = radius * radius;      while (oldList != NULL)       {        Node* newList = NULL;        while (oldList != NULL)         {          //pop a node          Node* node = oldList;          int x = node->_x;          int y = node->_y;          oldList = node->_next;          delete node;          assert (x < _map.size(0));          assert (y < _map.size(1));          assert (_map(x,y) == newId);          //push the node's neighbors          int umin = Util::max (x - window, 0);          int umax = Util::min (x + window, (int)_map.size(0) - 1);          int vmin = Util::max (y - window, 0);          int vmax = Util::min (y + window, (int)_map.size(1) - 1);          for (int u = umin; u <= umax; u++)           {            for (int v = vmin; v <= vmax; v++)             {              float distSqr = (x-u)*(x-u) + (y-v)*(y-v);              if (distSqr > radiusSqr) { continue; }              if (_map(u,v) != oldId) { continue; }              newList = new Node(u,v,newList);              _map(u,v) = newId;            }          }        }        oldList = newList;      }  }  //  // renumber the segments in a contigous manner  // remove size 0 segments, etc  //  void   Segmentation::_renumber()  {    //upper bound the number of segments    int maxseg = 0;    for (int x = 0; x < _map.size(0); x++)    {      for (int y = 0; y < _map.size(1); y++)      {        maxseg = Util::max(maxseg,_map(x,y));      }     }    //see which segment numbers are in use    Array1D<bool> empty(maxseg+1);    empty.init(true);    for (int x = 0; x < _map.size(0); x++)    {      for (int y = 0; y < _map.size(1); y++)      {        empty(_map(x,y)) = false;      }     }    //compute renumbering from old segment numbers to new    _numSegments = 0;    Array1D<int> renum(maxseg+1);    renum.init(-1);    for (int s = 0; s < maxseg+1; s++)    {      if (!empty(s))      {        renum(s) = _numSegments;        _numSegments++;      }    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?