Hugin trunk 0.1
Loading...
Searching...
No Matches
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"
34
35namespace HuginLines
36{
37
38template <class SrcImageIterator, class SrcAccessor, class DestImage>
39double 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 {
51 // calculate new image size
53 nh = static_cast<int>(0.5 + (sizefactor*inputSize.height()));
54 }
55 else
56 {
58 // calculate new image size
59 nw = static_cast<int>(0.5 + (sizefactor*inputSize.width()));
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
76vigra::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
88vigra::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
100double 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 }
112}
113
114
115Lines 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();
119
122
123 vigra::BImage lineImage = edgeMap2linePts(edge);
124 Lines lines;
126
127 return lines;
128};
129
130void 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
141HuginBase::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
159vigra::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
167vigra::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{
175public:
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 };
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 }
230private:
231 vigra::Point2D m_start;
232 vigra::Point2D m_end;
233};
234
235typedef std::vector<VerticalLine> VerticalLineVector;
236
237//linear fit of given line, returns endpoints of fitted line
239{
240 size_t n=line.line.size();
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
277{
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 {
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{
333public:
334 typedef vigra::UInt8 value_type;
335 template <class ITERATOR>
337 {
338 return 255 - (*i);
339 }
340 template <class ITERATOR, class DIFFERENCE>
342 {
343 return 255 - i[d];
344 }
345};
346
347template <class ImageType>
348HuginBase::CPVector _getFilteredLines(const HuginBase::Panorama& pano,const unsigned int imgNr,ImageType& image, vigra::BImage& mask, const unsigned int nrLines, const bool onlyVerticalLines)
349{
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;
358 vigra::BImage* edge;
359 if(!needsRemap)
360 {
361 //rectilinear image can be used as is
362 //detect edges
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));
378 remappedImage.setActive(true);
379 //create PanoramaOptions for remapping of image
382 opts.outputExposureValue=0;
383 //calculate output canvas size
386 tempPano.setOptions(opts);
387
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 };
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
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;
453 {
455 }
456 else
457 {
458 if (std::abs(roll) < 45 || (roll > 135 && roll < 225) || roll > 315)
459 {
461 }
462 else
463 {
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
501 {
502 // search only vertical lines
503 if (detectedLines.size() > 1)
504 {
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 {
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;
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 {
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 {
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 {
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
596 };
597 };
598 return verticalLines;
599};
600
601HuginBase::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
606HuginBase::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
611HuginBase::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
#define MAX_RESIZE_DIM
declaration of functions for finding lines
declaration of find lines algorithm
!! from PTOptimise.h 1951
Contains functions to transform whole images.
Dummy progress display, without output.
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)
virtual double getResultHorizontalFOV()
Definition FitPanorama.h:68
virtual double getResultHeight()
Definition FitPanorama.h:75
represents a control point
@ X
evaluate x, points are on a vertical line
@ Y
evaluate y, points are on a horizontal line
struct to hold a image state for stitching
Holds transformations for Image -> Pano and the other way.
bool transformImgCoord(double &x_dest, double &y_dest, double x_src, double y_src) const
like transform, but return image coordinates, not cartesian coordinates
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->image transformation
virtual void run()
runs the algorithm.
Panorama image options.
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
void setHeight(unsigned int h)
set panorama height
const vigra::Rect2D & getROI() const
void setWidth(unsigned int w, bool keepView=true)
set panorama width keep the HFOV, if keepView=true
unsigned int getHeight() const
get panorama height
Model for a panorama.
Definition Panorama.h:153
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition Panorama.h:211
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
unsigned int addImage(const SrcPanoImage &img)
the the number for a specific image
Definition Panorama.cpp:319
All variables of a source image.
static double calcFocalLength(SrcPanoImage::Projection proj, double hfov, double crop, vigra::Size2D imageSize)
calcualte focal length, given crop factor and hfov
void deleteAllMasks()
delete all masks
value_type operator()(ITERATOR const &i, DIFFERENCE d) const
value_type operator()(ITERATOR const &i) const
void SetEnd(const int x, const int y)
double GetLineLength() const
void SetEnd(const vigra::Point2D point)
void SetStart(const int x, const int y)
const bool IsVertical() const
const vigra::Point2D & GetEnd() const
void SetStart(const vigra::Point2D point)
double GetEstimatedDistance(const VerticalLine &otherLine) const
const vigra::Point2D & GetStart() const
double GetAngle() const
vigra::FRGBImage ImageType
#define DEG_TO_RAD(x)
Definition hugin_math.h:44
unsigned int optimize(PanoramaData &pano, const char *userScript)
optimize the images imgs, for variables optvec, using vars as start.
std::vector< ControlPoint > CPVector
std::vector< std::set< std::string > > OptimizeVector
std::vector< VerticalLine > VerticalLineVector
VerticalLine FitLine(SingleLine line)
HuginBase::CPVector _getFilteredLines(const HuginBase::Panorama &pano, const unsigned int imgNr, ImageType &image, vigra::BImage &mask, const unsigned int nrLines, const bool onlyVerticalLines)
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...
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's algorithm
Definition FindLines.cpp:76
vigra::BImage edgeMap2linePts(vigra::BImage &input)
marks line point
VerticalLineVector FilterLines(Lines lines, double roll, const bool onlyVerticalLines)
void ScaleLines(Lines &lines, const double scale)
scales the given lines with given factor use in conjugation with HuginLines::detectEdges to scale the...
bool SortByError(const HuginBase::ControlPoint &cp1, const HuginBase::ControlPoint &cp2)
std::vector< SingleLine > Lines
vector of extracted lines from image
Definition LinesTypes.h:50
double resize_image(const vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, DestImage &dest, int resize_dimension)
Definition FindLines.cpp:39
int linePts2lineList(vigra::BImage &img, int minsize, double flpix, Lines &lines)
converts a linePts image to a list of lines
vigra::Point2D GetFootpoint(const vigra::Point2D &p, const vigra::Point2D &p1, const vigra::Point2D &p2, double &u)
double calculate_focal_length_pixels(double focal_length, double cropFactor, double width, double height)
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
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
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...
int roundi(T x)
Definition hugin_math.h:73
double norm(T t)
Definition hugin_math.h:187
a single line extracted from image
Definition LinesTypes.h:44
std::vector< vigra::Point2D > line
Definition LinesTypes.h:45
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