Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ROI.cpp
1 /* This file is part of the BIAS library (Basic ImageAlgorithmS).
2 
3  Copyright (C) 2003-2009 (see file CONTACT for details)
4  Multimediale Systeme der Informationsverarbeitung
5  Institut fuer Informatik
6  Christian-Albrechts-Universitaet Kiel
7 
8  BIAS is free software; you can redistribute it and/or modify
9  it under the terms of the GNU Lesser General Public License as published by
10  the Free Software Foundation; either version 2.1 of the License, or
11  (at your option) any later version.
12 
13  BIAS is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public License
19  along with BIAS; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
21 #include "ROI.hh"
22 
23 #include <climits>
24 #ifdef WIN32
25 #undef max
26 #endif
27 
28 #include <Base/Common/W32Compat.hh>
29 
30 #include <Base/Debug/Error.hh>
31 #include "ImageBase.hh"
32 
33 #include <algorithm>
34 
35 using namespace BIAS;
36 using namespace std;
37 
38 #define ROI_IDENTIFIER "MIP-ROI"
39 #define ROI_IDENTIFIER_LENGTH 7
40 
41 #ifdef WIN32
42 # ifdef max
43 # undef max
44 # endif // max
45 #endif //WIN32
46 //////////////////////////////////////////////////////////////////////
47 // operator<<
48 /////////////////////////////////////////////////////////////////////
49 
50 ostream&
51 BIAS::operator<<(ostream& os, const enum ERoiType& type)
52 {
53  switch (type)
54  {
55  case ROI_Corners:
56  os << "ROI_Corners";
57  break;
58  case ROI_Mask:
59  os << "ROI_Mask";
60  break;
61  case ROI_Points:
62  os << "ROI_Points";
63  break;
64  case ROI_Rows:
65  os << "ROI_Rows";
66  break;
67  default:
68  os << "Unknown ROI type" << type;
69  break;
70  }
71  return os;
72 }
73 
74 ostream&
75 BIAS::operator<<(ostream& os, const Position& pos)
76 {
77  os << "[" << pos.x << ", " << pos.y << "]";
78  return os;
79 }
80 
81 ostream&
82 BIAS::operator<<(ostream& os, const ROI& roi)
83 {
84  os << "ROI (" << roi.Width_ << "x" << roi.Height_ << ") type: "
85  << roi.RoiType_ << " : ";
86  switch (roi.RoiType_){
87  case ROI_Corners:
88  os << "(" << roi.UpperLeftX_ << ", " << roi.UpperLeftY_ << ") <--> ("
89  << roi.LowerRightX_ << ", " << roi.LowerRightY_ << ")";
90  break;
91  case ROI_Points:
92  {
93  vector<Position>::const_iterator it;
94  for (it = roi.Vector_.begin(); it != roi.Vector_.end(); it++)
95  os << *it << " ";
96  }
97  break;
98  case ROI_Rows:
99  for (unsigned y = 0; y < roi.Height_; y++)
100  os << y << ":[" << roi.RowStart_[y] << ", " << roi.RowEnd_[y] << ") ";
101  break;
102  case ROI_Mask:
103  break;
104  default:
105  BEXCEPTION("unknonw roi type "<<roi.RoiType_);
106  break;
107  }
108  return os;
109 }
110 
111 //////////////////////////////////////////////////////////////////////
112 // class
113 /////////////////////////////////////////////////////////////////////
114 
115 const int ROI::Version_ = ROI_VERSION_NUMBER;
116 
118 {
119  Release();
120 }
121 
123  RoiType_(ROI_Corners), Width_(0), Height_(0), UpperLeftX_(0), UpperLeftY_(0),
124  LowerRightX_(0), LowerRightY_(0), Mask_(), Vector_(), RowStart_(),
125  RowEnd_()
126 {
127  NewDebugLevel("D_ROI_IO");
128  UnsetROI();
129 }
130 
131 ROI::ROI(const ROI& roi) :
132  RoiType_(ROI_Corners), Width_(0), Height_(0), UpperLeftX_(0), UpperLeftY_(0),
133  LowerRightX_(0), LowerRightY_(0), Mask_(), Vector_(), RowStart_(),
134  RowEnd_()
135 {
136  NewDebugLevel("D_ROI_IO");
137  operator=(roi);
138 }
139 
140 void
142 {
144  Width_ = 0;
145  Height_ = 0;
146  UpperLeftX_ = UpperLeftY_ = 0;
148  Mask_.clear();
149  Vector_.clear();
150  RowStart_.clear();
151  RowEnd_.clear();
152 }
153 
154 ROI&
155 ROI::operator=(const ROI& roi)
156 {
157  RoiType_ = roi.RoiType_;
158  Width_ = roi.Width_;
159  Height_ = roi.Height_;
160  UpperLeftX_ = roi.UpperLeftX_;
161  UpperLeftY_ = roi.UpperLeftY_;
164  Mask_ = roi.Mask_;
165  Vector_ = roi.Vector_;
166  RowStart_ = roi.RowStart_;
167  RowEnd_ = roi.RowEnd_;
168 
169  return *this;
170 }
171 
172 bool
173 ROI::operator==(const ROI& roi) const
174 {
175  if (RoiType_!=roi.RoiType_) return false;
176  switch (RoiType_){
177  case ROI_Corners:
178  return (UpperLeftX_==roi.UpperLeftX_ && UpperLeftY_==roi.UpperLeftY_ &&
180  break;
181  case ROI_Mask:
182  if (Mask_.size()!=roi.Mask_.size()) return false;
183  for (unsigned i=0; i<Mask_.size(); i++){
184  if (Mask_[i]!=roi.Mask_[i]) return false;
185  }
186  return true;
187  break;
188  case ROI_Points:
189  if (Vector_.size()!=roi.Vector_.size()) return false;
190  for (unsigned i=0; i<Vector_.size(); i++){
191  if (Vector_[i]!=roi.Vector_[i]) return false;
192  }
193  return true;
194  break;
195  case ROI_Rows:
196  BIASASSERT(RowStart_.size()==RowEnd_.size());
197  if (RowStart_.size()!=roi.RowStart_.size() ||
198  RowEnd_.size()!=roi.RowEnd_.size() ) return false;
199  for (unsigned i=0; i<Vector_.size(); i++){
200  if (RowStart_[i]!=roi.RowStart_[i] ||
201  RowEnd_[i]!=roi.RowEnd_[i]) return false;
202  }
203  return true;
204  break;
205  default:
206  BIASERR("ROI::operator==() unfinished code");
207  BIASABORT;
208  break;
209  }
210  return false;
211 }
212 
213 void
215 {
217  UpperLeftX_ = UpperLeftY_ = 0;
220  Mask_.clear();
221  Vector_.clear();
222  RowStart_.clear();
223  RowEnd_.clear();
224 }
225 
226 void
227 ROI::Resize(unsigned w, unsigned h)
228 {
229  if (Width_ != w || Height_ != h)
230  {
231  Release();
232  Width_ = w;
233  Height_ = h;
234  }
235 }
236 
237 void
238 ROI::SetROIType(const enum ERoiType& type)
239 {
240  if (type == RoiType_)
241  return;
242  // release memory
243  switch (RoiType_)
244  {
245  case ROI_Corners:
246  break;
247  case ROI_Mask:
248  Mask_.clear();
249  break;
250  case ROI_Points:
251  break;
252  case ROI_Rows:
253  RowStart_.clear();
254  RowEnd_.clear();
255  break;
256  default:
257  BEXCEPTION("Unknown ROI type "<<RoiType_<<" given");
258  break;
259  }
260  // allocate memory
261  switch (type)
262  {
263  case ROI_Corners:
264  break;
265  case ROI_Mask:
266  Mask_.resize(Width_ * Height_, true);
267  break;
268  case ROI_Points:
269  break;
270  case ROI_Rows:
271  RowStart_.resize(Height_, 0);
272  RowEnd_.resize(Height_, Width_);
273  break;
274  default:
275  BEXCEPTION("Unknown ROI type "<<RoiType_<<" given");
276  break;
277  }
278  RoiType_ = type;
279 }
280 
281 ///////////////////////////////////////////////////////////////////////
282 // corners
283 //////////////////////////////////////////////////////////////////////
284 
285 
286 int
287 ROI::SetCorners(unsigned UpperLeftX, unsigned UpperLeftY,
288  unsigned LowerRightX, unsigned LowerRightY)
289 {
290  //cout<<"ROI::SetCorners() : "<<UpperLeftX<<","<<UpperLeftY
291  //<<" - "<<LowerRightX<<","<<LowerRightY<<endl;
293  int res = 0;
294 #ifdef BIAS_DEBUG
295  if (UpperLeftX < 0)
296  {
297  BIASWARN( "UpperLeftX "<<UpperLeftX<<" is <0");
298  UpperLeftX =0;
299  }
300  else if( UpperLeftX > Width_)
301  {
302  BIASWARN( "UpperLeftX "<<UpperLeftX<<" is out of image range "<<Width_);
303  UpperLeftX = Width_;
304  }
305  if (UpperLeftY < 0)
306  {
307  BIASWARN("UpperLeftY "<<UpperLeftY<<" is <0");
308  UpperLeftY=0;
309  }
310  else if(UpperLeftY > Height_)
311  {
312  BIASWARN("UpperLeftY "<<UpperLeftY<<" is out of image range "<<Height_);
313  UpperLeftY=Height_;
314  }
315  if (LowerRightX < 0 )
316  {
317  BIASWARN("LowerRightX "<<LowerRightX<<" is < 0");
318  LowerRightX = 0;
319  }
320  else if( LowerRightX > Width_ )
321  {
322  BIASWARN("LowerRightX "<<LowerRightX<<" is out of image range "<<Width_);
323  LowerRightX = Width_;
324  }
325 
326  if (LowerRightY < 0)
327  {
328  BIASWARN("LowerRightY "<<LowerRightY<<" is <0");
329  LowerRightY = 0;
330  }
331  else if (LowerRightY > Height_ )
332  {
333  BIASWARN("LowerRightY "<<LowerRightY<<" is out of image range "<<Height_);
334  LowerRightY = Height_;
335  }
336  if (LowerRightX < UpperLeftX)
337  {
338 
339  BIASWARN("WARNING: You swapped the x coordinates of the upper left:"<<UpperLeftX<<" and the"
340  <<" lower right "<<LowerRightX<<" corner. ");
341  // no, this is a serious bug, fix outside this function
342  BIASABORT;
343  unsigned int temp = UpperLeftX;
344  UpperLeftX = LowerRightX;
345  LowerRightX = temp;
346  }
347 
348  if (LowerRightY < UpperLeftY)
349  {
350  BIASWARN("WARNING: You swapped the y coordinates of the upper left:"<<UpperLeftY<<" and the"
351  <<" lower right "<<LowerRightY<<"corner.");
352  // no, this is a serious bug, fix outside this function
353  BIASABORT;
354  unsigned int temp = UpperLeftY;
355  UpperLeftY = LowerRightY;
356  LowerRightY = temp;
357  }
358 #endif
359 
360  UpperLeftX_ = UpperLeftX;
361  LowerRightX_ = LowerRightX;
362  UpperLeftY_ = UpperLeftY;
363  LowerRightY_ = LowerRightY;
364 
365  return res;
366 }
367 
368 int
370 {
371  if (RoiType_ != ROI_Mask)
372  {
373  return -1;
374  }
375 
376  BIASASSERT(im.GetStorageType()==ImageBase::ST_invalid ||
378 
379  if (im.GetWidth() != Width_ || im.GetHeight() != Height_ ||
380  im.GetChannelCount() != 1)
381  im.Release();
382 
383  if (im.IsEmpty())
385 
386  unsigned char *dst = (unsigned char *) im.GetImageData();
387  for (unsigned y = 0; y < Height_; y++)
388  {
389  for (unsigned x = 0; x < Width_; x++)
390  {
391  dst[y * Width_ + x] = (Mask(x, y)) ? (0) : (numeric_limits<
392  unsigned char>::max());
393  }
394  }
395 
396  return 0;
397 }
398 
399 int
401 {
403  int res = 0;
404  if (im.GetWidth() == Width_ && im.GetHeight() == Height_)
405  {
407  im.GetChannelCount() == 1)
408  {
409  const unsigned char *ida =
410  static_cast<const unsigned char *> (im.GetImageData());
411  for (unsigned y = 0; y < Height_; y++)
412  {
413  for (unsigned x = 0; x < Width_; x++)
414  {
415  SetMask(x, y, (ida[y * Width_ + x] == 0));
416  }
417  }
418  }
419  else
420  {
421  BIASERR("Wrong mask image given, single channel unsigned "
422  "character image expected!");
423  res = -1;
424  }
425  }
426  else
427  {
428  BIASERR("Wrong mask image size "<<im.GetWidth()<<"x"<<im.GetHeight()
429  <<" given, expected "<<Width_<<"x"<<Height_<<"!"<<endl);
430  res = -2;
431  }
432  return res;
433 }
434 
435 void
436 ROI::SetRows(const std::vector<unsigned>& start,
437  const std::vector<unsigned>& end)
438 {
440  if (start.size() != Height_ || end.size() != Height_)
441  {
442  BEXCEPTION("invalid argument vector size ("<<Height_<<"): "
443  <<start.size()<<" "<<end.size());
444  }
445  for (unsigned y = 0; y < Height_; y++)
446  {
447  if (start[y] > end[y])
448  {
449  BEXCEPTION("invalid argument vector content: start>end "<<start[y]
450  <<" > "<<end[y]);
451  }
452  if (end[y] > Width_)
453  {
454  BEXCEPTION("invalid argument vector content: end > width "<<end[y]
455  <<" > "<<Width_);
456  }
457  }
458  RowStart_ = start;
459  RowEnd_ = end;
460 }
461 
462 void
463 ROI::SetVector(std::vector<Position>& pos)
464 {
466  Vector_ = pos;
467  sort(Vector_.begin(), Vector_.end());
468 }
469 
470 bool
471 ROI::GetVector(std::vector<Position>& vec) const
472 {
473  vec = Vector_;
474  return (RoiType_ == ROI_Points);
475 }
476 
477 void
478 ROI::SetMask(const unsigned& x, const unsigned& y, const bool val)
479 {
481  if (x >= Width_ || y >= Height_)
482  BEXCEPTION("Out of bounds of mask image ("<<x<<", "<<y<<")");
483  BIASASSERT(Height_ * Width_ == Mask_.size());
484  Mask_[y * Width_ + x] = val;
485 }
486 
487 bool
488 ROI::Mask(const unsigned& x, const unsigned& y) const
489 {
490  BIASASSERT(RoiType_==ROI_Mask);
491  if (x >= Width_ || y >= Height_)
492  BEXCEPTION("Out of bounds of mask image ("<<x<<", "<<y<<")");
493  BIASASSERT(Height_ * Width_ == Mask_.size());
494  return Mask_[y * Width_ + x];
495 }
496 
497 bool
498 ROI::SameSize(const ROI& roi) const
499 {
500  BIASASSERT(RoiType_==ROI_Corners);
501  return
502  ((LowerRightX_-UpperLeftX_) - (roi.LowerRightX_-roi.UpperLeftX_)) == 0 &&
503  ((LowerRightY_-UpperLeftY_) - (roi.LowerRightY_-roi.UpperLeftY_)) == 0;
504 }
505 
506 int
507 ROI::WriteBinary(std::ostream& os) const
508 {
509  if (!os)
510  return -1;
511 
512  // 'header'
513  os.write(ROI_IDENTIFIER, ROI_IDENTIFIER_LENGTH);
514  os.write(reinterpret_cast<const char*> (&Version_), sizeof(int));
515  // size of mask image
516  os.write(reinterpret_cast<const char*> (&Width_), sizeof(unsigned));
517  os.write(reinterpret_cast<const char*> (&Height_), sizeof(unsigned));
518  // type
519  os.write(reinterpret_cast<const char*> (&RoiType_), sizeof(enum ERoiType));
520  BCDOUT(D_ROI_IO, "wrote roi type: "<<RoiType_<<endl);
521  switch (RoiType_)
522  {
523  case ROI_Corners:
524  // rectangular roi
525  os.write(reinterpret_cast<const char*> (&UpperLeftX_), sizeof(unsigned));
526  os.write(reinterpret_cast<const char*> (&UpperLeftY_), sizeof(unsigned));
527  os.write(reinterpret_cast<const char*> (&LowerRightX_), sizeof(unsigned));
528  os.write(reinterpret_cast<const char*> (&LowerRightY_), sizeof(unsigned));
529  break;
530  case ROI_Points:
531  {
532  unsigned length = (int)Vector_.size();
533  os.write(reinterpret_cast<const char*> (&length), sizeof(unsigned));
534  vector<Position>::const_iterator it;
535  for (it = Vector_.begin(); it != Vector_.end(); it++)
536  {
537  BCDOUT(D_ROI_IO, "writing " << *it << endl);
538  os.write(reinterpret_cast<const char*> (&(it->x)), sizeof(unsigned));
539  os.write(reinterpret_cast<const char*> (&(it->y)), sizeof(unsigned));
540  }
541  }
542  break;
543  case ROI_Mask:
544  bool tmp;
545  for (unsigned y = 0; y < Height_; y++)
546  {
547  for (unsigned x = 0; x < Width_; x++)
548  {
549  BIASASSERT(Mask_.size() == Width_*Height_);
550  tmp = Mask_[y * Width_ + x];
551  os.write(reinterpret_cast<const char*> (&(tmp)), sizeof(bool));
552  }
553  }
554  break;
555  case ROI_Rows:
556  for (unsigned y = 0; y < Height_; y++)
557  {
558  os.write(reinterpret_cast<const char*> (&(RowStart_[y])),
559  sizeof(unsigned));
560  os.write(reinterpret_cast<const char*> (&(RowEnd_[y])),
561  sizeof(unsigned));
562  }
563  break;
564  default:
565  BEXCEPTION("Unknown ROI type "<<RoiType_<<" given");
566  break;
567  }
568 
569  return (os.good()) ? 0 : -2;
570 }
571 
572 int
573 ROI::ReadBinary(std::istream& is)
574 {
575  //SetDebugLevel(D_ROI_IO);
576  int res = 0;
577  char identifier[ROI_IDENTIFIER_LENGTH];
578  int Version;
579  unsigned length;
580  vector<Position>::iterator it;
581 
582  // 'header'
583  is.read(identifier, ROI_IDENTIFIER_LENGTH);
584  if (strncmp(identifier, ROI_IDENTIFIER, ROI_IDENTIFIER_LENGTH) != 0)
585  {
586  BIASERR("invalid ROI identifier "<<identifier<<endl);
587  return -1;
588  }
589  is.read(reinterpret_cast<char*> (&Version), sizeof(int));
590 
591  switch (Version)
592  {
593  case 100:
594  {
595  // rectangular roi
596  is.read(reinterpret_cast<char*> (&UpperLeftX_), sizeof(unsigned));
597  is.read(reinterpret_cast<char*> (&UpperLeftY_), sizeof(unsigned));
598  is.read(reinterpret_cast<char*> (&LowerRightX_), sizeof(unsigned));
599  is.read(reinterpret_cast<char*> (&LowerRightY_), sizeof(unsigned));
600  // size of mask image
601  unsigned w, h;
602  is.read(reinterpret_cast<char*> (&w), sizeof(unsigned));
603  is.read(reinterpret_cast<char*> (&h), sizeof(unsigned));
604  Resize(w, h);
605  // size of vector
606  is.read(reinterpret_cast<char*> (&length), sizeof(unsigned));
607  // validity flags
608 
609  bool MaskValid, VectorValid;
610  is.read(reinterpret_cast<char*> (&MaskValid), sizeof(bool));
611  is.read(reinterpret_cast<char*> (&VectorValid), sizeof(bool));
612  BCDOUT(D_ROI_IO, "read MaskValid "<<boolalpha<<MaskValid
613  << " VectorValid "<<boolalpha<<VectorValid<<endl);
614  // mask image
615  if (MaskValid && VectorValid)
616  {
617  BEXCEPTION("roi can no longer hold mask and vectors concurrently");
618  }
619  if (MaskValid)
620  {
621  unsigned char *mask = new unsigned char[w * h];
622  BCDOUT(D_ROI_IO, "reading mask image of size "
623  <<Width_<<"x"<<Height_<<endl);
624  is.read(reinterpret_cast<char*> (mask), Width_ * Height_
625  * sizeof(unsigned char));
627  for (unsigned y = 0; y < Height_; y++)
628  {
629  for (unsigned x = 0; x < Width_; x++)
630  {
631  SetMask(x, y, (mask[y * Width_ + x] == 0));
632  }
633  }
634  delete[] mask;
635  }
636  else if (VectorValid)
637  {
639  Vector_.resize(length);
640  BCDOUT(D_ROI_IO, "reading vector of length "<<Vector_.size()<<endl);
641  for (it = Vector_.begin(); it != Vector_.end(); it++)
642  {
643  is.read(reinterpret_cast<char*> (&(it->x)), sizeof(unsigned));
644  is.read(reinterpret_cast<char*> (&(it->y)), sizeof(unsigned));
645  BCDOUT(D_ROI_IO, "read "<<*it<<endl);
646  }
647  }
648  res = (is.good()) ? 0 : -3;
649  }
650  break;
651  case 200:
652  // size
653  unsigned w, h;
654  is.read(reinterpret_cast<char*> (&w), sizeof(unsigned));
655  is.read(reinterpret_cast<char*> (&h), sizeof(unsigned));
656  Resize(w, h);
657  // type
658  enum ERoiType type;
659  is.read(reinterpret_cast<char*> (&type), sizeof(enum ERoiType));
660  SetROIType(type);
661  switch (RoiType_)
662  {
663  case ROI_Corners:
664  // rectangular roi
665  is.read(reinterpret_cast<char*> (&UpperLeftX_), sizeof(unsigned));
666  is.read(reinterpret_cast<char*> (&UpperLeftY_), sizeof(unsigned));
667  is.read(reinterpret_cast<char*> (&LowerRightX_), sizeof(unsigned));
668  is.read(reinterpret_cast<char*> (&LowerRightY_), sizeof(unsigned));
669  break;
670  case ROI_Points:
671  unsigned length;
672  is.read(reinterpret_cast<char*> (&length), sizeof(unsigned));
673  Vector_.resize(length);
674  BCDOUT(D_ROI_IO, "reading vector of length "<<Vector_.size()<<endl)
675  ;
676  for (it = Vector_.begin(); it != Vector_.end(); it++)
677  {
678  is.read(reinterpret_cast<char*> (&(it->x)), sizeof(unsigned));
679  is.read(reinterpret_cast<char*> (&(it->y)), sizeof(unsigned));
680  BCDOUT(D_ROI_IO, "read "<<*it<<endl);
681  }
682  break;
683  case ROI_Mask:
684  bool tmp;
685  for (unsigned y = 0; y < Height_; y++)
686  {
687  for (unsigned x = 0; x < Width_; x++)
688  {
689  is.read(reinterpret_cast<char*> (&tmp), sizeof(bool));
690  SetMask(x, y, tmp);
691  }
692  }
693  break;
694  case ROI_Rows:
695  for (unsigned y = 0; y < Height_; y++)
696  {
697  is.read(reinterpret_cast<char*> (&(RowStart_[y])), sizeof(unsigned));
698  is.read(reinterpret_cast<char*> (&(RowEnd_[y])), sizeof(unsigned));
699  }
700  break;
701  default:
702  BEXCEPTION("Unknown ROI type "<<RoiType_<<" given");
703  break;
704  }
705  break;
706  default:
707  BIASERR("Unknown ROI version "<<Version<<"!");
708  res = -2;
709  break;
710  }
711  return res;
712 }
713 
714 
715 //////////////////////////////////////////////////////////////////////
716 // conversion functions
717 /////////////////////////////////////////////////////////////////////
718 
719 int
720 ROI::ConvertROIType(const enum ERoiType& type)
721 {
722  switch (RoiType_) {
723  case ROI_Corners:
724  switch (type) {
725  case ROI_Corners:
726  return 0;
727  case ROI_Mask:
728  return Corners2Mask_();
729  case ROI_Points:
730  return Corners2Vector_();
731  case ROI_Rows:
732  return Corners2Rows_();
733  }
734  break;
735  case ROI_Mask:
736  switch (type) {
737  case ROI_Corners:
738  return Mask2Corners_();
739  case ROI_Mask:
740  return 0;
741  case ROI_Points:
742  return Mask2Vector_();
743  case ROI_Rows:
744  return Mask2Rows_();
745  }
746  break;
747  case ROI_Points:
748  switch (type) {
749  case ROI_Corners:
750  return Vector2Corners_();
751  case ROI_Mask:
752  return Vector2Mask_();
753  case ROI_Points:
754  return 0;
755  case ROI_Rows:
756  return Vector2Rows_();
757  }
758  break;
759  case ROI_Rows:
760  switch (type) {
761  case ROI_Corners:
762  return Rows2Corners_();
763  case ROI_Mask:
764  return Rows2Mask_();
765  case ROI_Points:
766  return Rows2Vector_();
767  case ROI_Rows:
768  return 0;
769  }
770  break;
771  default:
772  BIASERR("Source ROI for conversion has unknown type " << RoiType_ << "!");
773  return -1;
774  }
775  BIASERR("Unknown target ROI type " << type << " for conversion given!");
776  return -1;
777 }
778 
779 int
781 {
782  BEXCEPTION("Unfinished ROI conversion from corners to mask!");
783  return (RoiType_ == ROI_Corners ? 0 : -1);
784 }
785 
786 int
788 {
789  BEXCEPTION("Unfinished ROI conversion from corners to point vector!");
790  return (RoiType_ == ROI_Corners ? 0 : -1);
791 }
792 
793 int
795 {
796  BEXCEPTION("Unfinished ROI conversion from corners to rows!");
797  return (RoiType_ == ROI_Corners ? 0 : -1);
798 }
799 
800 int
802 {
803  BEXCEPTION("Invalid ROI conversion from mask to corners!");
804  return -1;
805 }
806 
807 int
809 {
810  if (RoiType_ != ROI_Mask)
811  return -1;
812  register unsigned y = 0, x = 0;
813  vector<Position> vec;
814 
815  for (y = 0; y < Height_; y++)
816  {
817  for (x = 0; x < Width_; x++)
818  {
819  if (Mask(x, y))
820  vec.push_back(Position(x, y));
821  }
822  }
823  SetVector(vec);
824  return 0;
825 }
826 
827 int
829 {
830  BEXCEPTION("Invalid ROI conversion from mask to rows!");
831  return -1;
832 }
833 
834 int
836 {
837  if (RoiType_ != ROI_Points)
838  return -1;
839  //@todo Ensure that point vector is sorted from top left to bottom right!
840  SetCorners(Vector_.begin()->x, Vector_.begin()->y, Vector_.rbegin()->x,
841  Vector_.rbegin()->y);
842  return 0;
843 }
844 
845 int
847 {
848  if (RoiType_ != ROI_Points)
849  return -1;
850  vector<Position> vec;
851  GetVector(vec);
852  vector<Position>::iterator it;
854  for (it = vec.begin(); it != vec.end(); it++)
855  {
856 #ifdef BIAS_DEBUG
857  if (!(it->y >= 0 && it->x >= 0 &&
858  it->y < GetHeight() && it->x < GetWidth() ))
859  BIASERR((*it)<<" "<<Width_<<"x"<<Height_<<endl);
860  BIASASSERT(it->y >= 0 && it->x >= 0 &&
861  it->y < Height_ && it->x < Width_ );
862 #endif
863  SetMask(it->x, it->y, true);
864  }
865  return 0;
866 }
867 
868 int
870 {
871  BEXCEPTION("Invalid ROI conversion from point vector to rows!");
872  return -1;
873 }
874 
875 int
877 {
878  BEXCEPTION("Unfinished ROI conversion from rows to corners!");
879  return (RoiType_ == ROI_Rows ? 0 : -1);
880 }
881 
882 int
884 {
885  BEXCEPTION("Unfinished ROI conversion from rows to mask!");
886  return (RoiType_ == ROI_Rows ? 0 : -1);
887 }
888 
889 int
891 {
892  BEXCEPTION("Unfinished ROI conversion from rows to point vector!");
893  return (RoiType_ == ROI_Rows ? 0 : -1);
894 }
895 /*
896 int
897 ROI::Vector2Corners()
898 {
899  if (RoiType_ != ROI_Points)
900  return -1;
901  SetCorners(Vector_.begin()->x, Vector_.begin()->y, Vector_.rbegin()->x,
902  Vector_.rbegin()->y);
903  return 0;
904 }
905 
906 int
907 ROI::Mask2Corners()
908 {
909  BEXCEPTION("unfinished");
910  return (RoiType_ == ROI_Mask);
911 }
912 
913 void
914 ROI::Corners2Mask()
915 {
916  BEXCEPTION("unfinished");
917 }
918 
919 void
920 ROI::Corners2Vector()
921 {
922  BEXCEPTION("unfinished");
923 }
924 */
925 void
926 ROI::Erode(const ROI &src, const unsigned half_mask_size)
927 {
928  RoiType_ = src.RoiType_;
929  switch (RoiType_){
930  case ROI_Corners:
931  UpperLeftX_ += half_mask_size;
932  UpperLeftY_ += half_mask_size;
933  if (UpperLeftX_>Width_){
935  }
936  if (UpperLeftY_>Height_){
938  }
939  if (LowerRightX_<half_mask_size){
940  LowerRightX_ = 0;
941  }
942  if (LowerRightY_<half_mask_size){
943  LowerRightY_ = 0;
944  }
945  LowerRightX_ -= half_mask_size;
946  LowerRightY_ -= half_mask_size;
948  BEXCEPTION("empty ROI");
949  }
950  break;
951  case ROI_Rows:
952  {
953  // check the border of the mask, when the boprder is in the ROI, all
954  // pixel in the mask are also in the roi
955  const int hws = half_mask_size;
956  const int h = (int)src.RowStart_.size();
957  RowStart_.resize(h);
958  RowEnd_.resize(h);
959  int i, y, x;
960  for (y=0; y<h; y++){
961  if (src.RowStart_[y]+2*hws+1>=src.RowEnd_[y]){
962  RowStart_[y] = RowEnd_[y] = 0;
963  continue; // next row
964  }
965  // search for the first pixel to the right from start, where the border
966  // of the maske around it resides completely inside the old roi
967  bool found_start = false;
968  for (x=(int)(src.RowStart_[y])+hws; x<(int)(src.RowEnd_[y])-hws; x++){
969  bool all_in = true;
970  for (i=-hws; i<=hws; i++){
971  if ( ! ( src.IsInROI(x+i, y+hws) && src.IsInROI(x+i, y-hws) &&
972  src.IsInROI(x+hws, y+i) && src.IsInROI(x-hws, y+i) ) ){
973  all_in = false;
974  break;
975  }
976  }
977  if (all_in){
978  found_start = true;
979  RowStart_[y] = x;
980  break; // found start, search for end
981  }
982  }
983  if (!found_start){
984  RowStart_[y] = RowEnd_[y] = 0;
985  continue;
986  }
987  // search for the first pixel to the left from end, where the border
988  // of the maske around it resides completely inside the old roi
989  bool found_end = false;
990  for (x=(int)(src.RowEnd_[y])-hws-1; x>(int)(RowStart_[y]); x--){
991  bool all_in = true;
992  for (i=-hws; i<=hws; i++){
993  if ( ! ( src.IsInROI(x+i, y+hws) && src.IsInROI(x+i, y-hws) &&
994  src.IsInROI(x+hws, y+i) && src.IsInROI(x-hws, y+i) ) ){
995  all_in = false;
996  break;
997  }
998  }
999  if (all_in){
1000  found_end = true;
1001  RowEnd_[y] = x;
1002  break; // found start, search for end
1003  }
1004  }
1005  if (!found_end){
1006  RowStart_[y] = RowEnd_[y] = 0;
1007  continue;
1008  }
1009  }
1010  }
1011  break;
1012  case ROI_Mask:
1013  case ROI_Points:
1014  default:
1015  BIASERR("Erode() is not implemented yet for this ROI type!");
1016  BIASABORT;
1017  break;
1018  }
1019 }
int Corners2Vector_()
Fills vector representation of ROI from corner representation.
Definition: ROI.cpp:787
int Corners2Mask_()
Fills mask representation of ROI from corner representation.
Definition: ROI.cpp:780
int Mask2Corners_()
Fills corner/bounding box representation of ROI from mask representation.
Definition: ROI.cpp:801
stores valid/nvalid positions in image
Definition: ROI.hh:49
class for handling different region of interest (ROI) representations...
Definition: ROI.hh:118
int SetCorners(unsigned UpperLeftX, unsigned UpperLeftY, unsigned LowerRightX, unsigned LowerRightY)
Sets a rectangular region of interest.
Definition: ROI.cpp:287
void Resize(unsigned width, unsigned height)
Resizes parent image.
Definition: ROI.cpp:227
void Release()
Deletes internal memory, sets mask and vector invalid.
Definition: ROI.cpp:141
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
Definition: ImageBase.hh:245
bool SameSize(const ROI &roi) const
Returns true if both ROIs have the same size.
Definition: ROI.cpp:498
std::vector< bool > Mask_
internal data for ROI of type ROI_Mask the mask data: Mask_[y*Width_+x] corresponds to pixel at (x...
Definition: ROI.hh:369
unsigned x
member variables
Definition: ROI.hh:72
int Mask2Vector_()
Fills vector representation of ROI from mask representation.
Definition: ROI.cpp:808
int Vector2Rows_()
Fills rows representation of ROI from vector representation.
Definition: ROI.cpp:869
bool Mask(const unsigned &x, const unsigned &y) const
Direct access to the mask data, const version.
Definition: ROI.cpp:488
unsigned GetWidth() const
width capacity of roi (image width)
Definition: ROI.hh:250
void UnsetROI()
Delete region of interest.
Definition: ROI.cpp:214
unsigned y
Definition: ROI.hh:72
unsigned int GetWidth() const
Definition: ImageBase.hh:312
int WriteBinary(std::ostream &os) const
binary output to stream
Definition: ROI.cpp:507
int Corners2Rows_()
Fills rows representation of ROI from corner representation.
Definition: ROI.cpp:794
unsigned Height_
Definition: ROI.hh:356
void SetROIType(const enum ERoiType &type)
alloc and free of internal memory
Definition: ROI.cpp:238
enum ERoiType RoiType_
which method is used to store the ROI
Definition: ROI.hh:354
int SetMaskImage(const ImageBase &im)
every pixel with value==0.0 is in the ROI, every pixel with value!=0.0 is not in the ROI ...
Definition: ROI.cpp:400
invalid not set image storage type
Definition: ImageBase.hh:111
unsigned Width_
maximum dimension of roi data
Definition: ROI.hh:356
const void * GetImageData() const
Definition: ImageBase.hh:280
unsigned LowerRightX_
Definition: ROI.hh:363
std::vector< Position > * GetVector()
returns a pointer to the vector representation of the ROI
Definition: ROI.hh:242
int ReadBinary(std::istream &is)
binary input from stream
Definition: ROI.cpp:573
ROI()
str. constructor
Definition: ROI.cpp:122
bool VectorValid() const
is the position vector valid?
Definition: ROI.hh:311
int Rows2Vector_()
Fills vector representation of ROI from rows representation.
Definition: ROI.cpp:890
int Vector2Corners_()
Fills corner/bounding box representation of ROI from vector representation.
Definition: ROI.cpp:835
int Rows2Corners_()
Fills corner representation of ROI from rows representation.
Definition: ROI.cpp:876
bool operator==(const ROI &roi) const
comparison
Definition: ROI.cpp:173
bool IsInROI(const double &x, const double &y) const
ROI check if pixel position is inside the ROI.
Definition: ROI.hh:463
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
void Erode(const ROI &src, const unsigned half_mask_size)
Definition: ROI.cpp:926
int Rows2Mask_()
Fills mask representation of ROI from rows representation.
Definition: ROI.cpp:883
unsigned int GetHeight() const
Definition: ImageBase.hh:319
unsigned LowerRightY_
Definition: ROI.hh:363
long int NewDebugLevel(const std::string &name)
creates a new debuglevel
Definition: Debug.hh:474
std::ostream & operator<<(std::ostream &os, const Array2D< T > &arg)
Definition: Array2D.hh:260
unsigned UpperLeftX_
internal data for ROI of type ROI_Corners rectangular region of interest defined by upper left and lo...
Definition: ROI.hh:362
ROI & operator=(const ROI &roi)
assignment operator
Definition: ROI.cpp:155
static const int Version_
version number of ROI class
Definition: ROI.hh:380
std::vector< unsigned > RowEnd_
Definition: ROI.hh:377
void Release(const bool reset_storage_type=false)
Free the allocated data structures Hands off: Do !!NOT!! change the default of reset_storage_type: Im...
Definition: ImageBase.cpp:350
bool MaskValid() const
is the position vector valid?
Definition: ROI.hh:307
int ConvertROIType(const enum ERoiType &type)
Generic conversion function from current ROI representation to the given ROI representation.
Definition: ROI.cpp:720
void Init(unsigned int width, unsigned int height, unsigned int nChannels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
Initialize image size and channels.
Definition: ImageBase.cpp:229
enum EStorageType GetStorageType() const
Definition: ImageBase.hh:414
(8bit) unsigned char image storage type
Definition: ImageBase.hh:112
~ROI()
destructor
Definition: ROI.cpp:117
unsigned GetHeight() const
height capacity of roi (image height)
Definition: ROI.hh:254
void SetMask(const unsigned &x, const unsigned &y, const bool val)
Direct access to the mask data.
Definition: ROI.cpp:478
void SetVector(std::vector< Position > &pos)
Sets MaskValid_=false and VectorValid_=true.
Definition: ROI.cpp:463
int Mask2Rows_()
Fills rows representation of ROI from mask representation.
Definition: ROI.cpp:828
This is the base class for images in BIAS.
Definition: ImageBase.hh:102
ERoiType
Definition: ROI.hh:40
int GetMaskImage(ImageBase &im) const
returns an image of StorageType unsigned char, where every pixel not in the ROI is set to UCHAR_MAX a...
Definition: ROI.cpp:369
std::vector< Position > Vector_
internal data for ROI of type ROI_Points Vector instance of ROI, always sorted from top left to botto...
Definition: ROI.hh:373
void SetRows(const std::vector< unsigned > &start, const std::vector< unsigned > &end)
Horizontal start and end position per image row, the length of the vectors always corresponds to the ...
Definition: ROI.cpp:436
unsigned UpperLeftY_
Definition: ROI.hh:362
int Vector2Mask_()
Fills vector representation of ROI from mask representation.
Definition: ROI.cpp:846
std::vector< unsigned > RowStart_
internal data for ROI of type ROI_Rows the ROI is specified by a min and a max value for each row in ...
Definition: ROI.hh:377