Hugin trunk 0.1
Loading...
Searching...
No Matches
ComputeImageROI.cpp
Go to the documentation of this file.
1// -*- c-basic-offset: 4 -*-
26#include "ComputeImageROI.h"
27
28#include <algorithm>
31
32
33
34namespace HuginBase {
35
42template <class TRANSFORM>
44 const PanoramaOptions & dest,
46 vigra::Rect2D & imgRect,
47 vigra::BImage & alpha,
48 double & scale,
49 double maxLength = 180.0)
50{
52 ul.x = DBL_MAX;
53 ul.y = DBL_MAX;
54 lr.x = -DBL_MAX;
55 lr.y = -DBL_MAX;
56
57 // remap into a miniature version of the pano and use
58 // that to check for boundaries. This should be much more
59 // robust than the old code that tried to trace the boundaries
60 // of the images using the inverse transform, which could be fooled
61 // easily by fisheye images.
62
63 scale = std::min(maxLength/dest.getSize().x, maxLength/dest.getSize().y);
64
65 // take dest roi into account...
66 vigra::Size2D destSz;
67 destSz.x = hugin_utils::ceili(dest.getSize().x * scale);
68 destSz.y = hugin_utils::ceili(dest.getSize().y * scale);
69 vigra::Rect2D destRect;
70 destRect.setUpperLeft(vigra::Point2D (hugin_utils::floori(dest.getROI().left() * scale),
71 hugin_utils::floori(dest.getROI().top() * scale)));
72 destRect.setLowerRight(vigra::Point2D (hugin_utils::ceili(dest.getROI().right() * scale),
73 hugin_utils::ceili(dest.getROI().bottom() * scale)));
74 destRect = destRect & vigra::Rect2D(destSz);
75
76 DEBUG_DEBUG("scale " << scale);
77 DEBUG_DEBUG("dest roi " << dest.getROI());
78 DEBUG_DEBUG("dest Sz: " << destSz);
79 DEBUG_DEBUG("dest rect: " << destRect);
80
82 double radius2=0;
83 if (src.getCropMode() == SrcPanoImage::CROP_CIRCLE) {
84 cropCenter.x = src.getCropRect().left() + src.getCropRect().width()/2.0;
85 cropCenter.y = src.getCropRect().top() + src.getCropRect().height()/2.0;
86 radius2 = std::min(src.getCropRect().width()/2.0, src.getCropRect().height()/2.0);
88 }
89
90 // remap image
91 vigra::BImage img(destSz.x, destSz.y, (unsigned char)0);
92 for (int y=destRect.top(); y < destRect.bottom(); y++) {
93 for (int x=destRect.left(); x < destRect.right(); x++) {
94 // sample image
95 // coordinates in real image pixels
96 double sx,sy;
97 transf.transformImgCoord(sx,sy, x/scale, y/scale);
98 bool valid=true;
99 if (src.getCropMode() == SrcPanoImage::CROP_CIRCLE) {
100 double dx = sx - cropCenter.x;
101 double dy = sy - cropCenter.y;
102 if (dx*dx + dy*dy > radius2) {
103 valid = false;
104 }
105 } else if (!src.getCropRect().contains(vigra::Point2D(hugin_utils::roundi(sx), hugin_utils::roundi(sy))) ) {
106 valid = false;
107 }
108 if(valid && src.hasActiveMasks())
109 valid=!src.isInsideMasks(vigra::Point2D(hugin_utils::roundi(sx), hugin_utils::roundi(sy)));
110
111 if (valid) {
112 img(x,y) = 255;
113/* if ( ul.x > (x-1)/scale ) {
114 ul.x = (x-1)/scale;
115 }
116 if ( ul.y > (y-1)/scale ) {
117 ul.y = (y-1)/scale;
118 }
119
120 if ( lr.x < (x+1)/scale ) {
121 lr.x = (x+1)/scale;
122 }
123 if ( lr.y < (y+1)/scale ) {
124 lr.y = (y+1)/scale;
125 }
126*/
127 } else {
128 img(x,y) = 0;
129 }
130 }
131 }
132
133 alpha.resize(img.size());
134
135 // dilate alpha image, to cover neighbouring pixels,
136 // that may be valid in the full resolution image
137 vigra::discDilation(vigra::srcImageRange(img),
138 vigra::destImage(alpha), 1);
139
140 ul.x = destRect.right();
141 ul.y = destRect.bottom();
142 lr.x = destRect.left();
143 lr.y = destRect.top();
144
145 for (int y=destRect.top(); y < destRect.bottom(); y++) {
146 for (int x=destRect.left(); x < destRect.right(); x++) {
147 if (alpha(x,y)) {
148 if ( ul.x > x ) {
149 ul.x = x;
150 }
151 if ( ul.y > y ) {
152 ul.y = y;
153 }
154
155 if ( lr.x < x ) {
156 lr.x = x;
157 }
158 if ( lr.y < y ) {
159 lr.y = y;
160 }
161 }
162 }
163 }
164
165 // check if we have found some pixels..
166 if ( ul.x == destRect.right() || ul.y == destRect.bottom()
167 || lr.x == destRect.left()|| lr.y == destRect.top() ) {
168
169 // no valid pixel found. return empty ROI
170 imgRect = vigra::Rect2D();
171
172 initImage(img.upperLeft()+destRect.upperLeft(),
173 img.upperLeft()+destRect.lowerRight(),
174 img.accessor(),0);
175 /*
176 // no valid pixel.. strange.. either there is no image here, or we have
177 // overlooked some pixel.. to be on the safe side. remap the whole image here...
178 imgRect = dest.getROI();
179 alpha.resize(img.size().x, img.size().y, 0);
180 initImage(img.upperLeft()+destRect.upperLeft(),
181 img.upperLeft()+destRect.lowerRight(),
182 img.accessor(),255);
183 */
184 } else {
185 // bounding rect after scan
186 DEBUG_DEBUG("ul: " << ul << " lr: " << lr);
187 ul.x = (ul.x)/scale;
188 ul.y = (ul.y)/scale;
189 lr.x = (lr.x+1)/scale;
190 lr.y = (lr.y+1)/scale;
191 imgRect.setUpperLeft(vigra::Point2D(hugin_utils::roundi(ul.x), hugin_utils::roundi(ul.y)));
192 imgRect.setLowerRight(vigra::Point2D(hugin_utils::roundi(lr.x), hugin_utils::roundi(lr.y)));
193 // ensure that the roi is inside the destination rect
194 imgRect = dest.getROI() & imgRect;
195 DEBUG_DEBUG("bounding box: " << imgRect);
196 }
197
198}
199
206template <class TRANSFORM>
208 TRANSFORM & transf, vigra::Rect2D & imgRect, double maxLength = 180.0)
209{
210 vigra::BImage img;
211 double scale;
213}
214
215 vigra::Rect2D estimateOutputROI(const PanoramaData & pano, const PanoramaOptions & opts, unsigned i, const double maxLength)
216 {
217 vigra::Rect2D imageRect;
222 return imageRect;
223 }
224
225 std::vector<vigra::Rect2D> ComputeImageROI::computeROIS(const PanoramaData& panorama,
226 const PanoramaOptions & opts,
227 const UIntSet & images)
228 {
229 std::vector<vigra::Rect2D> res;
230 for (UIntSet::const_iterator it = images.begin();
231 it != images.end(); ++it)
232 {
233 res.push_back(estimateOutputROI(panorama, opts, *it));
234 }
235 return res;
236 }
237
238}
Contains functions to transform whole images.
static std::vector< vigra::Rect2D > computeROIS(const PanoramaData &panorama, const PanoramaOptions &opts, const UIntSet &images)
Holds transformations for Image -> Pano and the other way.
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
Model for a panorama.
virtual SrcPanoImage getSrcImage(unsigned imgNr) const =0
get a complete description of a source image
Panorama image options.
All variables of a source image.
#define DEBUG_DEBUG(msg)
Definition utils.h:68
mainly consists of wrapper around the pano tools library, to assist in ressource management and to pr...
Definition wxcms.cpp:39
void estimateImageRect(const SrcPanoImage &src, const PanoramaOptions &dest, TRANSFORM &transf, vigra::Rect2D &imgRect, double maxLength=180.0)
calculate the outline of the image
void estimateImageAlpha(const SrcPanoImage &src, const PanoramaOptions &dest, TRANSFORM &transf, vigra::Rect2D &imgRect, vigra::BImage &alpha, double &scale, double maxLength=180.0)
calculate the outline of the image
vigra::Rect2D estimateOutputROI(const PanoramaData &pano, const PanoramaOptions &opts, unsigned i, const double maxLength)
std::set< unsigned int > UIntSet
int floori(double x)
Definition hugin_math.h:65
int roundi(T x)
Definition hugin_math.h:73
int ceili(double x)
Definition hugin_math.h:60
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