Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ContourDetectorBSpline.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 #include <fstream>
26 
27 #include <Base/Debug/Debug.hh>
28 #include <Base/Debug/Error.hh>
29 #include <Base/ImageUtils/ImageDraw.hh>
30 #include <Base/Math/Matrix2x2.hh>
31 #include <Filter/GradientSobel3x3.hh>
32 #include <MathAlgo/SVD.hh>
33 
34 
35 #include "ContourDetectorBSpline.hh"
36 
37 using namespace BIAS;
38 using namespace std;
39 
40 template <class StorageType>
43  pData_=NULL;
44  pShapeSpaceMatrix_=NULL;
45  pSubShapeSpaceMatrix_=NULL;
46  pRegMatrix_=NULL;
47  curveInitialised_=false;
48  fitSampleWidth_= new double(0.1);
49  drawSampleWidth_= new double(0.1);
50 }
51 
52 
53 template <class StorageType>
56  if(pData_!=NULL){pData_->Unregister();}
57  if(pShapeSpaceMatrix_!=NULL){pShapeSpaceMatrix_->Unregister();}
58  if(pSubShapeSpaceMatrix_!=NULL){pSubShapeSpaceMatrix_->Unregister();}
59  if(pRegMatrix_!=NULL){pRegMatrix_->Unregister();}
60 }
61 
62 
63 template <class StorageType>
66  std::vector<BIAS::BIASContour>& contour){
67 
68  BIASWARN("Unfinished!");
69  return -1;
70 }
71 
72 
73 //public:
74 template <class StorageType> ContourDetectorBSpline<StorageType>
76 Cluster(const std::vector<ContourDetectorBSpline<StorageType> >& bSplines){
77 
78  unsigned int i,j; //counter variables
79  //build new object
81 
82  //register with data objects from given B-Spline curves
83  std::vector<ContourBSplineData*> bSplineData;
84  for(i=0;i<bSplines.size();i++){
85  bSplineData.push_back(bSplines[i].pData_);
86  }
87  bSpline.pData_= ContourBSplineData::Register(bSplineData);
88 
89  //build new Q
90  unsigned int numBasePolynoms= (bSpline.pData_->numBasePolynoms_);//new
91  unsigned int splinesNumBasePolynoms;//from particular curves
92  unsigned int pos=0;
93  BIAS::Vector<double> Q(2*numBasePolynoms);
94  for(i=0;i<bSplines.size();i++){
95  splinesNumBasePolynoms=((bSplines[i]).pData_)->numBasePolynoms_;
96  for(j=0;j<splinesNumBasePolynoms;j++){
97  Q[pos+j]=((bSplines[i]).Q_)[j];
98  Q[pos+j+numBasePolynoms]=((bSplines[i]).Q_)[j+splinesNumBasePolynoms];
99  }
100  pos+=splinesNumBasePolynoms;
101  }
102  bSpline.Q_=Q;
103  return bSpline;
104 }
105 
106 ///////////////////////////////////////////////////////
107 template <class StorageType> void
109 Init(const unsigned int order,
110  const ContourBSplineType::Type bType,
111  const std::vector<unsigned int>& mPnts,
112  const std::vector<BIAS::Vector2<double> >& cPnts){
114 
115  //convert vector of control points into internal used format
116  CPntsToQ_(cPnts,Q);
117  Init(order, bType, mPnts, Q);
118 }
119 
120 ///////////////////////////////////////////////////////
121 template <class StorageType> void
123 Init(const unsigned int order,
124  const ContourBSplineType::Type bType,
125  const std::vector<BIAS::Vector2<double> >& cPnts){
126 
127  //multiplicity for all control points is 1
128  std::vector<unsigned int> mPnts(cPnts.size(),1);
130 
131  //convert vector of control points into internal used format
132  CPntsToQ_(cPnts,Q);
133  Init(order, bType, mPnts, Q);
134 }
135 
136 ///////////////////////////////////////////////////////
137 template <class StorageType> void
139 Init(const unsigned int order,
140  const ContourBSplineType::Type bType,
141  const std::vector<unsigned int>& mPnts,
142  const BIAS::Vector<double>& Q){
143 #ifdef BIAS_DEBUG
144  TestInit_(order, bType, mPnts, Q);
145 #endif
146  Q_=Q;
147  cout<<"test init done"<<endl;
148  //register data
149  pData_=ContourBSplineData::Register(order, bType, mPnts);
150  cout<<"register done"<<endl;
151  BIASCDOUT(D_CONTOURBSPLINE_INIT,"metricmatrix: " <<
152  pData_->splineMetricMatrix_ <<
153  std::endl<<std::flush);
154 }
155 
156 ///////////////////////////////////////////////////////
157 template <class StorageType> void
159 Init(const unsigned int order,
160  const ContourBSplineType::Type bType,
161  const BIAS::Vector<double>& Q){
162  //multiplicity for all control points is 1
163  std::vector<unsigned int> mPnts(Q.Size()/2,1);
164 
165  Init(order, bType, mPnts, Q);
166 }
167 ///////////////////////////////////////////////////
168 template <class StorageType> void
171  unsigned int i; //counter variable
172  unsigned int numBasePolynoms = pData_->numBasePolynoms_;
173  unsigned int order = pData_->order_;
174  unsigned int numSpans = pData_->numSpans_;
175 
176  // split control point vector into Qx and Qy
177  BIAS::Matrix<double> Qx(numBasePolynoms,1);
178  BIAS::Matrix<double> Qy(numBasePolynoms,1);
179  for(i=0;i<numBasePolynoms;i++){
180  Qx[i][0]=Q_[i];
181  Qy[i][0]=Q_[i+numBasePolynoms];
182  }
183 
184  curveVectors_.clear();
185 
186  //using equation on p.292 ("active contours") to compute coeff vectors
187  std::vector<BIAS::Vector<double> > tmpBin(2);
188  BIAS::Vector<double> tmpVecX(order);
189  BIAS::Vector<double> tmpVecY(order);
190  BIAS::Matrix<double> tmpMat(numBasePolynoms,1);
191  for(i=0;i<numSpans;i++){
192  //x part
193  tmpMat=Qx;
194  tmpMat.MultLeft((pData_->placedSpanMatrices_)[i]);
195  tmpVecX=tmpMat.GetCol(0);
196  //y part
197  tmpMat=Qy;
198  tmpMat.MultLeft((pData_->placedSpanMatrices_)[i]);
199  tmpVecY=tmpMat.GetCol(0);
200 
201  tmpBin[0]=tmpVecX;
202  tmpBin[1]=tmpVecY;
203  curveVectors_.push_back(tmpBin);
204  }
205  curveInitialised_=true;
206 }
207 ///////////////////////////////////////////////////
208 template <class StorageType> void
211  const double& alpha, const unsigned int normalWidth){
212  //possibly init curve vectors
213  if(!curveInitialised_){ InitCurve_(); }
214 
215  //build gradient image with ROI
216  BIAS::Image<float> featImg;
217  GetFeatImage_(greyImg, featImg, normalWidth);
218 
219  Fit_(featImg, alpha, normalWidth);
220 }
221 
222 ///////////////////////////////////////////////////
223 template <class StorageType> void
226  const double& alpha, const unsigned int normalWidth,
227  const double& minClip){
228  //possibly init curve vectors
229  if(!curveInitialised_){ InitCurve_(); }
230 
231  //build gradient image with ROI
232  BIAS::Image<float> featImg;
233  GetFeatImage_(greyImg, featImg, normalWidth);
234 
235  Fit_(featImg, alpha, normalWidth, minClip);
236 }
237 
238 ///////////////////////////////////////////////////
239 template <class StorageType> void
241 Fit(const BIAS::Image<float>& featImg,
242  const double& alpha, const unsigned int normalWidth){
243  //possibly init curve vectors
244  if(!curveInitialised_){ InitCurve_(); }
245  Fit_(featImg, alpha, normalWidth);
246 }
247 
248 ///////////////////////////////////////////////////
249 template <class StorageType> void
251 Fit(const BIAS::Image<float>& featImg,
252  const double& alpha, const unsigned int normalWidth,
253  const double& minClip){
254  if(!curveInitialised_){ InitCurve_(); }
255  Fit_(featImg, alpha, normalWidth, minClip);
256 }
257 
258 ///////////////////////////////////////////////////
259 template <class StorageType> bool
261 Save(const std::string& filename){
262  unsigned int i,j,k; //counter variables
263 
264  std::ofstream fs;
265  fs.open(filename.c_str(), std::ofstream::out | std::ofstream::binary);
266  if(!fs.is_open())return false;
267 
268  //store order
269  fs.write( (char*) &(pData_->order_), sizeof(unsigned int) );
270 
271  //store BSpline type
272  fs.write( (char*) &(pData_->bType_), sizeof(ContourBSplineType::Type) );
273 
274  //store size of multiplicity and controlpoint vector (=numBasePolynoms)
275  fs.write( (char*) &(pData_->numBasePolynoms_), sizeof(unsigned int) );
276 
277  //store multiplicity vector
278  for(i=0;i<(pData_->numBasePolynoms_);i++){
279  fs.write( (char*) &((pData_->mPnts_)[i]), sizeof(unsigned int) );
280  }
281 
282  //store controlpoint vector (plain)
283  for(i=0;i<2*(pData_->numBasePolynoms_);i++){
284  fs.write( (char*) &(Q_[i]), sizeof(double) );
285  }
286 
287  //for clustered curve there is more to save (numSpans & placedSpanMatrices)
288  if(pData_->bType_==ContourBSplineType::Cluster){
289  //store numSpans
290  fs.write( (char*) &(pData_->numSpans_), sizeof(unsigned int) );
291 
292  //store placedSpanMatrices
293  for(i=0;i<pData_->numSpans_;i++){
294  for(j=0;j<pData_->order_;j++){
295  for(k=0;k<pData_->numBasePolynoms_;k++){
296  fs.write( (char*) &((pData_->placedSpanMatrices_)[i][j][k]),
297  sizeof(double) );
298  }
299  }
300  }
301  //store numSpansVec size
302  unsigned int numSpansVecSize=(pData_->numSpansVec_).size();
303  fs.write( (char*) &numSpansVecSize, sizeof(unsigned int) );
304 
305  //store numSpansVec
306  for(i=0;i<numSpansVecSize;i++){
307  fs.write( (char*) &((pData_->numSpansVec_)[i]), sizeof(unsigned int) );
308  }
309  }
310 
311  //close filestream
312  fs.close();
313  return true;
314 }
315 
316 ///////////////////////////////////////////////////
317 template <class StorageType> bool
319 Load(const std::string& filename){
320  unsigned int i,j,k; //counter variables
321 
322  std::ifstream fs;
323  fs.open(filename.c_str(), std::ifstream::in | std::ifstream::binary);
324  if(!fs.is_open()){
325  return false;
326  }
327  //load order
328  unsigned int order;
329  fs.read( (char*) &order, sizeof(unsigned int) );
330 
331  //load BSpline type
333  fs.read( (char*) &bType, sizeof(ContourBSplineType::Type) );
334 
335  //load num of base polynoms
336  unsigned int numBasePolynoms;
337  fs.read( (char*) &numBasePolynoms, sizeof(unsigned int) );
338 
339  //load multiplicity vector
340  std::vector<unsigned int> mPnts(numBasePolynoms);
341  for(i=0; i<numBasePolynoms; i++){
342  fs.read( (char*) &mPnts[i], sizeof(unsigned int) );
343  }
344 
345  //load controlpoint vector (plain)
346  BIAS::Vector<double> Q(2*numBasePolynoms);
347  for(i=0; i<2*numBasePolynoms; i++){
348  fs.read( (char*) &Q[i], sizeof(double) );
349  }
350 
351  //if we have a Cluster BSpline ... there is more to load
352  if(bType==ContourBSplineType::Cluster){
353  //load numSpans
354  unsigned int numSpans;
355 
356  fs.read( (char*) &numSpans, sizeof(unsigned int) );
357 
358  //load placedSpanMatrices
359  std::vector<BIAS::Matrix<double> > placedSpanMatrices;
360  BIAS::Matrix<double> placedSpanMatrix(order,numBasePolynoms);
361  for(i=0;i<numSpans;i++){
362  for(j=0;j<order;j++){
363  for(k=0;k<numBasePolynoms;k++){
364  fs.read( (char*) &(placedSpanMatrix[j][k]), sizeof(double) );
365  }
366  }
367  placedSpanMatrices.push_back(placedSpanMatrix);
368  }
369 
370  //load numSpansVec size
371  unsigned int numSpansVecSize;
372  fs.read( (char*) &numSpansVecSize, sizeof(unsigned int) );
373 
374  //load numSpansVec
375  std::vector<unsigned int> numSpansVec(numSpansVecSize);
376  for(i=0;i<numSpansVecSize;i++){
377  fs.read( (char*) &(numSpansVec[i]), sizeof(unsigned int) );
378  }
379 
380  //build up bSpline
381  Q_=Q;
382  pData_=ContourBSplineData::Register(order, bType, mPnts, numBasePolynoms,
383  numSpans, numSpansVec,
384  placedSpanMatrices);
385 
386  }else{
387  //build up bSpline (normal case)
388  Init(order, bType, mPnts, Q);
389  }
390 
391  //close filestream
392  fs.close();
393 
394  return true;
395 }
396 /////////////////////////////////////////////////////////
397 template <class StorageType> void
399 Rotate(const double& angle){
400  //curve must have its center at zero
401  unsigned int i; //counter variable
402 
403  BIAS::Vector2<double> tmp,tmp2;
404  BIAS::Matrix2x2<double> rot;//rotation matrix
405  rot[0][0]=cos(angle);
406  rot[0][1]=-sin(angle);
407  rot[1][0]=sin(angle);
408  rot[1][1]=cos(angle);
409  for(i=0;i<pData_->numBasePolynoms_;i++){
410  tmp[0]=Q_[i];
411  tmp[1]=Q_[i+(pData_->numBasePolynoms_)];
412  rot.Mult(tmp,tmp2);
413  Q_[i]=tmp2[0];
414  Q_[i+(pData_->numBasePolynoms_)]=tmp2[1];
415  }
416 }
417 
418 template <class StorageType> void
420 GetPoint(const double& t, BIAS::Vector2<double>& res){
421  if(!curveInitialised_){ InitCurve_(); }
422  unsigned int span;
423  unsigned int numSpans= pData_->numSpans_;
424  double s;
425  BIAS::Vector<double> sVec(pData_->order_); //curve parametric vector
426 
427  //compute which span to use and convert t regarding span
428  if(t<=0.){
429  span=0;
430  s=0.;
431  }
432  else if(t>=1.){
433  span=numSpans-1;
434  s=1.;
435  }
436  else{
437  span = (unsigned int) (t * (double)(numSpans));
438  s= (t*numSpans) - span;
439  }
440 
441  //finaly get point
442  GetPointAndParamVec_(span,s,sVec,res);
443 }
444 
445 /////////////////////////////////////////////////////////
446 template <class StorageType> void
448 GetNormal(const double& t, BIAS::Vector2<double>& res){
449  if(!curveInitialised_){ InitCurve_();}
450 
451  unsigned int span;
452  unsigned int numSpans=pData_->numSpans_;
453  double s;
454 
455  //compute which span to use and convert t regarding span
456  if(t<=0.){
457  span=0;
458  s=0.;
459  }
460  else if(t>=1.){
461  span=numSpans-1;
462  s=1.;
463  }
464  else{
465  span = (unsigned int) (t * (double)(numSpans) );
466  s= (t*numSpans) - span;
467  }
468 
469  //finaly get normal
470  GetNormal_(span,s,res);
471 }
472 
473 /////////////////////////////////////////////////////////
474 template <class StorageType> void
477  const double& t,
478  const unsigned int normalWidth,
479  BIAS::Vector2<double>& res){
480  //convert input image into gradient image with ROI
481  BIAS::Image<float> featImg;
482  GetFeatImage_(greyImg,featImg,normalWidth);
483 
484  //finally get feature point
485  GetFeature(featImg, t, normalWidth, res);
486 }
487 
488 /////////////////////////////////////////////////////////
489 template <class StorageType> void
492  const double& t,
493  const unsigned int normalWidth,
494  const double& minClip,
495  BIAS::Vector2<double>& res){
496  //convert input image into gradient image
497  BIAS::Image<float> featImg;
498  GetFeatImage_(greyImg,featImg,normalWidth);
499 
500  //finally get feature point
501  GetFeature(featImg, t, normalWidth, minClip, res);
502 }
503 
504 /////////////////////////////////////////////////////////
505 template <class StorageType> void
508  const double& t,
509  const unsigned int normalWidth,
510  BIAS::Vector2<double>& res){
511  //possibly initialise curve vectors
512  if(!curveInitialised_){ InitCurve_(); }
513 
514  unsigned int span; //current span
515  unsigned int numSpans=pData_->numSpans_;
516  double s;
517 
518  //compute which span to use and convert t regarding span
519  if(t<=0.){
520  span=0;
521  s=0.;
522  }
523  else if(t>=1.){
524  span=numSpans-1;
525  s=1.;
526  }
527  else{
528  span = (unsigned int) (t * (double)(numSpans) );
529  s= (t*numSpans) - span;
530  }
531 
532  BIAS::Vector2<double> curvePnt;
533  BIAS::Vector2<double> normal;
534  //compute curve point at t
535  GetPoint_(span,s,curvePnt);
536  //compute normal at t
537  GetNormal_(span,s,normal);
538  //finally get feature point
539  GetFeature(featImg, normalWidth, curvePnt, normal, res);
540 }
541 
542 /////////////////////////////////////////////////////////
543 template <class StorageType> void
546  const double& t,
547  const unsigned int normalWidth,
548  const double& minClip,
549  BIAS::Vector2<double>& res){
550  //possibly initialise curve vectors
551  if(!curveInitialised_){ InitCurve_(); }
552 
553  unsigned int span;
554  unsigned int numSpans=pData_->numSpans_;
555  double s;
556 
557  //compute which span to use and convert t regarding span
558  if(t<=0.){
559  span=0;
560  s=0.;
561  }
562  else if(t>=1.){
563  span=numSpans-1;
564  s=1.;
565  }
566  else{
567  span = (unsigned int) (t * (double)(numSpans) );
568  s= (t*numSpans) - span;
569  }
570  BIAS::Vector2<double> curvePnt;
571  BIAS::Vector2<double> normal;
572  //compute curve point at t
573  GetPoint_(span,s,curvePnt);
574  //compute normal at t
575  GetNormal_(span,s,normal);
576  //finally get feature point at t
577  GetFeature(featImg, normalWidth, curvePnt, normal, minClip, res);
578 }
579 
580 /////////////////////////////////////////////////////////
581 template <class StorageType> void
583 GetBoundingBox(int& minX, int& minY,
584  int& maxX, int& maxY){
585  unsigned int i; //counter variable
586  unsigned int offset = Q_.size()/2;
587  int tmpX, tmpY;
588 
589  minX=(int) (Q_[0]+0.5);
590  maxX=(int) (Q_[0]+0.5);
591  minY=(int) (Q_[offset]+0.5);
592  maxY=(int) (Q_[offset]+0.5);
593 
594  for(i=1;i<offset;i++){
595  tmpX=(int) (Q_[i]+0.5);
596  tmpY=(int) (Q_[offset+i]+0.5);
597  if(tmpX < minX){
598  minX=tmpX;
599  }
600  else if(tmpX > maxX){
601  maxX=tmpX;
602  }
603  if(tmpY < minY){
604  minY=tmpY;
605  }
606  else if(tmpY > maxY){
607  maxY=tmpY;
608  }
609  }
610  BIASCDOUT(D_CONTOURBSPLINE_BOUNDINGBOX, "BSplines Bounding Box is: (" <<
611  minX << "," << minY << ") (" << maxX << "," << maxY <<")." << std::endl <<
612  std::flush);
613 }
614 
615 /////////////////////////////////////////////////////////
616 template <class StorageType> void
619  const StorageType color[3]){
620  unsigned int i; //counter variable
621 
622 
623  for(i=0; i<pData_->numBasePolynoms_;i++){
625  (unsigned int)Q_[i],
626  (unsigned int)Q_[i+pData_->numBasePolynoms_],
627  2, color);
628  }
629 }
630 
631 /////////////////////////////////////////////////////////
632 template <class StorageType> void
635  const StorageType color[3]){
636  if(!curveInitialised_){ InitCurve_(); }
637 
638  unsigned int i,j; //counter variable
639  double t; //counter variable
640 
641  BIAS::Vector2<double> first;
642  BIAS::Vector2<double> second;
643 
644  //convert sampleOffset_ relative to span
645  double d = *drawSampleWidth_ * (double)pData_->numSpans_;
646  unsigned int offset=0;
647 
648  for(i=0;i<(pData_->numSpansVec_).size();i++){
649  GetPoint_(offset,0.,first);
650  for(j=offset;j<((pData_->numSpansVec_)[i]+offset);j++){
651  for(t=0.;t<(1.+d);t+=d){
652  (t>1.)? GetPoint_(j,1,second):GetPoint_(j,t,second);
654  (unsigned int)first[0],
655  (unsigned int)first[1],
656  (unsigned int)second[0],
657  (unsigned int)second[1],
658  color);
659  first=second;
660  }
661  }
662  offset+=(pData_->numSpansVec_)[i];
663  }
664 }
665 
666 /////////////////////////////////////////////////////////
667 template <class StorageType> void
670  if(!curveInitialised_){ InitCurve_(); }
671 
672  unsigned int i,j; //counter variable
673  double t; //counter variable
674  float color[1]={255.};
675 
676  BIAS::Vector2<double> first;
677  BIAS::Vector2<double> second;
678 
679  //convert sampleOffset_ relative to span
680  double d = *drawSampleWidth_ * (double)pData_->numSpans_;
681  unsigned int offset=0;
682 
683  for(i=0;i<(pData_->numSpansVec_).size();i++){
684  GetPoint_(offset,0.,first);
685  for(j=offset;j<((pData_->numSpansVec_)[i]+offset);j++){
686  for(t=0.;t<(1.+d);t+=d){
687  (t>1.)? GetPoint_(j,1,second):GetPoint_(j,t,second);
689  (unsigned int)first[0],
690  (unsigned int)first[1],
691  (unsigned int)second[0],
692  (unsigned int)second[1],
693  color);
694  first=second;
695  }
696  }
697  offset+=(pData_->numSpansVec_)[i];
698  }
699 }
700 
701 /////////////////////////////////////////////////////////
702 template <class StorageType> void
704 DrawNormals(const unsigned int normalWidth,
706  const StorageType color[3]){
707  if(!curveInitialised_){ InitCurve_(); }
708  unsigned int i;//counter variable
709  double t; //counter variable
710 
711  unsigned int numSpans=pData_->numSpans_;
712 
713  BIAS::Vector2<double> curvePnt;
714  BIAS::Vector2<double> normal;
715 
716  //convert sampleOffset_ relative to span
717  double d = *fitSampleWidth_ * (double) numSpans;
718 
719  for(i=0;i<numSpans;i++){
720  for(t=0.;t<1.+d;t+=d){
721  if(t>1.){
722  GetPoint_(i,1.,curvePnt);
723  GetNormal_(i,1.,normal);
724  }else{
725  GetPoint_(i,t,curvePnt);
726  GetNormal_(i,t,normal);
727  }
729  (unsigned int)curvePnt[0],
730  (unsigned int)curvePnt[1],
731  (unsigned int)(curvePnt[0]+
732  (double)normalWidth*normal[0]),
733  (unsigned int)(curvePnt[1]+
734  (double)normalWidth*normal[1]),
735  color);
736 
738  (unsigned int) curvePnt[0],
739  (unsigned int) curvePnt[1],
740  (unsigned int)(curvePnt[0]-
741  (double)normalWidth*normal[0]),
742  (unsigned int)(curvePnt[1]-
743  (double)normalWidth*normal[1]),
744  color);
745  }
746  }
747 }
748 
749 //protected:
750 
751 /////////////////////////////////////////////////////////
752 template <class StorageType> void
754 CPntsToQ_(const std::vector<BIAS::Vector2<double> >& cPnts){
755  unsigned int i; //counter variable
756  Q_.newsize(2*cPnts.size());
757 
758  for(i=0;i<cPnts.size();i++){
759  Q_[i]=cPnts[i][0];
760  Q_[i+cPnts.size()]=cPnts[i][1];
761  }
762 }
763 
764 /////////////////////////////////////////////////////////
765 template <class StorageType> void
767 CPntsToQ_(const std::vector<BIAS::Vector2<double> >& cPnts,
769  unsigned int i; //counter variable
770  Q.newsize(2*cPnts.size());
771 
772  for(i=0;i<cPnts.size();i++){
773  Q[i]=cPnts[i][0];
774  Q[i+cPnts.size()]=cPnts[i][1];
775  }
776 }
777 
778 /////////////////////////////////////////////////////////
779 template <class StorageType> void
781 QToCPnts_(std::vector<BIAS::Vector2<double> >& cPnts){
782  unsigned int i; //counter variable
783  cPnts.resize(Q_.size()/2);
784  for(i=0;i<cPnts.size();i++){
785  cPnts[i][0]=Q_[i];
786  cPnts[i][1]=Q_[i+cPnts.size()];
787  }
788 }
789 
790 /////////////////////////////////////////////////////////
791 template <class StorageType> void
794  std::vector<BIAS::Vector2<double> >& cPnts){
795  unsigned int i; //counter variable
796  cPnts.resize(Q.size()/2);
797  for(i=0;i<cPnts.size();i++){
798  cPnts[i][0]=Q[i];
799  cPnts[i][1]=Q[i+cPnts.size()];
800  }
801 }
802 
803 /////////////////////////////////////////////////////////
804 template <class StorageType> void
806 GetPointAndParamVec_(const unsigned int span,
807  const double& s,
808  BIAS::Vector<double>& resParamVec,
809  BIAS::Vector2<double>& resPoint){
810  unsigned int i,j; //loop variables
811 
812  unsigned int order=pData_->order_;
813 
814  //build sVec (parametric vector for computation of U matrix)
815  resParamVec.newsize(order);
816  resParamVec[0] = 1.;
817  resParamVec[1] = s;
818  resParamVec[2] = s*s;
819  double tmpS;
820  for(i=3;i<order;i++){ //only go through loops if order>3
821  tmpS=s;
822  for(j=0;j<(i-1);j++){
823  tmpS*=s;
824  }
825  resParamVec[i]=tmpS;
826  }
827  //compute result point
828  resPoint[0]=resParamVec.ScalarProduct(curveVectors_[span][0]);
829  resPoint[1]=resParamVec.ScalarProduct(curveVectors_[span][1]);
830 }
831 
832 /////////////////////////////////////////////////////////
833 template <class StorageType> void
835 GetNormal_(const unsigned int span, const double& s,
836  BIAS::Vector2<double>& res){
837  unsigned int i,j; //loop variables
838 
839  unsigned int order = pData_->order_;
840 
841  //build sVec (parametric vector for computation)
842  BIAS::Vector<double>sVec(order);
843  sVec[0]=0.;
844  sVec[1]=1.;
845  sVec[2]=2*s;
846  double tmpS;
847  for(i=3;i<order;i++){ //only go through loops if order>3
848  tmpS=s;
849  for(j=0;j<(i-2);j++){
850  tmpS*=s;
851  }
852  tmpS*=i;
853  sVec[i]=tmpS;
854  }
855 
856  //compute result point
857  res[0]=-sVec.ScalarProduct(curveVectors_[span][1]);
858  res[1]= sVec.ScalarProduct(curveVectors_[span][0]);
859 
860  //normalise
861  double length=res.NormL2();
862  res[0]/=length;
863  res[1]/=length;
864 }
865 
866 /////////////////////////////////////////////////////////
867 template <class StorageType> void
870  const unsigned int normalWidth,
871  const BIAS::Vector2<double>& curvePnt,
872  const BIAS::Vector2<double>& normal,
873  BIAS::Vector2<double>& res){
874  unsigned int i;//counter variable
875 
876  //nothing found
877  res[0]=curvePnt[0];
878  res[1]=curvePnt[1];
879 
880  float maxInt; //intensity
881  float tmpInt;
882 
883  //check curvePnt
884  if((curvePnt[0])<0 || (curvePnt[1]<0) || (curvePnt[0]>featImg.GetWidth()) ||
885  (curvePnt[1]>featImg.GetHeight()) ){
886  return;
887  }
888  maxInt = featImg.PixelValue((unsigned int)(curvePnt[0]+0.5),
889  (unsigned int)(curvePnt[1]+0.5));
890 
891  for(i=1;i<normalWidth; i++){
892  //search outer region for change in pixelvalue
893  int x = (int)(curvePnt[0]+(double)i*normal[0]+0.5);
894  int y = (int)(curvePnt[1]+(double)i*normal[1]+0.5);
895 
896  if(x<(int)featImg.GetWidth() && y<(int)featImg.GetHeight() && x>=0 && y>=0){ //check img border
897  tmpInt = featImg.PixelValue(x,y);
898  if(tmpInt>maxInt){
899  maxInt=tmpInt;
900  res[0]=curvePnt[0]+(double)i*normal[0];
901  res[1]=curvePnt[1]+(double)i*normal[1];
902  }
903  }
904 
905  //search inner region for change in pixelvalue
906  x = (int)(curvePnt[0]-(double)i*normal[0]+0.5);
907  y = (int)(curvePnt[1]-(double)i*normal[1]+0.5);
908  if(x<(int)featImg.GetWidth() && y<(int)featImg.GetHeight() && x>=0 && y>=0){
909  tmpInt = featImg.PixelValue(x,y);
910  if(tmpInt>maxInt){
911  maxInt=tmpInt;
912  res[0]=curvePnt[0]-(double)i*normal[0];
913  res[1]=curvePnt[1]-(double)i*normal[1];
914  }
915  }
916  }
917 }
918 
919 /////////////////////////////////////////////////////////
920 template <class StorageType> void
923  const unsigned int normalWidth,
924  const BIAS::Vector2<double>& curvePnt,
925  const BIAS::Vector2<double>& normal,
926  const double& minClip,
927  BIAS::Vector2<double>& res){
928  unsigned int i;//counter variable
929 
930  //nothing found
931  res[0]=curvePnt[0];
932  res[1]=curvePnt[1];
933 
934  float maxInt; //intensity
935  float tmpInt;
936 
937  //check curvePnt
938  if((curvePnt[0])<0 || (curvePnt[1]<0) || (curvePnt[0]>featImg.GetWidth()) ||
939  (curvePnt[1]>featImg.GetHeight()) ){
940  return;
941  }
942  maxInt = featImg.PixelValue((unsigned int)(curvePnt[0]+0.5),
943  (unsigned int)(curvePnt[1]+0.5));
944 
945  for(i=1;i<normalWidth; i++){
946  //search outer region for change in pixelvalue
947  int x = (int)(curvePnt[0]+(double)i*normal[0]+0.5);
948  int y = (int)(curvePnt[1]+(double)i*normal[1]+0.5);
949 
950  if(x<(int)featImg.GetWidth() && y<(int)featImg.GetHeight() && x>=0 && y>=0){ //check img border
951  tmpInt = featImg.PixelValue(x,y);
952  if(tmpInt>maxInt && tmpInt>=minClip){
953  maxInt=tmpInt;
954  res[0]=curvePnt[0]+(double)i*normal[0];
955  res[1]=curvePnt[1]+(double)i*normal[1];
956  }
957  }
958 
959  //search inner region for change in pixelvalue
960  x = (int)(curvePnt[0]-(double)i*normal[0]+0.5);
961  y = (int)(curvePnt[1]-(double)i*normal[1]+0.5);
962  if(x<(int)featImg.GetWidth() && y<(int)featImg.GetHeight() && x>=0 && y>=0){
963  tmpInt = featImg.PixelValue(x,y);
964  if(tmpInt>maxInt && tmpInt>=minClip){
965  maxInt=tmpInt;
966  res[0]=curvePnt[0]-(double)i*normal[0];
967  res[1]=curvePnt[1]-(double)i*normal[1];
968  }
969  }
970  }
971 }
972 
973 
974 /////////////////////////////////////////////////////////
975 template <class StorageType> void
977 Fit_(const BIAS::Image<float>& featImg, const double& alpha, const unsigned int normalWidth){
978  unsigned int i; //counter variables
979  double t; //counter variable
980 
981  unsigned int span;
982  unsigned int numSpans=pData_->numSpans_;
983  unsigned int numBasePolynoms=pData_->numBasePolynoms_;
984  double s;
985 
986  BIAS::Vector2<double> curvePnt; //point on BSpline at time t
987  BIAS::Vector2<double> normal; //normal at time t
988  BIAS::Vector2<double> featPnt; //feature point at time t determined by filter
989 
990  BIAS::Vector<double> sVec(pData_->order_); //curve param vector at time t
991 
992  /*
993  * initialise Z_0 (?observation vector?) and
994  * S_0 (?statistical information matrix?)
995  */
996  unsigned int size=pShapeSpaceMatrix_->num_cols();
997  BIAS::Vector<double> Z(size);
998  BIAS::Matrix<double> S(size,size);
999  BIAS::Matrix<double> tmpS(size, size);
1000  Z.SetZero();
1001  S.SetZero();
1002 
1003  //iteration step (core of algorithm)
1004  for(t=0.; t<(1.+*fitSampleWidth_); t+=*fitSampleWidth_){
1005 
1006  /*
1007  * use filter to find new position at time t
1008  * - get span at time t
1009  * - convert t(->s) relative to span
1010  * - get point and normal at time t
1011  * - get feature point
1012  */
1013  if(t<=0.){
1014  span=0;
1015  s=0.;
1016  }
1017  else if(t>=1.){
1018  span=numSpans-1;
1019  s=1.;
1020  }
1021  else{
1022  span = (unsigned int) (t * (double)(numSpans) );
1023  s= (t*(double)numSpans) - (double)span;
1024  }
1025  GetPointAndParamVec_(span,s,sVec,curvePnt);
1026  GetNormal_(span,s,normal);
1027  GetFeature(featImg, normalWidth, curvePnt, normal, featPnt);
1028 
1029  //1. compute v_i
1030  double v = (featPnt-curvePnt).ScalarProduct(normal);
1031 
1032  //2. compute h(si)^T
1033  BIAS::Vector<double> h(size);
1034 
1035  //2.1 compute U(si)
1036  BIAS::Vector<double> B(numBasePolynoms);
1037  (pData_->placedSpanMatrices_)[span].MultLeft(sVec, B);
1038 
1039  BIAS::Matrix<double> U(2,2*numBasePolynoms);
1040  U.SetZero();
1041  for(i=0;i<numBasePolynoms;i++){
1042  U[0][i]=B[i];
1043  U[1][i+numBasePolynoms]=B[i];
1044  }
1045  U.Mult(*pShapeSpaceMatrix_); //inplace multiplication!!!
1046  U.MultLeft(normal, h);//h(si)
1047 
1048  //3. update S
1049  S=S+((1./(double)fitSamples_)* h.OuterProduct(h));//TODO "measurement error"
1050 
1051  //4. update Z
1052  Z=Z+(((1./(double)fitSamples_)*v)*h);
1053  }
1054 
1055  //update control points
1056  BIAS::Matrix<double> regMat;
1057  pRegMatrix_->Multiply(alpha, regMat);
1058  BIAS::SVD superS(regMat+S);
1059  BIASCDOUT(D_CONTOURBSPLINE_FIT, "old Q_" << Q_ << std::endl << std::flush);
1060  Q_=*pShapeSpaceMatrix_*(superS.Invert()*Z) + Q_;
1061  BIASCDOUT(D_CONTOURBSPLINE_FIT, "new Q_" << Q_ << std::endl << std::flush);
1062  BIASCDOUT(D_CONTOURBSPLINE_FIT, "S^-: " << pRegMatrix_ << std::endl << std::flush);
1063  BIASCDOUT(D_CONTOURBSPLINE_FIT, "S: " << S << std::endl << std::flush);
1064  BIASCDOUT(D_CONTOURBSPLINE_FIT, "(S+S^-)^-1: " << superS.Invert() << std::flush);
1065  BIASCDOUT(D_CONTOURBSPLINE_FIT, "Z: " << Z << std::endl << std::flush);
1066 
1067  //through update of the control points the curveVectors_ aren't valid anymore
1068  curveInitialised_=false;
1069 }
1070 
1071 /////////////////////////////////////////////////////////
1072 template <class StorageType> void
1074 Fit_(const BIAS::Image<float>& featImg, const double& alpha,
1075  const unsigned int normalWidth, const double& minClip){
1076  unsigned int i; //counter variables
1077  double t; //counter variable
1078 
1079  unsigned int span;
1080  unsigned int numSpans=pData_->numSpans_;
1081  unsigned int numBasePolynoms=pData_->numBasePolynoms_;
1082  double s;
1083 
1084  BIAS::Vector2<double> curvePnt; //point on BSpline at time t
1085  BIAS::Vector2<double> normal; //normal at time t
1086  BIAS::Vector2<double> featPnt; //feature point at time t determined by filter
1087 
1088  BIAS::Vector<double> sVec(pData_->order_); //curve param vector at time t
1089 
1090  /*
1091  * initialise Z_0 (?observation vector?) and
1092  * S_0 (?statistical information matrix?)
1093  */
1094  unsigned int size=pShapeSpaceMatrix_->num_cols();
1095  BIAS::Vector<double> Z(size);
1096  BIAS::Matrix<double> S(size,size);
1097  BIAS::Matrix<double> tmpS(size, size);
1098  Z.SetZero();
1099  S.SetZero();
1100 
1101  //iteration step (core of algorithm)
1102  for(t=0.; t<(1.+*fitSampleWidth_); t+=*fitSampleWidth_){
1103 
1104  /*
1105  * use filter to find new position at time t
1106  * - get span at time t
1107  * - convert t(->s) relative to span
1108  * - get point and normal at time t
1109  * - get feature point
1110  */
1111  if(t<=0.){
1112  span=0;
1113  s=0.;
1114  }
1115  else if(t>=1.){
1116  span=numSpans-1;
1117  s=1.;
1118  }
1119  else{
1120  span = (unsigned int) (t * (double)(numSpans) );
1121  s= (t*(double)numSpans) - (double)span;
1122  }
1123  GetPointAndParamVec_(span,s,sVec,curvePnt);
1124  GetNormal_(span,s,normal);
1125  GetFeature(featImg, normalWidth, curvePnt, normal, minClip, featPnt);
1126 
1127  //1. compute v_i
1128  double v = (featPnt-curvePnt).ScalarProduct(normal);
1129 
1130  //2. compute h(si)^T
1131  BIAS::Vector<double> h(size);
1132 
1133  //2.1 compute U(si)
1134  BIAS::Vector<double> B(numBasePolynoms);
1135  (pData_->placedSpanMatrices_)[span].MultLeft(sVec, B);
1136 
1137  BIAS::Matrix<double> U(2,2*numBasePolynoms);
1138  U.SetZero();
1139  for(i=0;i<numBasePolynoms;i++){
1140  U[0][i]=B[i];
1141  U[1][i+numBasePolynoms]=B[i];
1142  }
1143  U.Mult(*pShapeSpaceMatrix_); //inplace multiplication!!!
1144  U.MultLeft(normal, h);//h(si)
1145 
1146  //3. update S
1147  S=S+((1./(double)fitSamples_)* h.OuterProduct(h));//TODO "measurement error"
1148 
1149  //4. update Z
1150  Z=Z+(((1./(double)fitSamples_)*v)*h);
1151  }
1152 
1153  //update control points
1154  BIAS::Matrix<double> regMat;
1155  pRegMatrix_->Multiply(alpha, regMat);
1156  BIAS::SVD superS(regMat+S);
1157  BIASCDOUT(D_CONTOURBSPLINE_FIT, "old Q_" << Q_ << std::endl << std::flush);
1158  Q_=*pShapeSpaceMatrix_*(superS.Invert()*Z) + Q_;
1159  BIASCDOUT(D_CONTOURBSPLINE_FIT, "new Q_" << Q_ << std::endl << std::flush);
1160  BIASCDOUT(D_CONTOURBSPLINE_FIT, "S^-: " << pRegMatrix_ << std::endl << std::flush);
1161  BIASCDOUT(D_CONTOURBSPLINE_FIT, "S: " << S << std::endl << std::flush);
1162  BIASCDOUT(D_CONTOURBSPLINE_FIT, "(S+S^-)^-1: " << superS.Invert() << std::flush);
1163  BIASCDOUT(D_CONTOURBSPLINE_FIT, "Z: " << Z << std::endl << std::flush);
1164 
1165  //through update of the control points the curveVectors_ aren't valid anymore
1166  curveInitialised_=false;
1167 }
1168 
1169 //private:
1170 
1171 /////////////////////////////////////////////////////////
1172 template <class StorageType> void
1175  BIAS::Image<float>& featImg,
1176  const unsigned int normalWidth){
1177  BIAS::Image<float> featX;
1178  BIAS::Image<float> featY;
1179  int minx,miny,maxx,maxy;
1180  GetBoundingBox(minx,miny,maxx,maxy);
1181  featImg.Init(greyImg.GetWidth(), greyImg.GetHeight(),
1182  greyImg.GetChannelCount());
1183  featImg.FillImageWithConstValue(0.);
1184 
1185  greyImg.SetROICorners(
1186  (minx>(int)normalWidth)? minx-normalWidth : 0,
1187  (miny>(int)normalWidth)? miny-normalWidth : 0,
1188  ((maxx+normalWidth)<greyImg.GetWidth())?
1189  maxx+normalWidth : (greyImg.GetWidth()-1),
1190  ((maxy+normalWidth)<greyImg.GetHeight())?
1191  maxy+normalWidth : (greyImg.GetHeight()-1));
1192 
1193  //filter ROI -> gradient image
1195  gsobel.Filter(greyImg,featX,featY,featImg);
1196  greyImg.UnsetROI();
1197 }
1198 
1199 
1200 
1201 #ifdef BIAS_DEBUG
1202 /////////////////////////////////////////////////////////
1203 template <class StorageType> void
1205 TestInit_(const unsigned int order,
1206  const ContourBSplineType::Type bType,
1207  const std::vector<unsigned int>& mPnts,
1208  const BIAS::Vector<double>& Q){
1209  unsigned int i; //counter variable
1210 
1211  //test equality of dimension of control points and multiplicity vector
1212  if(mPnts.size()!=Q.Size()/2){
1213  BIASERR("Dimension of control point vector and dimension of multiplicity"<<
1214  " vector for control points arent equal.\r\n");
1215  exit(EXIT_FAILURE);
1216  }
1217  //test dimenstion of control points vector
1218  if(Q.Size()/2<order){
1219  BIASERR("BSpline needs >=" << order << " control points, even if one "<<
1220  "of the control points has a multiplicity >1.\r\n");
1221  exit(EXIT_FAILURE);
1222  }
1223  //avoid real multiple control points
1224  for(i=1;i<Q.Size()/2;i++){
1225  if((Q[i]==Q[i-1]) && (Q[i+Q.size()/2]==Q[i-1+Q.size()/2])){
1226  BIASERR("Dont use real multiple control points. Pontrol point " << i <<
1227  " and " << i+1 << " are equal. This would bug the contour " <<
1228  "algorithm. Try to increase the multiplicity for the control " <<
1229  "point.\r\n");
1230  exit(EXIT_FAILURE);
1231  }
1232  }
1233 
1234  /*
1235  * aperiodic BSpline tests
1236  */
1237  if(bType==ContourBSplineType::Open){
1238  //test aperiodic case for first and last controlpoint multiplicity
1239  if(mPnts.front()>1 || mPnts.back()>1){
1240  BIASWARN("This BSpline interpolates through end points. A "<<
1241  "multiplicity for first and last control point greater 1 "<<
1242  "gets ignored.\r\n");
1243  }
1244  //test aperiodic bspline for reasonable multiplicity
1245  for(i=1;i<order-1;i++){//check front
1246  if(mPnts[i]>1){
1247  BIASERR("The first control point with multiplicity greater 1 may be "<<
1248  "control point "<< order-1 << "(begin counting with 0).\r\n");
1249  exit(EXIT_FAILURE);
1250  }
1251  }
1252  for(i=mPnts.size()-2;i>mPnts.size()-order;i--){//check back
1253  if(mPnts[i]>1){
1254  BIASERR("the last control point with multiplicity greater 1 may be " <<
1255  "control point " << mPnts.size()-order <<
1256  "(begin counting with 0).\r\n");
1257  exit(EXIT_FAILURE);
1258  }
1259  }
1260  //test aperiodic bspline for splits
1261  for(i=order-1;i<mPnts.size()-order;i++){
1262  if(mPnts[i]>=order){
1263  BIASERR("The multiplicity of control point " << i <<
1264  " (begin counting with 0) is >=" << order <<
1265  " and would thus split the B-SPline curve into parts.\r\n");
1266  exit(EXIT_FAILURE);
1267  }
1268  }
1269  }
1270 
1271  /*
1272  * periodic BSpline tests
1273  */
1274  if(bType==ContourBSplineType::Closed){
1275  //test periodic bspline for splits
1276  for(i=0;i<mPnts.size();i++){
1277  if(mPnts[i]>=order){
1278  BIASERR("The multiplicity of " << i << "th control point is " <<
1279  ">=" << order << " and would thus split the BSpline into " <<
1280  "parts.\r\n");
1281  exit(EXIT_FAILURE);
1282  }
1283  }
1284  }
1285 }
1286 #endif
1287 
1288 //////////////////////////////////////////////////////////////////////////
1289 // instantiation
1290 //////////////////////////////////////////////////////////////////////////
1291 namespace BIAS{
1293 //template class ContourDetectorBSpline<float>;
1294 
1295 // fill in instances as required
1296 #ifdef BUILD_IMAGE_INT
1297 template class ContourDetectorBSpline<int>;
1298 #endif
1299 #ifdef BUILD_IMAGE_CHAR
1300 //template class ContourDetectorBSpline<char>;
1301 #endif
1302 #ifdef BUILD_IMAGE_SHORT
1303 #endif
1304 #ifdef BUILD_IMAGE_USHORT
1306 #endif
1307 #ifdef BUILD_IMAGE_UINT
1308 #endif
1309 #ifdef BUILD_IMAGE_DOUBLE
1310 #endif
1311 }
T ScalarProduct(const Vector< T > &argvec) const
scalar product (inner product) of two vectors returning a scalr
Definition: Vector.hh:355
void InitCurve_()
initializes curve for drawing or for getting points on it
void GetFeature(BIAS::Image< StorageType > &greyImg, const double &t, const unsigned int normalWidth, BIAS::Vector2< double > &res)
returns the feature point with highest gradient along the normal in curve point located at &quot;t&quot; ...
void GetNormal(const double &t, BIAS::Vector2< double > &res)
returns normal in curve point
void GetFeatImage_(BIAS::Image< StorageType > &greyImg, BIAS::Image< float > &featImg, const unsigned int normalWidth)
converts given grey image to gradient image with ROI
computes and holds the singular value decomposition of a rectangular (not necessarily quadratic) Matr...
Definition: SVD.hh:92
void GetPoint(const double &t, BIAS::Vector2< double > &res)
returns point on the curve
ContourBSplineData * pData_
pointer to data of B-Spline curve initialised by call of Init(...)
bool Load(const std::string &filename)
load/initialise a ContourBSpline object from an given binary file
Vector< T > GetCol(const int &col) const
return a copy of column &quot;col&quot;, zero based counting
Definition: Matrix.cpp:252
static int CircleCenterFilled(Image< StorageType > &im, unsigned int CenterX, unsigned int CenterY, unsigned int Radius, const StorageType Value[])
draws a filled circle using Value
Definition: ImageDraw.cpp:1023
void Mult(const Vector2< T > &argvec, Vector2< T > &destvec) const
matrix - vector multiplicate this matrix with Vector2, storing the result in destvec calculates: dest...
Definition: Matrix2x2.hh:228
gradient calculation with sobel 3 by 3 masks
unsigned int Size() const
length of the vector
Definition: Vector.hh:143
void GetPointAndParamVec_(const unsigned int numSpan, const double &s, BIAS::Vector< double > &resParamVec, BIAS::Vector2< double > &res)
computes a point on curve and a parameter vector (byproduct) which can be used for computing a specia...
unsigned int GetWidth() const
Definition: ImageBase.hh:312
void SetZero()
equivalent to matrix call
Definition: Vector.hh:156
StorageType PixelValue(const unsigned int x, const unsigned int y, const unsigned short int channel=0) const
Returns value of pixel at specific position, using specific channel as offset.
Definition: Image.hh:91
void DrawCurve(BIAS::Image< StorageType > &img, const StorageType color[3])
draws B-Spline curve into image
unsigned int numBasePolynoms_
number of base polynoms of curve - equal to number of control points
void Init(const unsigned int order, const ContourBSplineType::Type bType, const std::vector< BIAS::Vector2< double > > &cPnts)
initialisation function for simple curve without edges
void DrawControlPoints(BIAS::Image< StorageType > &img, const StorageType color[3])
draws the control points of the B-Spline curve into image
virtual void clear()
stl conform interface destroys Matrix JW
Definition: Matrix.hh:534
int Detect(Image< StorageType > &image, std::vector< BIAS::BIASContour > &contour)
detect function, unfinished
Vector< T > & newsize(Subscript N)
Definition: vec.h:220
void GetNormal_(const unsigned int numSpan, const double &s, BIAS::Vector2< double > &res)
computes a normal at curve point which is parametrized by &quot;numSpan&quot; and &quot;s&quot;
BIAS::Vector< double > Q_
vector of control points; first entries are x-coordinates; last entries are y-coordinates ...
static ContourBSplineData * Register(const unsigned int order, const ContourBSplineType::Type bType, const std::vector< unsigned int > &mPnts)
registers a ContourBSpline object and returns pointer to its data object
Matrix< T > OuterProduct(const Vector< T > &v) const
outer product, constructs a matrix.
Definition: Vector.cpp:99
void SetZero()
Sets all values to zero.
Definition: Matrix.hh:856
static int Line(Image< StorageType > &im, const unsigned int start[2], const unsigned int end[2], const StorageType value[])
lines
Definition: ImageDraw.cpp:404
void Rotate(const double &angle)
rotates curve by angle (rad)
ContourDetectorBSpline()
standard constructor
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
void QToCPnts_(std::vector< BIAS::Vector2< double > > &cPnts)
converts a flat control point vector Q whose first entries are x-coordinates and last entries are y-c...
unsigned int GetHeight() const
Definition: ImageBase.hh:319
void FillImageWithConstValue(StorageType Value)
fill grey images
Definition: Image.cpp:456
The image template class for specific storage types.
Definition: Image.hh:78
represents a special B-Spline and holds functions to handle fitting
void TestInit_(const unsigned int order, const ContourBSplineType::Type bType, const std::vector< unsigned int > &mPnts, const BIAS::Vector< double > &Q)
tests if B-Spline curve with given parameter can get initialized.
void Init(unsigned int Width, unsigned int Height, unsigned int channels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
calls Init from ImageBase storageType is ignored, just dummy argument
Definition: Image.cpp:421
void Mult(const Matrix< T > &arg, Matrix< T > &result) const
matrix multiplication, result is not allocated
Definition: Matrix.hh:913
void CPntsToQ_(const std::vector< BIAS::Vector2< double > > &cPnts)
converts a given control point vector in x,y-coordinates to the internal used flat control point vect...
void Fit_(const BIAS::Image< float > &featImg, const double &alpha, const unsigned int normalWidth)
fits the curve to a features curve with regularized fitting
double NormL2() const
Return the L2 norm: sqrt(a^2 + b^2)
Definition: Vector2.hh:430
Matrix< double > Invert()
returns pseudoinverse of A = U * S * V^T A^+ = V * S^+ * U^T
Definition: SVD.cpp:214
bool Save(const std::string &filename)
saves all values which are needed to reinitialise the object to a binary file
void Multiply(const T &scalar, Matrix< T > &dest) const
multiplication function, storing data destination matrix
Definition: Matrix.hh:779
void GetBoundingBox(int &minX, int &minY, int &maxX, int &maxY)
returns the parameter of the bounding box of the curve
void MultLeft(const Matrix< T > &arg)
in Place matrix multiplication this is equal to M = arg*M, but faster
Definition: Matrix.hh:947
void Fit(BIAS::Image< StorageType > &greyImg, const double &alpha, const unsigned int normalWidth)
fits B-Spline curve to gradient features found in the image
virtual int Filter(const Image< InputStorageType > &src, Image< OutputStorageType > &grad)
returns a 2 channel image containing gx and gy
static ContourDetectorBSpline Cluster(const std::vector< ContourDetectorBSpline< StorageType > > &bSplines)
builds a new ContourBspline object from given vector of ContourBSpline objects
int SetROICorners(unsigned int UpperLeftX, unsigned int UpperLeftY, unsigned int LowerRightX, unsigned int LowerRightY)
Definition: ImageBase.cpp:1048
Subscript size() const
Definition: vec.h:262
void DrawNormals(const unsigned int normalWidth, BIAS::Image< StorageType > &img, const StorageType color[3])
draws B-Spline normals into image
void UnsetROI()
deprecated, use GetROI()-&gt;UnsetROI()
Definition: ImageBase.cpp:1057
virtual ~ContourDetectorBSpline()
destructor