26 #include "vigra/edgedetection.hxx"
38 template <
class SrcImageIterator,
class SrcAccessor,
class DestImage>
39 double resize_image(
const vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, DestImage& dest,
int resize_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)
48 if (inputSize.width() >= inputSize.height())
50 sizefactor = (double)resize_dimension / inputSize.width();
52 nw = resize_dimension;
53 nh =
static_cast<int>(0.5 + (sizefactor*inputSize.height()));
57 sizefactor = (double)resize_dimension / inputSize.height();
59 nw =
static_cast<int>(0.5 + (sizefactor*inputSize.width()));
60 nh = resize_dimension;
70 dest.resize(inputSize);
73 return 1.0/sizefactor;
76 vigra::BImage*
detectEdges(
const vigra::UInt8RGBImage& input,
const double scale,
const double threshold,
const unsigned int resize_dimension,
double& size_factor)
79 vigra::UInt8Image scaled;
83 vigra::BImage* image =
new vigra::BImage(scaled.width(), scaled.height(), 255);
88 vigra::BImage*
detectEdges(
const vigra::BImage& input,
const double scale,
const double threshold,
const unsigned int resize_dimension,
double& size_factor)
91 vigra::UInt8Image scaled;
95 vigra::BImage* image =
new vigra::BImage(scaled.width(), scaled.height(), 255);
102 double pixels_per_mm = 0;
105 pixels_per_mm= (cropFactor/24.0)* ((width>height)?height:width);
109 pixels_per_mm= (24.0/cropFactor)* ((width>height)?height:width);
111 return focal_length*pixels_per_mm;
115 Lines findLines(vigra::BImage& edge,
double length_threshold,
double focal_length,
double crop_factor)
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);
120 int lmin = int(sqrt(min_line_length_squared));
132 for(
unsigned int i=0; i<lines.size(); i++)
134 for(
unsigned int j=0; j<lines[i].line.size(); j++)
136 lines[i].line[j]*=scale;
144 double interval = (line.
line.size()-1)/(1.0*numberOfCtrlPoints);
145 for(
unsigned int k = 0; k < numberOfCtrlPoints; k++)
147 int start = (int)(k * interval);
148 int stop = (int)((k+1) * interval);
150 imgNr,line.
line[stop].x, line.
line[stop].y,lineNr);
156 #define MAX_RESIZE_DIM 1600
159 vigra::Point2D
GetFootpoint(
const vigra::Point2D& p,
const vigra::Point2D& p1,
const vigra::Point2D& p2,
double& u)
164 return vigra::Point2D(p1.x + diff.
x, p1.y + diff.
y);
167 vigra::Point2D
GetFootpoint(
const vigra::Point2D& p,
const vigra::Point2D& p1,
const vigra::Point2D& p2)
182 m_start = vigra::Point2D(x, y);
190 m_end = vigra::Point2D(x, y);
198 auto getDist = [](
const vigra::Point2D& p,
const vigra::Point2D& p1,
const vigra::Point2D& p2)->
double
201 const vigra::Point2D endPoint =
GetFootpoint(p, p1, p2, t);
202 if (-0.1 < t && t < 1.1)
204 return (endPoint - p).magnitude();
236 size_t n=line.
line.size();
242 for(
size_t i=0;i<n;i++)
244 s_x+=(double)line.
line[i].x/n;
245 s_y+=(
double)line.
line[i].y/n;
246 s_xy+=(double)line.
line[i].x*line.
line[i].y/n;
247 s_x2+=(
double)line.
line[i].x*line.
line[i].x/n;
249 if(std::abs(s_x2-s_x*s_x)<0.00001)
258 double slope=(s_xy-s_x*s_y)/(s_x2-s_x*s_x);
259 double offset=s_y-slope*s_x;
261 vigra::Point2D p1(0,offset);
262 vigra::Point2D p2(100,100*slope+offset);
277 for(Lines::const_iterator it=lines.begin(); it!=lines.end(); ++it)
279 if((*it).status==
valid_line && (*it).line.size()>2)
284 if(diff.magnitude()>20)
290 bool distanceBig =
true;
291 for (
auto& otherLine : vertLines)
297 if (std::abs(vl.
GetAngle() - otherLine.GetAngle()) < 0.05)
311 vertLines.push_back(vl);
331 template <
class ITERATOR>
336 template <
class ITERATOR,
class DIFFERENCE>
343 template <
class ImageType>
350 double roll=(needsRemap?0:srcImage.getRoll());
351 double size_factor=1.0;
366 remappedImage.setYaw(0);
367 remappedImage.setPitch(0);
368 remappedImage.setX(0);
369 remappedImage.setY(0);
370 remappedImage.setZ(0);
371 remappedImage.setExposureValue(0);
372 remappedImage.setEMoRParams(std::vector<float>(5, 0.0));
374 remappedImage.setActive(
true);
401 if (mask.size().area() > 0)
412 edge=
detectEdges(remappedBitmap,2,4,
std::max(remappedBitmap.width(),remappedBitmap.height())+10,size_factor);
417 if (mask.size().area() > 0)
423 double focalLength=srcImage.getExifFocalLength();
427 srcImage.getProjection(),srcImage.getHFOV(),srcImage.getCropFactor(),srcImage.getSize());
429 Lines foundLines=
findLines(*edge,0.05,focalLength,srcImage.getCropFactor());
434 if(!filteredLines.empty())
443 for(
size_t i=0; i<filteredLines.size(); i++)
451 cp.
x1 = filteredLines[i].GetStart().x*size_factor;
452 cp.
y1 = filteredLines[i].GetStart().y*size_factor;
453 cp.
x2 = filteredLines[i].GetEnd().x*size_factor;
454 cp.
y2 = filteredLines[i].GetEnd().y*size_factor;
460 if(!transform.
transformImgCoord(xout,yout,filteredLines[i].GetStart().x,filteredLines[i].GetStart().y))
466 if(!transform.
transformImgCoord(xout,yout,filteredLines[i].GetEnd().x,filteredLines[i].GetEnd().y))
476 detectedLines.push_back(cp);
482 if(detectedLines.size()>1)
487 tempImage.setPitch(0);
488 tempImage.setRoll(0);
493 for(
size_t i=0; i<detectedLines.size(); i++)
501 std::set<std::string> imgopt;
504 optVec.push_back(imgopt);
514 double minError,maxError,mean,var;
517 double limit=mean+sqrt(var);
519 for(
int i=detectedLines.size()-1; i>=0; i--)
521 if(detectedLines[i].error>limit)
523 detectedLines.erase(detectedLines.begin()+i);
528 maxError=
std::max(detectedLines[i].error,maxError);
531 if(!detectedLines.empty() && maxError>0)
535 for(
size_t i=0;i<detectedLines.size();i++)
539 detectedLines[i].error=detectedLines[i].error/maxError+(1.0-
std::min(length,500.0)/500.0);
541 std::sort(detectedLines.begin(),detectedLines.end(),
SortByError);
543 for(
size_t i=0;i<detectedLines.size() && i<nrLines; i++)
549 verticalLines.push_back(cp);
557 if(detectedLines.size()==1)
559 vigra::Diff2D diff((
double)detectedLines[0].x2-detectedLines[0].x1,(
double)detectedLines[0].y2-detectedLines[0].y1);
566 verticalLines.push_back(cp);
571 return verticalLines;
AlphaImage m_mask
corresponding alpha channel
std::vector< vigra::Point2D > line
Dummy progress display, without output.
const vigra::Point2D & GetEnd() const
void setHeight(unsigned int h)
set panorama height
void setPanoImage(const SrcPanoImage &src, const PanoramaOptions &dest, vigra::Rect2D roi)
VerticalLine FitLine(SingleLine line)
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
void SetStart(const vigra::Point2D point)
double calculate_focal_length_pixels(double focal_length, double cropFactor, double width, double height)
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
declaration of functions for finding lines
const vigra::Point2D & GetStart() const
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...
Contains functions to transform whole images.
double resize_image(const vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, DestImage &dest, int resize_dimension)
std::vector< VerticalLine > VerticalLineVector
vigra::Point2D GetFootpoint(const vigra::Point2D &p, const vigra::Point2D &p1, const vigra::Point2D &p2, double &u)
a single line extracted from image
virtual void run()
runs the algorithm.
const CPVector & getCtrlPoints() const
get all control point of this Panorama
int getHeight() const
Get the height of the image in pixels.
vigra::pair< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImage(const ROIImage< Image, Mask > &img)
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...
value_type operator()(ITERATOR const &i) const
represents a control point
void setOptimizeVector(const OptimizeVector &optvec)
set optimize setting
double GetEstimatedDistance(const VerticalLine &otherLine) const
const vigra::Rect2D & getROI() const
unsigned int addCtrlPoint(const ControlPoint &point)
add a new control point.
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
vigra::FRGBImage ImageType
int getWidth() const
Get the width of the image in pixels.
void remapImage(vigra::triple< ImgIter, ImgIter, ImgAccessor > srcImg, vigra_ext::Interpolator interpol, AppBase::ProgressDisplay *progress, bool singleThreaded=false)
remap a image without alpha channel
RemapImage m_image
remapped image
virtual double getResultHeight()
void deleteAllMasks()
delete all masks
declaration of find lines algorithm
evaluate x, points are on a vertical line
VerticalLineVector FilterLines(Lines lines, double roll)
double GetLineLength() const
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)
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
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
!! from PTOptimise.h 1951
unsigned int addImage(const SrcPanoImage &img)
the the number for a specific image
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.
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
virtual double getResultHorizontalFOV()
void SetEnd(const int x, const int y)
void SetEnd(const vigra::Point2D point)
std::vector< SingleLine > Lines
vector of extracted lines from image
void SetStart(const int x, const int y)
std::vector< ControlPoint > CPVector
vigra::triple< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImageRange(ROIImage< Image, Alpha > &img)
void copyImage(SrcImageIterator src_upperleft, SrcImageIterator src_lowerright, SrcAccessor src_acc, DestImageIterator dest_upperleft, DestAccessor dest_acc)
std::vector< std::set< std::string > > OptimizeVector
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
void setOptions(const PanoramaOptions &opt)
set new output settings This is not used directly for optimizing/stiching, but it can be feed into ru...
value_type operator()(ITERATOR const &i, DIFFERENCE d) const
All variables of a source image.
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
struct to hold a image state for stitching
int linePts2lineList(vigra::BImage &img, int minsize, double flpix, Lines &lines)
converts a linePts image to a list of lines
void setWidth(unsigned int w, bool keepView=true)
set panorama width keep the HFOV, if keepView=true
HuginBase::CPVector _getVerticalLines(const HuginBase::Panorama &pano, const unsigned int imgNr, ImageType &image, vigra::BImage &mask, const unsigned int nrLines)
vigra::BImage edgeMap2linePts(vigra::BImage &input)
marks line point
bool SortByError(const HuginBase::ControlPoint &cp1, const HuginBase::ControlPoint &cp2)
double outputExposureValue