SmallRemappedImageCache::MRemappedImage * SmallRemappedImageCache::getRemapped(const PanoramaData& pano, const PanoramaOptions & popts, unsigned int imgNr, vigra::Rect2D outputROI, AppBase::MultiProgressDisplay& progress) { // always map to HDR mode. curve and exposure is applied in preview window, for speed PanoramaOptions opts = popts; opts.outputMode = PanoramaOptions::OUTPUT_HDR; opts.outputExposureValue = 0.0; // return old image, if already in cache and if it has changed since the last rendering if (set_contains(m_images, imgNr)) { // return cached image if the parameters of the image have not changed SrcPanoImage oldParam = m_imagesParam[imgNr]; if (oldParam == pano.getSrcImage(imgNr) && m_panoOpts[imgNr].getHFOV() == opts.getHFOV() && m_panoOpts[imgNr].getWidth() == opts.getWidth() && m_panoOpts[imgNr].getHeight() == opts.getHeight() && m_panoOpts[imgNr].getProjection() == opts.getProjection() && m_panoOpts[imgNr].getProjectionParameters() == opts.getProjectionParameters() ) { DEBUG_DEBUG("using cached remapped image " << imgNr); return m_images[imgNr]; } } ImageCache::getInstance().softFlush(); typedef BasicImageView<RGBValue<unsigned char> > BRGBImageView; // typedef NumericTraits<PixelType>::RealPromote RPixelType; // remap image DEBUG_DEBUG("remapping image " << imgNr); // load image const SrcPanoImage & img = pano.getImage(imgNr); ImageCache::EntryPtr e = ImageCache::getInstance().getSmallImage(img.getFilename().c_str()); if ( (e->image8->width() == 0) && (e->image16->width() == 0) && (e->imageFloat->width() == 0) ) { throw std::runtime_error("could not retrieve small source image for preview generation"); } Size2D srcImgSize; if (e->image8->width() > 0) srcImgSize = e->image8->size(); else if (e->image16->width() > 0) srcImgSize = e->image16->size(); else srcImgSize = e->imageFloat->size(); MRemappedImage *remapped = new MRemappedImage; SrcPanoImage srcPanoImg = pano.getSrcImage(imgNr); // adjust distortion parameters for small preview image srcPanoImg.resize(srcImgSize); FImage srcFlat; // use complete image, by supplying an empty mask image BImage srcMask; if (img.getVigCorrMode() & SrcPanoImage::VIGCORR_FLATFIELD) { ImageCache::EntryPtr e = ImageCache::getInstance().getSmallImage(img.getFlatfieldFilename().c_str()); if (!e) { throw std::runtime_error("could not retrieve flatfield image for preview generation"); } if (e->image8->width()) { srcFlat.resize(e->image8->size()); copyImage(srcImageRange(*(e->image8), RGBToGrayAccessor<RGBValue<UInt8> >()), destImage(srcFlat)); } else if (e->image16->width()) { srcFlat.resize(e->image16->size()); copyImage(srcImageRange(*(e->image16), RGBToGrayAccessor<RGBValue<vigra::UInt16> >()), destImage(srcFlat)); } else { srcFlat.resize(e->imageFloat->size()); copyImage(srcImageRange(*(e->imageFloat), RGBToGrayAccessor<RGBValue<float> >()), destImage(srcFlat)); } } progress.pushTask(AppBase::ProgressTask("remapping", "", 0)); // compute the bounding output rectangle here! vigra::Rect2D outROI = estimateOutputROI(pano, opts, imgNr); DEBUG_DEBUG("srcPanoImg size: " << srcPanoImg.getSize() << " pano roi:" << outROI); if (e->imageFloat->width()) { // remap image remapImage(*(e->imageFloat), srcMask, srcFlat, srcPanoImg, opts, outROI, *remapped, progress); } else if (e->image16->width()) { // remap image remapImage(*(e->image16), srcMask, srcFlat, srcPanoImg, opts, outROI, *remapped, progress); } else { remapImage(*(e->image8), srcMask, srcFlat, srcPanoImg, opts, outROI, *remapped, progress); } progress.popTask(); m_images[imgNr] = remapped; m_imagesParam[imgNr] = pano.getSrcImage(imgNr); m_panoOpts[imgNr] = opts; return remapped; }
bool PanoDetector::loadProject() { ifstream ptoFile(_inputFile.c_str()); if (ptoFile.bad()) { cerr << "ERROR: could not open file: '" << _inputFile << "'!" << endl; return false; } _prefix=hugin_utils::getPathPrefix(_inputFile); if(_prefix.empty()) { // Get the current working directory: char* buffer; #ifdef _WINDOWS #define getcwd _getcwd #endif if((buffer=getcwd(NULL,0))!=NULL) { _prefix.append(buffer); free(buffer); _prefix=includeTrailingPathSep(_prefix); } }; _panoramaInfo->setFilePrefix(_prefix); AppBase::DocumentData::ReadWriteError err = _panoramaInfo->readData(ptoFile); if (err != AppBase::DocumentData::SUCCESSFUL) { cerr << "ERROR: couldn't parse panos tool script: '" << _inputFile << "'!" << endl; return false; } // Create a copy of panoramaInfo that will be used to define // image options _panoramaInfoCopy=_panoramaInfo->duplicate(); // Add images found in the project file to _filesData unsigned int nImg = _panoramaInfo->getNrOfImages(); unsigned int imgWithKeyfile=0; for (unsigned int imgNr = 0; imgNr < nImg; ++imgNr) { // insert the image in the map _filesData.insert(make_pair(imgNr, ImgData())); // get the data ImgData& aImgData = _filesData[imgNr]; // get a copy of image info SrcPanoImage img = _panoramaInfoCopy.getSrcImage(imgNr); // set the name aImgData._name = img.getFilename(); // modify image position in the copy img.setYaw(0); img.setRoll(0); img.setPitch(0); img.setX(0); img.setY(0); img.setZ(0); img.setActive(true); img.setResponseType(SrcPanoImage::RESPONSE_LINEAR); img.setExposureValue(0); _panoramaInfoCopy.setImage(imgNr,img); // Number pointing to image info in _panoramaInfo aImgData._number = imgNr; aImgData._needsremap=(img.getHFOV()>=65 && img.getProjection() != SrcPanoImage::FISHEYE_STEREOGRAPHIC); // set image detection size if(aImgData._needsremap) { _filesData[imgNr]._detectWidth = max(img.getSize().width(),img.getSize().height()); _filesData[imgNr]._detectHeight = max(img.getSize().width(),img.getSize().height()); } else { _filesData[imgNr]._detectWidth = img.getSize().width(); _filesData[imgNr]._detectHeight = img.getSize().height(); }; if (_downscale) { _filesData[imgNr]._detectWidth >>= 1; _filesData[imgNr]._detectHeight >>= 1; } // set image remapping options if(aImgData._needsremap) { aImgData._projOpts.setProjection(PanoramaOptions::STEREOGRAPHIC); aImgData._projOpts.setHFOV(250); aImgData._projOpts.setVFOV(250); aImgData._projOpts.setWidth(250); aImgData._projOpts.setHeight(250); // determine size of output image. // The old code did not work with images with images with a FOV // approaching 180 degrees vigra::Rect2D roi=estimateOutputROI(_panoramaInfoCopy,aImgData._projOpts,imgNr); double scalefactor = max((double)_filesData[imgNr]._detectWidth / roi.width(), (double)_filesData[imgNr]._detectHeight / roi.height() ); // resize output canvas vigra::Size2D canvasSize((int)aImgData._projOpts.getWidth() * scalefactor, (int)aImgData._projOpts.getHeight() * scalefactor); aImgData._projOpts.setWidth(canvasSize.width(), false); aImgData._projOpts.setHeight(canvasSize.height()); // set roi to cover the remapped input image roi = roi * scalefactor; _filesData[imgNr]._detectWidth = roi.width(); _filesData[imgNr]._detectHeight = roi.height(); aImgData._projOpts.setROI(roi); } // Specify if the image has an associated keypoint file aImgData._keyfilename = getKeyfilenameFor(_keypath,aImgData._name); ifstream keyfile(aImgData._keyfilename.c_str()); aImgData._hasakeyfile = keyfile.good(); if(aImgData._hasakeyfile) { imgWithKeyfile++; }; } //update masks, convert positive masks into negative masks //because positive masks works only if the images are on the final positions _panoramaInfoCopy.updateMasks(true); //if all images has keyfile, we don't need to load celeste model file if(nImg==imgWithKeyfile) { _celeste=false; }; return true; }
int main(int argc, char* argv[]) { // parse arguments const char* optstring = "o:t:h"; enum { MINOVERLAP=1000 }; static struct option longOptions[] = { {"output", required_argument, NULL, 'o' }, {"template", required_argument, NULL, 't'}, {"help", no_argument, NULL, 'h' }, 0 }; int c; int optionIndex = 0; string output; string templateFile; while ((c = getopt_long (argc, argv, optstring, longOptions,&optionIndex)) != -1) { switch (c) { case 'o': output = optarg; break; case 't': templateFile = optarg; if(!hugin_utils::FileExists(templateFile)) { cerr << "Error: Template \"" << templateFile << "\" not found." << endl; return 1; }; break; case 'h': usage(argv[0]); return 0; case ':': cerr <<"Option " << longOptions[optionIndex].name << " requires a parameter" << endl; return 1; break; case '?': break; default: abort (); } } if (argc - optind == 0) { cout << "Error: No project file given." << endl; return 1; }; if (argc - optind != 1) { cout << "Error: pto_template can only work on one project file at one time" << endl; return 1; }; if (templateFile.length()==0) { cerr << "Error: No template given." << endl; return 1; }; string input=argv[optind]; // read panorama Panorama pano; ifstream prjfile(input.c_str()); if (!prjfile.good()) { cerr << "Error: could not open script : " << input << endl; return 1; } pano.setFilePrefix(hugin_utils::getPathPrefix(input)); DocumentData::ReadWriteError err = pano.readData(prjfile); if (err != DocumentData::SUCCESSFUL) { cerr << "Error while parsing panos tool script: " << input << endl; cerr << "DocumentData::ReadWriteError code: " << err << endl; return 1; } if(pano.getNrOfImages()==0) { cerr << "Error: project file does not contains any image" << endl; cerr << "aborting processing" << endl; return 1; }; Panorama newPano; ifstream templateStream(templateFile.c_str()); if (!templateStream.good()) { cerr << "Error: could not open template script : " << templateFile << endl; return 1; } newPano.setFilePrefix(hugin_utils::getPathPrefix(templateFile)); err = newPano.readData(templateStream); if (err != DocumentData::SUCCESSFUL) { cerr << "Error while parsing template script: " << templateFile << endl; cerr << "DocumentData::ReadWriteError code: " << err << endl; return 1; } if (pano.getNrOfImages() != newPano.getNrOfImages()) { cerr << "Error: template expects " << newPano.getNrOfImages() << " images," << endl << " current project contains " << pano.getNrOfImages() << " images" << endl << " Could not apply template" << endl; return false; } // check image sizes, and correct parameters if required. for (unsigned int i = 0; i < newPano.getNrOfImages(); i++) { // check if image size is correct const SrcPanoImage & oldSrcImg = pano.getImage(i); SrcPanoImage newSrcImg = newPano.getSrcImage(i); // just keep the file name newSrcImg.setFilename(oldSrcImg.getFilename()); if (oldSrcImg.getSize() != newSrcImg.getSize()) { // adjust size properly. newSrcImg.resize(oldSrcImg.getSize()); } newPano.setSrcImage(i, newSrcImg); } // keep old control points. newPano.setCtrlPoints(pano.getCtrlPoints()); //write output UIntSet imgs; fill_set(imgs, 0, newPano.getNrOfImages()-1); // Set output .pto filename if not given if (output=="") { output=input.substr(0,input.length()-4).append("_template.pto"); } ofstream of(output.c_str()); newPano.printPanoramaScript(of, newPano.getOptimizeVector(), newPano.getOptions(), imgs, false, hugin_utils::getPathPrefix(input)); cout << endl << "Written output to " << output << endl; return 0; }