ComputeImageROI.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00026 #include "ComputeImageROI.h"
00027 
00028 #include <algorithm>
00029 #include <nona/RemappedPanoImage.h>
00030 #include <nona/RemappedPanoImage.h>
00031 
00032 
00033 
00034 namespace HuginBase {
00035 
00042 template <class TRANSFORM>
00043 void estimateImageRect(const SrcPanoImage & src,
00044                        const PanoramaOptions & dest,
00045                        TRANSFORM & transf,
00046                        vigra::Rect2D & imgRect);
00047     
00049 template <class TRANSFORM>
00050 void estimateImageAlpha(const SrcPanoImage & src,
00051                         const PanoramaOptions & dest,
00052                         TRANSFORM & transf,
00053                         vigra::Rect2D & imgRect,
00054                          vigra::BImage & alpha,
00055                          double & scale);
00056                          
00057         
00058     
00059 template <class TRANSFORM>
00060 void estimateImageAlpha(const SrcPanoImage & src,
00061                         const PanoramaOptions & dest,
00062                        TRANSFORM & transf,
00063                        vigra::Rect2D & imgRect,
00064                        vigra::BImage & alpha,
00065                        double & scale)
00066 {
00067     hugin_utils::FDiff2D ul, lr;
00068     ul.x = DBL_MAX;
00069     ul.y = DBL_MAX;
00070     lr.x = -DBL_MAX;
00071     lr.y = -DBL_MAX;
00072 
00073     // remap into a miniature version of the pano and use
00074     // that to check for boundaries. This should be much more
00075     // robust than the old code that tried to trace the boundaries
00076     // of the images using the inverse transform, which could be fooled
00077     // easily by fisheye images.
00078 
00079     double maxLength = 180;
00080     scale = std::min(maxLength/dest.getSize().x, maxLength/dest.getSize().y);
00081 
00082     // take dest roi into account...
00083     vigra::Size2D destSz;
00084     destSz.x = hugin_utils::ceili(dest.getSize().x * scale);
00085     destSz.y = hugin_utils::ceili(dest.getSize().y * scale);
00086     vigra::Rect2D destRect;
00087     destRect.setUpperLeft(vigra::Point2D (hugin_utils::floori(dest.getROI().left() * scale),
00088                           hugin_utils::floori(dest.getROI().top() * scale)));
00089     destRect.setLowerRight(vigra::Point2D (hugin_utils::ceili(dest.getROI().right() * scale),
00090                    hugin_utils::ceili(dest.getROI().bottom() * scale)));
00091     destRect = destRect & vigra::Rect2D(destSz);
00092 
00093     DEBUG_DEBUG("scale " << scale);
00094     DEBUG_DEBUG("dest roi " << dest.getROI());
00095     DEBUG_DEBUG("dest Sz: " << destSz);
00096     DEBUG_DEBUG("dest rect: " << destRect);
00097 
00098     hugin_utils::FDiff2D cropCenter;
00099     double radius2=0;
00100     if (src.getCropMode() == SrcPanoImage::CROP_CIRCLE) {
00101         cropCenter.x = src.getCropRect().left() + src.getCropRect().width()/2.0;
00102         cropCenter.y = src.getCropRect().top() + src.getCropRect().height()/2.0;
00103         radius2 = std::min(src.getCropRect().width()/2.0, src.getCropRect().height()/2.0);
00104         radius2 = radius2 * radius2;
00105     }
00106 
00107     // remap image
00108     vigra::BImage img(destSz.x, destSz.y, (unsigned char)0);
00109     for (int y=destRect.top(); y < destRect.bottom(); y++) {
00110         for (int x=destRect.left(); x < destRect.right(); x++) {
00111             // sample image
00112             // coordinates in real image pixels
00113             double sx,sy;
00114             transf.transformImgCoord(sx,sy, x/scale, y/scale);
00115             bool valid=true;
00116             if (src.getCropMode() == SrcPanoImage::CROP_CIRCLE) {
00117                 double dx = sx - cropCenter.x;
00118                 double dy = sy - cropCenter.y;
00119                 if (dx*dx + dy*dy > radius2) {
00120                         valid = false;
00121                 }
00122             } else if (!src.getCropRect().contains(vigra::Point2D(hugin_utils::roundi(sx), hugin_utils::roundi(sy))) ) {
00123                 valid = false;
00124             }
00125             if(valid && src.hasActiveMasks())
00126                 valid=!src.isInsideMasks(vigra::Point2D(hugin_utils::roundi(sx), hugin_utils::roundi(sy)));
00127 
00128             if (valid) {
00129                 img(x,y) = 255;
00130 /*                if ( ul.x > (x-1)/scale ) {
00131                     ul.x = (x-1)/scale;
00132                 }
00133                 if ( ul.y > (y-1)/scale ) {
00134                     ul.y = (y-1)/scale;
00135                 }
00136 
00137                 if ( lr.x < (x+1)/scale ) {
00138                     lr.x = (x+1)/scale;
00139                 }
00140                 if ( lr.y < (y+1)/scale ) {
00141                     lr.y = (y+1)/scale;
00142                 }
00143 */
00144             } else {
00145                 img(x,y) = 0;
00146             }
00147         }
00148     }
00149 
00150     alpha.resize(img.size());
00151 
00152         // dilate alpha image, to cover neighbouring pixels,
00153         // that may be valid in the full resolution image
00154     vigra::discDilation(vigra::srcImageRange(img),
00155                         vigra::destImage(alpha), 1);
00156 
00157     ul.x = destRect.right();
00158     ul.y = destRect.bottom();
00159     lr.x = destRect.left();
00160     lr.y = destRect.top();
00161 
00162     for (int y=destRect.top(); y < destRect.bottom(); y++) {
00163         for (int x=destRect.left(); x < destRect.right(); x++) {
00164             if (alpha(x,y)) {
00165                 if ( ul.x > x ) {
00166                     ul.x = x;
00167                 }
00168                 if ( ul.y > y ) {
00169                     ul.y = y;
00170                 }
00171 
00172                 if ( lr.x < x ) {
00173                     lr.x = x;
00174                 }
00175                 if ( lr.y < y ) {
00176                     lr.y = y;
00177                 }
00178             }
00179         }
00180     }
00181 
00182     // check if we have found some pixels..
00183     if ( ul.x == destRect.right() || ul.y == destRect.bottom() 
00184          || lr.x == destRect.left()|| lr.y == destRect.top() ) {
00185 
00186         // no valid pixel found. return empty ROI
00187         imgRect = vigra::Rect2D();
00188 
00189         initImage(img.upperLeft()+destRect.upperLeft(), 
00190                   img.upperLeft()+destRect.lowerRight(),
00191                   img.accessor(),0);
00192         /*
00193         // no valid pixel.. strange.. either there is no image here, or we have
00194         // overlooked some pixel.. to be on the safe side. remap the whole image here...
00195         imgRect = dest.getROI();
00196         alpha.resize(img.size().x, img.size().y, 0);
00197         initImage(img.upperLeft()+destRect.upperLeft(), 
00198                   img.upperLeft()+destRect.lowerRight(),
00199                   img.accessor(),255);
00200         */
00201     } else {
00202         // bounding rect after scan
00203         DEBUG_DEBUG("ul: " << ul << "  lr: " << lr);
00204         ul.x = (ul.x)/scale;
00205         ul.y = (ul.y)/scale;
00206         lr.x = (lr.x+1)/scale;
00207         lr.y = (lr.y+1)/scale;
00208         imgRect.setUpperLeft(vigra::Point2D(hugin_utils::roundi(ul.x), hugin_utils::roundi(ul.y)));
00209         imgRect.setLowerRight(vigra::Point2D(hugin_utils::roundi(lr.x), hugin_utils::roundi(lr.y)));
00210         // ensure that the roi is inside the destination rect
00211         imgRect = dest.getROI() & imgRect;
00212         DEBUG_DEBUG("bounding box: " << imgRect);
00213     }
00214 
00215 }
00216 
00223 template <class TRANSFORM>
00224 void estimateImageRect(const SrcPanoImage & src, const PanoramaOptions & dest,
00225                        TRANSFORM & transf, vigra::Rect2D & imgRect)
00226 {
00227     vigra::BImage img;
00228     double scale;
00229     estimateImageAlpha(src, dest, transf, imgRect, img, scale);
00230 }
00231 
00232     vigra::Rect2D estimateOutputROI(const PanoramaData & pano, const PanoramaOptions & opts, unsigned i)
00233     {
00234         vigra::Rect2D imageRect;
00235         SrcPanoImage srcImg = pano.getSrcImage(i);
00236         PTools::Transform transf;
00237         transf.createTransform(srcImg, opts);
00238         estimateImageRect(srcImg, opts, transf, imageRect);
00239         return imageRect;
00240     }
00241 
00242     std::vector<vigra::Rect2D> ComputeImageROI::computeROIS(const PanoramaData& panorama,
00243                                                             const PanoramaOptions & opts,
00244                                                             const UIntSet & images)
00245     {
00246         std::vector<vigra::Rect2D> res;
00247         for (UIntSet::const_iterator it = images.begin(); 
00248              it != images.end(); ++it)
00249         {
00250             res.push_back(estimateOutputROI(panorama, panorama.getOptions(), *it));
00251         }
00252         return res;
00253     }
00254 
00255 }

Generated on 5 Dec 2016 for Hugintrunk by  doxygen 1.4.7