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();
240 size_t n=line.
line.size();
246 for(
size_t i=0;i<n;i++)
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;
253 if(std::abs(s_x2-s_x*s_x)<0.00001)
262 double slope=(s_xy-s_x*s_y)/(s_x2-s_x*s_x);
263 double offset=s_y-slope*s_x;
265 vigra::Point2D p1(0,offset);
266 vigra::Point2D p2(100,100*slope+offset);
281 for(Lines::const_iterator it=lines.begin(); it!=lines.end(); ++it)
283 if((*it).status==
valid_line && (*it).line.size()>2)
288 if(diff.magnitude()>20)
291 if(!onlyVerticalLines || std::abs((diff.x*cos(
DEG_TO_RAD(roll))+diff.y*sin(
DEG_TO_RAD(roll)))/diff.magnitude())<0.1)
294 bool distanceBig =
true;
295 for (
auto& otherLine : vertLines)
301 if (std::abs(vl.
GetAngle() - otherLine.GetAngle()) < 0.05)
315 vertLines.push_back(vl);
335 template <
class ITERATOR>
340 template <
class ITERATOR,
class DIFFERENCE>
347 template <
class ImageType>
354 double roll=(needsRemap?0:srcImage.getRoll());
355 double size_factor=1.0;
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);
405 if (mask.size().area() > 0)
416 edge=
detectEdges(remappedBitmap,2,4,
std::max(remappedBitmap.width(),remappedBitmap.height())+10,size_factor);
421 if (mask.size().area() > 0)
427 double focalLength=srcImage.getExifFocalLength();
431 srcImage.getProjection(),srcImage.getHFOV(),srcImage.getCropFactor(),srcImage.getSize());
433 Lines foundLines=
findLines(*edge,0.05,focalLength,srcImage.getCropFactor());
438 if(!filteredLines.empty())
447 for(
size_t i=0; i<filteredLines.size(); i++)
452 if (onlyVerticalLines)
458 if (std::abs(roll) < 45 || (roll > 135 && roll < 225) || roll > 315)
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;
478 if(!transform.
transformImgCoord(xout,yout,filteredLines[i].GetStart().x,filteredLines[i].GetStart().y))
484 if(!transform.
transformImgCoord(xout,yout,filteredLines[i].GetEnd().x,filteredLines[i].GetEnd().y))
494 detectedLines.push_back(cp);
500 if (onlyVerticalLines)
503 if (detectedLines.size() > 1)
508 tempImage.setPitch(0);
509 tempImage.setRoll(0);
514 for (
size_t i = 0; i < detectedLines.size(); i++)
522 std::set<std::string> imgopt;
525 optVec.push_back(imgopt);
535 double minError, maxError, mean, var;
538 double limit = mean + sqrt(var);
540 for (
int i = detectedLines.size() - 1; i >= 0; i--)
542 if (detectedLines[i].error > limit)
544 detectedLines.erase(detectedLines.begin() + i);
549 maxError =
std::max(detectedLines[i].error, maxError);
552 if (!detectedLines.empty() && maxError > 0)
556 for (
size_t i = 0; i < detectedLines.size(); i++)
560 detectedLines[i].error = detectedLines[i].error / maxError + (1.0 -
std::min(length, 500.0) / 500.0);
562 std::sort(detectedLines.begin(), detectedLines.end(),
SortByError);
564 for (
size_t i = 0; i < detectedLines.size() && i < nrLines; i++)
570 verticalLines.push_back(cp);
578 if (detectedLines.size() == 1)
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)
587 verticalLines.push_back(cp);
595 verticalLines = detectedLines;
598 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)
VerticalLineVector FilterLines(Lines lines, double roll, const bool onlyVerticalLines)
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
HuginBase::CPVector _getFilteredLines(const HuginBase::Panorama &pano, const unsigned int imgNr, ImageType &image, vigra::BImage &mask, const unsigned int nrLines, const bool onlyVerticalLines)
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
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...
evaluate x, points are on a vertical line
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)
const bool IsVertical() const
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
evaluate y, points are on a horizontal line
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
vigra::BImage edgeMap2linePts(vigra::BImage &input)
marks line point
bool SortByError(const HuginBase::ControlPoint &cp1, const HuginBase::ControlPoint &cp2)
double outputExposureValue