00001
00030 #include "Stitcher.h"
00031
00032 #include <vigra/stdimage.hxx>
00033
00034 namespace HuginBase {
00035 namespace Nona {
00036
00037 using namespace std;
00038 using namespace vigra;
00039 using namespace vigra_ext;
00040
00041
00046 void estimateBlendingOrder(const PanoramaData & pano, UIntSet images, vector<unsigned int> & blendOrder)
00047 {
00048 unsigned int nImg = images.size();
00049 DEBUG_ASSERT(nImg > 0);
00050
00051 typedef RemappedPanoImage<vigra::BRGBImage, vigra::BImage> RPImg;
00052
00053 PanoramaOptions opts = pano.getOptions();
00054
00055 opts.setWidth(400);
00056 Size2D size(opts.getWidth(), opts.getHeight());
00057 Rect2D completeAlphaROI(size);
00058
00059 std::map<unsigned int, RemappedPanoImage<vigra::BRGBImage, vigra::BImage> * > rimg;
00060 std::map<unsigned int, RemappedPanoImage<vigra::BRGBImage, vigra::BImage> * >::iterator rimgIter;
00061
00062 BImage alpha(size);
00063 Rect2D alphaROI;
00064
00065 for (UIntSet::iterator it = images.begin(); it != images.end(); ++it)
00066 {
00067
00068 rimg[*it] = new RPImg;
00069 rimg[*it]->setPanoImage(pano.getSrcImage(*it), opts, vigra::Rect2D(size));
00070 rimg[*it]->calcAlpha();
00071 #ifdef DEBUG
00072
00073 #endif
00074 }
00075
00076 int firstImg = *(images.begin());
00077
00078 alphaROI = rimg[firstImg]->boundingBox();
00079
00080 alphaROI = alphaROI & completeAlphaROI;
00081 DEBUG_DEBUG("alphaROI: " << alphaROI);
00082 DEBUG_DEBUG("alpha size: " << alpha.size());
00083 copyImage(applyRect(alphaROI, vigra_ext::srcMaskRange(*(rimg[firstImg]))),
00084
00085 applyRect(alphaROI, destImage(alpha)));
00086
00087 Rect2D overlap;
00088
00089 while (images.size() > 0) {
00090 unsigned int maxSize = 0;
00091 unsigned int choosenImg = *(images.begin());
00092
00093 for (UIntSet::iterator it = images.begin(); it != images.end(); ++it) {
00094
00095 DEBUG_DEBUG("examing overlap with image " << *it);
00096
00097 overlap = alphaROI & rimg[*it]->boundingBox();
00098 if (!overlap.isEmpty()) {
00099 DEBUG_DEBUG("ROI intersects: " << overlap.upperLeft()
00100 << " to " << overlap.lowerRight());
00101
00102
00103 if (overlap.area() > (int) maxSize) {
00104 OverlapSizeCounter counter;
00105 inspectTwoImages(applyRect(overlap, srcMaskRange(*(rimg[*it]))),
00106 applyRect(overlap, srcImage(alpha)),
00107 counter);
00108 DEBUG_DEBUG("overlap size in pixel: " << counter.getSize());
00109 if (counter.getSize() > maxSize) {
00110 choosenImg = *it;
00111 maxSize = counter.getSize();
00112 }
00113 }
00114 }
00115 }
00116
00117 blendOrder.push_back(choosenImg);
00118 images.erase(choosenImg);
00119
00120 alphaROI = alphaROI | rimg[choosenImg]->boundingBox();
00121 alphaROI = alphaROI & completeAlphaROI;
00122 }
00123
00124 for (rimgIter = rimg.begin(); rimgIter != rimg.end(); rimgIter++) {
00125 delete rimgIter->second;
00126 }
00127 }
00128
00129
00137 void stitchPanorama(const PanoramaData & pano,
00138 const PanoramaOptions & opt,
00139 AppBase::MultiProgressDisplay & progress,
00140 const std::string & basename,
00141 const UIntSet & usedImgs)
00142 {
00143 DEBUG_ASSERT(pano.getNrOfImages() > 0);
00144
00145
00146 unsigned int imgNr = *(usedImgs.begin());
00147 string fname = pano.getImage(imgNr).getFilename().c_str();
00148 DEBUG_DEBUG("Probing image: " << fname);
00149 vigra::ImageImportInfo info(fname.c_str());
00150 std::string pixelType = info.getPixelType();
00151 int bands = info.numBands();
00152 int extraBands = info.numExtraBands();
00153
00154
00155 for (UIntSet::const_iterator it = usedImgs.begin()++; it != usedImgs.end(); ++it) {
00156 vigra::ImageImportInfo info2(pano.getImage(*it).getFilename().c_str());
00157 if ( pixelType != info2.getPixelType() ) {
00158 UTILS_THROW(std::runtime_error, "image " <<
00159 pano.getImage(*it).getFilename() << " uses " <<
00160 info2.getPixelType() << " valued pixel, while " <<
00161 pano.getImage(0).getFilename() << " uses: " << pixelType);
00162 return;
00163 }
00164
00165 if (info2.numBands() - info2.numExtraBands() != bands - extraBands) {
00166 UTILS_THROW(std::runtime_error, "image " <<
00167 pano.getImage(*it).getFilename() << " has " <<
00168 info2.numBands() << " channels, while " <<
00169 pano.getImage(0).getFilename() << " uses: " << bands);
00170 return;
00171 }
00172 }
00173
00174 PanoramaOptions opts = opt;
00175 if (opts.outputMode == PanoramaOptions::OUTPUT_HDR) {
00176 if (opts.outputPixelType.size() == 0) {
00177 opts.outputPixelType = "FLOAT";
00178 }
00179 } else {
00180
00181 opts.outputEMoRParams = pano.getSrcImage(0).getEMoRParams();
00182 if (opts.outputPixelType.size() == 0) {
00183 opts.outputPixelType = pixelType;
00184 } else {
00185
00186
00187 pixelType = opts.outputPixelType;
00188 }
00189 }
00190
00191 #if 1
00192 if (opts.outputMode == PanoramaOptions::OUTPUT_HDR) {
00193 if (bands == 1 || bands == 2 && extraBands == 1) {
00194 stitchPanoIntern<FImage,BImage>(pano, opts, progress, basename, usedImgs);
00195 } else if (bands == 3 || bands == 4 && extraBands == 1) {
00196 stitchPanoIntern<FRGBImage,BImage>(pano, opts, progress, basename, usedImgs);
00197 } else {
00198 DEBUG_ERROR("unsupported depth, only images with 1 and 3 channel images are supported");
00199 throw std::runtime_error("unsupported depth, only images with 1 and 3 channel images are supported");
00200 return;
00201 }
00202 } else {
00203
00204 if (bands == 1 || bands == 2 && extraBands == 1) {
00205 if (pixelType == "UINT8"||
00206 pixelType == "INT16" ||
00207 pixelType == "UINT16" )
00208 {
00209 stitchPanoGray_8_16(pano, opts, progress, basename, usedImgs, pixelType.c_str());
00210 } else {
00211 stitchPanoGray_32_float(pano, opts, progress, basename, usedImgs, pixelType.c_str());
00212 }
00213 } else if (bands == 3 || bands == 4 && extraBands == 1) {
00214 if (pixelType == "UINT8" ||
00215 pixelType == "INT16" ||
00216 pixelType == "UINT16" )
00217 {
00218 stitchPanoRGB_8_16(pano, opts, progress, basename, usedImgs, pixelType.c_str());
00219 } else {
00220 stitchPanoRGB_32_float(pano, opts, progress, basename, usedImgs, pixelType.c_str());
00221 }
00222 }
00223 }
00224 #else
00225
00226 if (bands == 1 || bands == 2 && extraBands == 1) {
00227 stitchPanoIntern<FImage,BImage>(pano, opts, progress, basename, usedImgs);
00228 } else if (bands == 3 || bands == 4 && extraBands == 1) {
00229 stitchPanoIntern<FRGBImage,BImage>(pano, opts, progress, basename, usedImgs);
00230 } else {
00231 DEBUG_ERROR("unsupported depth, only images with 1 and 3 channel images are supported");
00232 throw std::runtime_error("unsupported depth, only images with 1 and 3 channel images are supported");
00233 return;
00234 }
00235 #endif
00236 }
00237
00238
00239 }
00240 }
00241