Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
FindLines.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
8 /***************************************************************************
9  * Copyright (C) 2009 by Tim Nugent *
10  * timnugent@gmail.com *
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  * This program is distributed in the hope that it will be useful, *
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
20  * GNU General Public License for more details. *
21  * *
22  * You should have received a copy of the GNU General Public License *
23  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
24  ***************************************************************************/
25 
26 #include "vigra/edgedetection.hxx"
27 #include "FindLines.h"
28 #include "FindN8Lines.h"
31 #include <nona/RemappedPanoImage.h>
34 
35 namespace HuginLines
36 {
37 
38 template <class SrcImageIterator, class SrcAccessor, class DestImage>
39 double resize_image(const vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, DestImage& dest, int resize_dimension)
40 {
41  // Re-size to max dimension
42  double sizefactor=1.0;
43  const vigra::Size2D inputSize(src.second - src.first);
44  if (inputSize.width() > resize_dimension || inputSize.height() > resize_dimension)
45  {
46  int nw;
47  int nh;
48  if (inputSize.width() >= inputSize.height())
49  {
50  sizefactor = (double)resize_dimension / inputSize.width();
51  // calculate new image size
52  nw = resize_dimension;
53  nh = static_cast<int>(0.5 + (sizefactor*inputSize.height()));
54  }
55  else
56  {
57  sizefactor = (double)resize_dimension / inputSize.height();
58  // calculate new image size
59  nw = static_cast<int>(0.5 + (sizefactor*inputSize.width()));
60  nh = resize_dimension;
61  }
62 
63  // create an image of appropriate size
64  dest.resize(nw, nh);
65  // resize the image, using a bi-cubic spline algorithm
66  resizeImageNoInterpolation(src, destImageRange(dest));
67  }
68  else
69  {
70  dest.resize(inputSize);
71  copyImage(src, destImage(dest));
72  };
73  return 1.0/sizefactor;
74 }
75 
76 vigra::BImage* detectEdges(const vigra::UInt8RGBImage& input, const double scale, const double threshold, const unsigned int resize_dimension, double& size_factor)
77 {
78  // Resize image
79  vigra::UInt8Image scaled;
80  size_factor = resize_image(vigra::srcImageRange(input, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >()), scaled, resize_dimension);
81 
82  // Run Canny edge detector
83  vigra::BImage* image = new vigra::BImage(scaled.width(), scaled.height(), 255);
84  vigra::cannyEdgeImage(vigra::srcImageRange(scaled), vigra::destImage(*image), scale, threshold, 0);
85  return image;
86 };
87 
88 vigra::BImage* detectEdges(const vigra::BImage& input, const double scale, const double threshold, const unsigned int resize_dimension, double& size_factor)
89 {
90  // Resize image
91  vigra::UInt8Image scaled;
92  size_factor=resize_image(vigra::srcImageRange(input), scaled, resize_dimension);
93 
94  // Run Canny edge detector
95  vigra::BImage* image = new vigra::BImage(scaled.width(), scaled.height(), 255);
96  vigra::cannyEdgeImage(vigra::srcImageRange(scaled), vigra::destImage(*image), scale, threshold, 0);
97  return image;
98 };
99 
100 double calculate_focal_length_pixels(double focal_length,double cropFactor,double width, double height)
101 {
102  double pixels_per_mm = 0;
103  if (cropFactor > 1)
104  {
105  pixels_per_mm= (cropFactor/24.0)* ((width>height)?height:width);
106  }
107  else
108  {
109  pixels_per_mm= (24.0/cropFactor)* ((width>height)?height:width);
110  }
111  return focal_length*pixels_per_mm;
112 }
113 
114 
115 Lines findLines(vigra::BImage& edge, double length_threshold, double focal_length,double crop_factor)
116 {
117  unsigned int longest_dimension=(edge.width() > edge.height()) ? edge.width() : edge.height();
118  double min_line_length_squared=(length_threshold*longest_dimension)*(length_threshold*longest_dimension);
119 
120  int lmin = int(sqrt(min_line_length_squared));
121  double flpix=calculate_focal_length_pixels(focal_length,crop_factor,edge.width(),edge.height());
122 
123  vigra::BImage lineImage = edgeMap2linePts(edge);
124  Lines lines;
125  linePts2lineList( lineImage, lmin, flpix, lines );
126 
127  return lines;
128 };
129 
130 void ScaleLines(Lines& lines,const double scale)
131 {
132  for(unsigned int i=0; i<lines.size(); i++)
133  {
134  for(unsigned int j=0; j<lines[i].line.size(); j++)
135  {
136  lines[i].line[j]*=scale;
137  };
138  };
139 };
140 
141 HuginBase::CPVector GetControlPoints(const SingleLine& line,const unsigned int imgNr, const unsigned int lineNr,const unsigned int numberOfCtrlPoints)
142 {
144  double interval = (line.line.size()-1)/(1.0*numberOfCtrlPoints);
145  for(unsigned int k = 0; k < numberOfCtrlPoints; k++)
146  {
147  int start = (int)(k * interval);
148  int stop = (int)((k+1) * interval);
149  HuginBase::ControlPoint cp(imgNr,line.line[start].x, line.line[start].y,
150  imgNr,line.line[stop].x, line.line[stop].y,lineNr);
151  cpv.push_back(cp);
152  };
153  return cpv;
154 };
155 
156 #define MAX_RESIZE_DIM 1600
157 
158 //return footpoint of point p on line between point p1 and p2
159 vigra::Point2D GetFootpoint(const vigra::Point2D& p, const vigra::Point2D& p1, const vigra::Point2D& p2, double& u)
160 {
161  hugin_utils::FDiff2D diff = p2 - p1;
162  u = ((p.x - p1.x)*(p2.x - p1.x) + (p.y - p1.y)*(p2.y - p1.y)) / hugin_utils::sqr(hugin_utils::norm(diff));
163  diff *= u;
164  return vigra::Point2D(p1.x + diff.x, p1.y + diff.y);
165 };
166 
167 vigra::Point2D GetFootpoint(const vigra::Point2D& p, const vigra::Point2D& p1, const vigra::Point2D& p2)
168 {
169  double u;
170  return GetFootpoint(p, p1, p2, u);
171 };
172 
174 {
175 public:
176  void SetStart(const vigra::Point2D point)
177  {
178  m_start = point;
179  };
180  void SetStart(const int x, const int y)
181  {
182  m_start = vigra::Point2D(x, y);
183  };
184  void SetEnd(const vigra::Point2D point)
185  {
186  m_end = point;
187  };
188  void SetEnd(const int x, const int y)
189  {
190  m_end = vigra::Point2D(x, y);
191  };
192  double GetLineLength() const
193  {
194  return (m_end - m_start).magnitude();
195  };
196  double GetEstimatedDistance(const VerticalLine& otherLine) const
197  {
198  auto getDist = [](const vigra::Point2D& p, const vigra::Point2D& p1, const vigra::Point2D& p2)->double
199  {
200  double t;
201  const vigra::Point2D endPoint = GetFootpoint(p, p1, p2, t);
202  if (-0.1 < t && t < 1.1)
203  {
204  return (endPoint - p).magnitude();
205  }
206  else
207  {
208  return DBL_MAX;
209  };
210  };
211  return std::min({getDist(otherLine.GetStart(), m_start, m_end), getDist(otherLine.GetEnd(), m_start, m_end),
212  getDist(m_start, otherLine.GetStart(), otherLine.GetEnd()), getDist(m_end, otherLine.GetStart(), otherLine.GetEnd())});
213  }
214  double GetAngle() const
215  {
216  return atan2(m_end.y - m_start.y, m_end.x - m_start.x);
217  };
218  const vigra::Point2D& GetStart() const
219  {
220  return m_start;
221  };
222  const vigra::Point2D& GetEnd() const
223  {
224  return m_end;
225  };
226  const bool IsVertical() const
227  {
228  return std::abs(m_start.x - m_end.x) < std::abs(m_start.y - m_end.y);
229  }
230 private:
231  vigra::Point2D m_start;
232  vigra::Point2D m_end;
233 };
234 
235 typedef std::vector<VerticalLine> VerticalLineVector;
236 
237 //linear fit of given line, returns endpoints of fitted line
239 {
240  size_t n=line.line.size();
241  VerticalLine vl;
242  double s_x=0;
243  double s_y=0;
244  double s_xy=0;
245  double s_x2=0;
246  for(size_t i=0;i<n;i++)
247  {
248  s_x+=(double)line.line[i].x/n;
249  s_y+=(double)line.line[i].y/n;
250  s_xy+=(double)line.line[i].x*line.line[i].y/n;
251  s_x2+=(double)line.line[i].x*line.line[i].x/n;
252  };
253  if(std::abs(s_x2-s_x*s_x)<0.00001)
254  {
255  //vertical line needs special treatment
256  vl.SetStart(s_x, line.line[0].y);
257  vl.SetEnd(s_x, line.line[n - 1].y);
258  }
259  else
260  {
261  //calculate slope and offset
262  double slope=(s_xy-s_x*s_y)/(s_x2-s_x*s_x);
263  double offset=s_y-slope*s_x;
264  //convert to parametric form
265  vigra::Point2D p1(0,offset);
266  vigra::Point2D p2(100,100*slope+offset);
267  //calculate footpoint of first and last point
268  vl.SetStart(GetFootpoint(line.line[0], p1, p2));
269  vl.SetEnd(GetFootpoint(line.line[n - 1], p1, p2));
270  };
271  return vl;
272 };
273 
274 //filter detected lines
275 //return fitted lines which have only a small deviation from the vertical
276 VerticalLineVector FilterLines(Lines lines,double roll, const bool onlyVerticalLines)
277 {
278  VerticalLineVector vertLines;
279  if(!lines.empty())
280  {
281  for(Lines::const_iterator it=lines.begin(); it!=lines.end(); ++it)
282  {
283  if((*it).status==valid_line && (*it).line.size()>2)
284  {
285  VerticalLine vl=FitLine(*it);
286  const vigra::Diff2D diff = vl.GetEnd() - vl.GetStart();
287  // check that line is long enough
288  if(diff.magnitude()>20)
289  {
290  // now check angle with respect to roll angle, accept only deviation of 5° (sin 5°=0.1)
291  if(!onlyVerticalLines || std::abs((diff.x*cos(DEG_TO_RAD(roll))+diff.y*sin(DEG_TO_RAD(roll)))/diff.magnitude())<0.1)
292  {
293  // check distance and angle to other lines
294  bool distanceBig = true;
295  for (auto& otherLine : vertLines)
296  {
297  // distance should be at least 80 pixel = 5 % from image width
298  if (vl.GetEstimatedDistance(otherLine) < 80)
299  {
300  // now check if line are parallel = have the same angle (tan(3°)=0.05)
301  if (std::abs(vl.GetAngle() - otherLine.GetAngle()) < 0.05)
302  {
303  distanceBig = false;
304  // both lines are close to each other, keep only the longer one
305  if (vl.GetLineLength() > otherLine.GetLineLength())
306  {
307  otherLine = vl;
308  }
309  continue;
310  };
311  };
312  }
313  if (distanceBig)
314  {
315  vertLines.push_back(vl);
316  };
317  };
318  };
319  };
320  };
321  };
322  return vertLines;
323 };
324 
325 //function to sort HuginBase::CPVector by error distance
327 {
328  return cp1.error<cp2.error;
329 };
330 
332 {
333 public:
334  typedef vigra::UInt8 value_type;
335  template <class ITERATOR>
336  value_type operator()(ITERATOR const & i) const
337  {
338  return 255 - (*i);
339  }
340  template <class ITERATOR, class DIFFERENCE>
341  value_type operator()(ITERATOR const & i, DIFFERENCE d) const
342  {
343  return 255 - i[d];
344  }
345 };
346 
347 template <class ImageType>
348 HuginBase::CPVector _getFilteredLines(const HuginBase::Panorama& pano,const unsigned int imgNr,ImageType& image, vigra::BImage& mask, const unsigned int nrLines, const bool onlyVerticalLines)
349 {
350  HuginBase::CPVector verticalLines;
351  HuginBase::CPVector detectedLines;
352  const HuginBase::SrcPanoImage& srcImage=pano.getImage(imgNr);
353  bool needsRemap=srcImage.getProjection()!=HuginBase::SrcPanoImage::RECTILINEAR;
354  double roll=(needsRemap?0:srcImage.getRoll());
355  double size_factor=1.0;
356  HuginBase::SrcPanoImage remappedImage;
358  vigra::BImage* edge;
359  if(!needsRemap)
360  {
361  //rectilinear image can be used as is
362  //detect edges
363  edge=detectEdges(image,2,4,MAX_RESIZE_DIM,size_factor);
364  }
365  else
366  {
367  //remap all other image to equirectangular
368  //create temporary SrcPanoImage, set appropriate image variables
369  remappedImage=pano.getSrcImage(imgNr);
370  remappedImage.setYaw(0);
371  remappedImage.setPitch(0);
372  remappedImage.setX(0);
373  remappedImage.setY(0);
374  remappedImage.setZ(0);
375  remappedImage.setExposureValue(0);
376  remappedImage.setEMoRParams(std::vector<float>(5, 0.0));
377  remappedImage.deleteAllMasks();
378  remappedImage.setActive(true);
379  //create PanoramaOptions for remapping of image
381  opts.setWidth(MAX_RESIZE_DIM);
382  opts.outputExposureValue=0;
383  //calculate output canvas size
384  HuginBase::Panorama tempPano;
385  tempPano.addImage(remappedImage);
386  tempPano.setOptions(opts);
387 
388  HuginBase::CalculateFitPanorama fitPano(tempPano);
389  fitPano.run();
390  opts.setHFOV(fitPano.getResultHorizontalFOV());
392  if (opts.getVFOV() > 100)
393  {
394  // limit vertical fov to 100 deg to prevent finding lines
395  // near nadir/zenit which are probably wrong with this simple
396  // line finding algorithmus
397  opts.setHeight(hugin_utils::roundi(opts.getHeight() * 90.0 / opts.getVFOV()));
398  };
399  tempPano.setOptions(opts);
400 
401  //finally remap image
404  remapped->setPanoImage(remappedImage,opts,opts.getROI());
405  if (mask.size().area() > 0)
406  {
407  remapped->remapImage(vigra::srcImageRange(image), vigra::srcImage(mask), vigra_ext::INTERP_CUBIC, progress);
408  }
409  else
410  {
411  remapped->remapImage(vigra::srcImageRange(image), vigra_ext::INTERP_CUBIC, progress);
412  };
413  ImageType remappedBitmap=remapped->m_image;
414  mask = remapped->m_mask;
415  //detect edges
416  edge=detectEdges(remappedBitmap,2,4,std::max(remappedBitmap.width(),remappedBitmap.height())+10,size_factor);
417  delete remapped;
418  delete progress;
419  };
420  // ignore all edges outside of masked areas
421  if (mask.size().area() > 0)
422  {
423  vigra::initImageIf(vigra::destImageRange(*edge), vigra::srcImage(mask, InvertedMaskAccessor()), vigra::UInt8(255));
424  };
425  //detect lines
426  //we need the focal length
427  double focalLength=srcImage.getExifFocalLength();
428  if(focalLength==0)
429  {
431  srcImage.getProjection(),srcImage.getHFOV(),srcImage.getCropFactor(),srcImage.getSize());
432  };
433  Lines foundLines=findLines(*edge,0.05,focalLength,srcImage.getCropFactor());
434  delete edge;
435  //filter results
436  VerticalLineVector filteredLines = FilterLines(foundLines, roll, onlyVerticalLines);
437  //create control points
438  if(!filteredLines.empty())
439  {
440  //we need to transform the coordinates to image coordinates because the detection
441  //worked on smaller images or in remapped image
443  if(needsRemap)
444  {
445  transform.createTransform(remappedImage,opts);
446  };
447  for(size_t i=0; i<filteredLines.size(); i++)
448  {
450  cp.image1Nr=0;
451  cp.image2Nr=0;
452  if (onlyVerticalLines)
453  {
455  }
456  else
457  {
458  if (std::abs(roll) < 45 || (roll > 135 && roll < 225) || roll > 315)
459  {
460  cp.mode = filteredLines[i].IsVertical() ? HuginBase::ControlPoint::X : HuginBase::ControlPoint::Y;
461  }
462  else
463  {
464  cp.mode = filteredLines[i].IsVertical() ? HuginBase::ControlPoint::Y : HuginBase::ControlPoint::X;
465  };
466  }
467  if(!needsRemap)
468  {
469  cp.x1 = filteredLines[i].GetStart().x*size_factor;
470  cp.y1 = filteredLines[i].GetStart().y*size_factor;
471  cp.x2 = filteredLines[i].GetEnd().x*size_factor;
472  cp.y2 = filteredLines[i].GetEnd().y*size_factor;
473  }
474  else
475  {
476  double xout;
477  double yout;
478  if(!transform.transformImgCoord(xout,yout,filteredLines[i].GetStart().x,filteredLines[i].GetStart().y))
479  {
480  continue;
481  };
482  cp.x1=xout;
483  cp.y1=yout;
484  if(!transform.transformImgCoord(xout,yout,filteredLines[i].GetEnd().x,filteredLines[i].GetEnd().y))
485  {
486  continue;
487  };
488  cp.x2=xout;
489  cp.y2=yout;
490  };
491  if(cp.x1>=0 && cp.x1<srcImage.getWidth() && cp.y1>=0 && cp.y1<srcImage.getHeight() &&
492  cp.x2>=0 && cp.x2<srcImage.getWidth() && cp.y2>=0 && cp.y2<srcImage.getHeight())
493  {
494  detectedLines.push_back(cp);
495  };
496  };
497  //now a final check of the found vertical lines
498  //we optimize the pano with a single image and disregard vertical lines with bigger errors
499  //we need at least 2 lines
500  if (onlyVerticalLines)
501  {
502  // search only vertical lines
503  if (detectedLines.size() > 1)
504  {
505  HuginBase::Panorama tempPano;
506  HuginBase::SrcPanoImage tempImage = pano.getSrcImage(imgNr);
507  tempImage.setYaw(0);
508  tempImage.setPitch(0);
509  tempImage.setRoll(0);
510  tempImage.setX(0);
511  tempImage.setY(0);
512  tempImage.setZ(0);
513  tempPano.addImage(tempImage);
514  for (size_t i = 0; i < detectedLines.size(); i++)
515  {
516  tempPano.addCtrlPoint(detectedLines[i]);
517  };
520  tempPano.setOptions(opt2);
522  std::set<std::string> imgopt;
523  imgopt.insert("p");
524  imgopt.insert("r");
525  optVec.push_back(imgopt);
526  tempPano.setOptimizeVector(optVec);
527  // ARGH the panotools optimizer uses global variables is not reentrant
528 #pragma omp critical
529  {
530  HuginBase::PTools::optimize(tempPano);
531  }
532  //first filter stage
533  //we disregard all lines with big error
534  //calculate statistic and determine limit
535  double minError, maxError, mean, var;
536  HuginBase::CalculateCPStatisticsError::calcCtrlPntsErrorStats(tempPano, minError, maxError, mean, var);
537  detectedLines = tempPano.getCtrlPoints();
538  double limit = mean + sqrt(var);
539  maxError = 0;
540  for (int i = detectedLines.size() - 1; i >= 0; i--)
541  {
542  if (detectedLines[i].error > limit)
543  {
544  detectedLines.erase(detectedLines.begin() + i);
545  }
546  else
547  {
548  //we need the max error of the remaining lines for the next step
549  maxError = std::max(detectedLines[i].error, maxError);
550  };
551  };
552  if (!detectedLines.empty() && maxError > 0) //security check, should never be false
553  {
554  //now keep only the best nrLines lines
555  //we are using error and line length as figure of merrit
556  for (size_t i = 0; i < detectedLines.size(); i++)
557  {
558  double length = sqrt(hugin_utils::sqr(detectedLines[i].x2 - detectedLines[i].x1) + hugin_utils::sqr(detectedLines[i].y2 - detectedLines[i].y1));
559  //calculate number of merrit
560  detectedLines[i].error = detectedLines[i].error / maxError + (1.0 - std::min(length, 500.0) / 500.0);
561  };
562  std::sort(detectedLines.begin(), detectedLines.end(), SortByError);
563  //only save best nrLines control points
564  for (size_t i = 0; i < detectedLines.size() && i < nrLines; i++)
565  {
566  HuginBase::ControlPoint cp = detectedLines[i];
567  cp.image1Nr = imgNr;
568  cp.image2Nr = imgNr;
569  cp.error = 0;
570  verticalLines.push_back(cp);
571  };
572  };
573  }
574  else
575  {
576  //if only one line was detected we do a special check
577  //the allow deviation between line and roll angle is checked more narrow than in the first check
578  if (detectedLines.size() == 1)
579  {
580  vigra::Diff2D diff((double)detectedLines[0].x2 - detectedLines[0].x1, (double)detectedLines[0].y2 - detectedLines[0].y1);
581  if (std::abs((diff.x * cos(DEG_TO_RAD(roll)) + diff.y * sin(DEG_TO_RAD(roll))) / diff.magnitude()) < 0.05)
582  {
583  HuginBase::ControlPoint cp = detectedLines[0];
584  cp.image1Nr = imgNr;
585  cp.image2Nr = imgNr;
586  cp.error = 0;
587  verticalLines.push_back(cp);
588  };
589  };
590  };
591  }
592  else
593  {
594  // search for all line directions
595  verticalLines = detectedLines;
596  };
597  };
598  return verticalLines;
599 };
600 
601 HuginBase::CPVector GetVerticalLines(const HuginBase::Panorama& pano,const unsigned int imgNr,vigra::UInt8RGBImage& image, vigra::BImage& mask, const unsigned int nrLines)
602 {
603  return _getFilteredLines(pano, imgNr, image, mask, nrLines, true);
604 };
605 
606 HuginBase::CPVector GetVerticalLines(const HuginBase::Panorama& pano,const unsigned int imgNr,vigra::BImage& image, vigra::BImage& mask, const unsigned int nrLines)
607 {
608  return _getFilteredLines(pano, imgNr, image, mask, nrLines, true);
609 };
610 
611 HuginBase::CPVector GetLines(const HuginBase::Panorama& pano, const unsigned int imgNr, vigra::UInt8RGBImage& image, vigra::BImage& mask)
612 {
613  return _getFilteredLines(pano, imgNr, image, mask, 0, false);
614 }
615 
616 }; //namespace
AlphaImage m_mask
corresponding alpha channel
Definition: ROIImage.h:274
std::vector< vigra::Point2D > line
Definition: LinesTypes.h:45
#define MAX_RESIZE_DIM
Definition: FindLines.cpp:156
Dummy progress display, without output.
double norm(T t)
Definition: hugin_math.h:180
vigra::Point2D m_end
Definition: FindLines.cpp:232
const vigra::Point2D & GetEnd() const
Definition: FindLines.cpp:222
void setHeight(unsigned int h)
set panorama height
int roundi(T x)
Definition: hugin_math.h:73
void setPanoImage(const SrcPanoImage &src, const PanoramaOptions &dest, vigra::Rect2D roi)
VerticalLine FitLine(SingleLine line)
Definition: FindLines.cpp:238
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
Definition: Panorama.cpp:1620
void SetStart(const vigra::Point2D point)
Definition: FindLines.cpp:176
double calculate_focal_length_pixels(double focal_length, double cropFactor, double width, double height)
Definition: FindLines.cpp:100
HuginBase::CPVector GetVerticalLines(const HuginBase::Panorama &pano, const unsigned int imgNr, vigra::UInt8RGBImage &image, vigra::BImage &mask, const unsigned int nrLines)
searches for vertical control points in given image
Definition: FindLines.cpp:601
declaration of functions for finding lines
const vigra::Point2D & GetStart() const
Definition: FindLines.cpp:218
unsigned int getHeight() const
get panorama height
static void calcCtrlPntsErrorStats(const PanoramaData &pano, double &min, double &max, double &mean, double &var, const int &imgNr=-1, const bool onlyActive=false, const bool ignoreLineCp=false)
void ScaleLines(Lines &lines, const double scale)
scales the given lines with given factor use in conjugation with HuginLines::detectEdges to scale the...
Definition: FindLines.cpp:130
Contains functions to transform whole images.
double resize_image(const vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, DestImage &dest, int resize_dimension)
Definition: FindLines.cpp:39
T sqr(T t)
Definition: hugin_math.h:174
std::vector< VerticalLine > VerticalLineVector
Definition: FindLines.cpp:235
vigra::Point2D GetFootpoint(const vigra::Point2D &p, const vigra::Point2D &p1, const vigra::Point2D &p2, double &u)
Definition: FindLines.cpp:159
VerticalLineVector FilterLines(Lines lines, double roll, const bool onlyVerticalLines)
Definition: FindLines.cpp:276
a single line extracted from image
Definition: LinesTypes.h:43
virtual void run()
runs the algorithm.
static char * line
Definition: svm.cpp:2784
const CPVector & getCtrlPoints() const
get all control point of this Panorama
Definition: Panorama.h:319
int getHeight() const
Get the height of the image in pixels.
Definition: SrcPanoImage.h:276
vigra::pair< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImage(const ROIImage< Image, Mask > &img)
Definition: ROIImage.h:300
Lines findLines(vigra::BImage &edge, double length_threshold, double focal_length, double crop_factor)
find straightish non-crossing lines find straightish non-crossing lines in an edge map using 8-neighb...
Definition: FindLines.cpp:115
value_type operator()(ITERATOR const &i) const
Definition: FindLines.cpp:336
represents a control point
Definition: ControlPoint.h:38
void setOptimizeVector(const OptimizeVector &optvec)
set optimize setting
Definition: Panorama.cpp:297
double GetEstimatedDistance(const VerticalLine &otherLine) const
Definition: FindLines.cpp:196
const vigra::Rect2D & getROI() const
Model for a panorama.
Definition: Panorama.h:152
unsigned int addCtrlPoint(const ControlPoint &point)
add a new control point.
Definition: Panorama.cpp:381
HuginBase::CPVector GetControlPoints(const SingleLine &line, const unsigned int imgNr, const unsigned int lineNr, const unsigned int numberOfCtrlPoints)
returns a HuginBase::CPVector with cps_per_lines
Definition: FindLines.cpp:141
vigra::FRGBImage ImageType
HuginBase::CPVector _getFilteredLines(const HuginBase::Panorama &pano, const unsigned int imgNr, ImageType &image, vigra::BImage &mask, const unsigned int nrLines, const bool onlyVerticalLines)
Definition: FindLines.cpp:348
int getWidth() const
Get the width of the image in pixels.
Definition: SrcPanoImage.h:266
void remapImage(vigra::triple< ImgIter, ImgIter, ImgAccessor > srcImg, vigra_ext::Interpolator interpol, AppBase::ProgressDisplay *progress, bool singleThreaded=false)
remap a image without alpha channel
double GetAngle() const
Definition: FindLines.cpp:214
virtual double getResultHeight()
Definition: FitPanorama.h:75
void deleteAllMasks()
delete all masks
declaration of find lines algorithm
vigra::Point2D m_start
Definition: FindLines.cpp:231
HuginBase::CPVector GetLines(const HuginBase::Panorama &pano, const unsigned int imgNr, vigra::UInt8RGBImage &image, vigra::BImage &mask)
searches for all lines, the same as GetVerticalLines execpt that no filtering according to roll angle...
Definition: FindLines.cpp:611
evaluate x, points are on a vertical line
Definition: ControlPoint.h:47
double GetLineLength() const
Definition: FindLines.cpp:192
static double calcFocalLength(SrcPanoImage::Projection proj, double hfov, double crop, vigra::Size2D imageSize)
calcualte focal length, given crop factor and hfov
vigra::pair< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImage(ROIImage< Image, Alpha > &img)
Definition: ROIImage.h:324
vigra::triple< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImageRange(const ROIImage< Image, Mask > &img)
helper function for ROIImages
Definition: ROIImage.h:287
vigra::BImage * detectEdges(const vigra::UInt8RGBImage &input, const double scale, const double threshold, const unsigned int resize_dimension, double &size_factor)
detect and mark edges in an edge image using Canny&#39;s algorithm
Definition: FindLines.cpp:76
!! from PTOptimise.h 1951
unsigned int addImage(const SrcPanoImage &img)
the the number for a specific image
Definition: Panorama.cpp:319
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition: threshold.h:41
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
bool transformImgCoord(double &x_dest, double &y_dest, double x_src, double y_src) const
like transform, but return image coordinates, not cartesian coordinates
virtual double getResultHorizontalFOV()
Definition: FitPanorama.h:68
void SetEnd(const int x, const int y)
Definition: FindLines.cpp:188
void SetEnd(const vigra::Point2D point)
Definition: FindLines.cpp:184
std::vector< SingleLine > Lines
vector of extracted lines from image
Definition: LinesTypes.h:50
static T max(T x, T y)
Definition: svm.cpp:65
void SetStart(const int x, const int y)
Definition: FindLines.cpp:180
Holds transformations for Image -&gt; Pano and the other way.
unsigned int optimize(PanoramaData &pano, const char *userScript)
optimize the images imgs, for variables optvec, using vars as start.
const bool IsVertical() const
Definition: FindLines.cpp:226
std::vector< ControlPoint > CPVector
Definition: ControlPoint.h:99
vigra::triple< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImageRange(ROIImage< Image, Alpha > &img)
Definition: ROIImage.h:312
#define DEG_TO_RAD(x)
Definition: hugin_math.h:44
void copyImage(SrcImageIterator src_upperleft, SrcImageIterator src_lowerright, SrcAccessor src_acc, DestImageIterator dest_upperleft, DestAccessor dest_acc)
Definition: openmp_vigra.h:305
std::vector< std::set< std::string > > OptimizeVector
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition: Panorama.h:211
void setOptions(const PanoramaOptions &opt)
set new output settings This is not used directly for optimizing/stiching, but it can be feed into ru...
Definition: Panorama.cpp:1531
value_type operator()(ITERATOR const &i, DIFFERENCE d) const
Definition: FindLines.cpp:341
All variables of a source image.
Definition: SrcPanoImage.h:194
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
Panorama image options.
evaluate y, points are on a horizontal line
Definition: ControlPoint.h:48
struct to hold a image state for stitching
static T min(T x, T y)
Definition: svm.cpp:62
int linePts2lineList(vigra::BImage &img, int minsize, double flpix, Lines &lines)
converts a linePts image to a list of lines
void createTransform(const vigra::Diff2D &srcSize, VariableMap srcVars, Lens::LensProjectionFormat srcProj, const vigra::Diff2D &destSize, PanoramaOptions::ProjectionFormat destProj, const std::vector< double > &destProjParam, double destHFOV, const vigra::Diff2D &origSrcSize)
initialize pano-&gt;image transformation
void setWidth(unsigned int w, bool keepView=true)
set panorama width keep the HFOV, if keepView=true
vigra::BImage edgeMap2linePts(vigra::BImage &input)
marks line point
Definition: FindN8Lines.cpp:43
bool SortByError(const HuginBase::ControlPoint &cp1, const HuginBase::ControlPoint &cp2)
Definition: FindLines.cpp:326