Example #1
0
vector<UIntSet> getHDRStacks(const PanoramaData & pano, UIntSet allImgs, PanoramaOptions opts)
{
    vector<UIntSet> result;

    // if no images are available, return empty result vector
    if ( allImgs.empty() )
    {
        return result;
    }

    UIntSet stack;

    CalculateImageOverlap overlap(&pano);
    overlap.calculate(10);  // we are testing 10*10=100 points
    do {
        unsigned srcImg = *(allImgs.begin());
        stack.insert(srcImg);
        allImgs.erase(srcImg);

        // find all images that have a suitable overlap.
        for (UIntSet::iterator it = allImgs.begin(); it !=  allImgs.end(); ) {
            unsigned srcImg2 = *it;
            ++it;
            if(overlap.getOverlap(srcImg,srcImg2)>opts.outputStacksMinOverlap)
            {
                stack.insert(srcImg2);
                allImgs.erase(srcImg2);
            }
        }
        result.push_back(stack);
        stack.clear();
    } while (allImgs.size() > 0);

    return result;
}
Example #2
0
vector<UIntSet> getExposureLayers(const PanoramaData & pano, UIntSet allImgs, PanoramaOptions opts)
{
    vector<UIntSet> result;

    // if no images are available, return empty result vector
    if ( allImgs.empty() )
    {
        return result;
    }

    UIntSet stack;

    do {
        unsigned srcImg = *(allImgs.begin());
        stack.insert(srcImg);
        allImgs.erase(srcImg);

        // find all images that have a suitable overlap.
        SrcPanoImage simg = pano.getSrcImage(srcImg);
        double maxEVDiff = opts.outputLayersExposureDiff;
        for (UIntSet::iterator it = allImgs.begin(); it !=  allImgs.end(); ) {
            unsigned srcImg2 = *it;
            ++it;
            SrcPanoImage simg2 = pano.getSrcImage(srcImg2);
            if ( fabs(simg.getExposureValue() - simg2.getExposureValue()) < maxEVDiff )
            {
                stack.insert(srcImg2);
                allImgs.erase(srcImg2);
            }
        }
        result.push_back(stack);
        stack.clear();
    } while (allImgs.size() > 0);

    return result;
}
Example #3
0
int main(int argc, char *argv[])
{
    // parse arguments
    const char * optstring = "o:hn:pws";

    int c;
    string output;
    bool onlyPair = false;
    bool wholePano = false;
    bool skipOptimisation = false;
    double n = 2.0;
    while ((c = getopt (argc, argv, optstring)) != -1)
    {
        switch (c) {
        case 'o':
            output = optarg;
            break;
        case 'h':
            usage(argv[0]);
            return 0;
        case 'n':
            n = atof(optarg);
            if(n==0)
            {
                cerr <<"Invalid parameter: " << optarg << " is not valid real number" << endl;
                return 1;
            };
	        if (n<1.0) 
            {
		        cerr << "Invalid parameter: n must be at least 1" << endl;
		        return 1;
            };
            break;
        case 'p':
            onlyPair= true;
            break;
        case 'w':
            wholePano = true;
            break;
        case 's':
            skipOptimisation = true;
            break;
        case ':':
            cerr <<"Option -n requires a number" << endl;
            return 1;
            break;
        case '?':
            break;
        default:
            abort ();
        }
    }

    if (argc - optind != 1) 
    {
        usage(argv[0]);
        return 1;
    };
    
    if (onlyPair && wholePano)
    {
        cerr << "Options -p and -w can't used together" << endl;
        return 1;
    };

    string input=argv[optind];

    Panorama pano;
    ifstream prjfile(input.c_str());
    if (!prjfile.good()) {
        cerr << "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;
    }

    size_t nrImg=pano.getNrOfImages();
    if (nrImg < 2) 
    {
        cerr << "Panorama should consist of at least two images" << endl;
        return 1;
    }

    if (pano.getNrOfCtrlPoints() < 3)
    {
        cerr << "Panorama should contain at least 3 control point" << endl;
    };
    
    size_t cpremoved1=0;
    UIntSet CPtoRemove;
    // step 1 with pairwise optimisation
    if(!wholePano)
    {
        CPtoRemove=getCPoutsideLimit_pair(pano,n);
        if (CPtoRemove.size()>0)
            for(UIntSet::reverse_iterator it = CPtoRemove.rbegin(); it != CPtoRemove.rend(); ++it)
                pano.removeCtrlPoint(*it);
        cpremoved1=CPtoRemove.size();
    };

    // step 2 with optimisation of whole panorama
    bool unconnected=false;
    if(!onlyPair)
    {
        //check for unconnected images
        CPGraph graph;
        createCPGraph(pano, graph);
        CPComponents comps;
        int parts=findCPComponents(graph, comps);
        if (parts > 1) 
        {
            unconnected=true;
        }
        else
        {
            CPtoRemove.clear();
            if(skipOptimisation)
            {
                std::cout << endl << "Skipping optimisation, current image positions will be used." << endl;
            };
            CPtoRemove=getCPoutsideLimit(pano,n,skipOptimisation);
            if (CPtoRemove.size()>0)
                for(UIntSet::reverse_iterator it = CPtoRemove.rbegin(); it != CPtoRemove.rend(); ++it)
                    pano.removeCtrlPoint(*it);
        };
    };

    cout << endl;
    if(!wholePano)
        cout << "Removed " << cpremoved1 << " control points in step 1" << endl;
    if(!onlyPair)
        if(unconnected)
            cout <<"Skipped step 2 because of unconnected image pairs" << endl;
        else
            cout << "Removed " << CPtoRemove.size() << " control points in step 2" << endl;

    //write output
    OptimizeVector optvec = pano.getOptimizeVector();
    UIntSet imgs;
    fill_set(imgs,0, pano.getNrOfImages()-1);
 	// Set output .pto filename if not given
	if (output=="")
    {
        output=input.substr(0,input.length()-4).append("_clean.pto");
	}
    ofstream of(output.c_str());
    pano.printPanoramaScript(of, optvec, pano.getOptions(), imgs, false, hugin_utils::getPathPrefix(input));
    
    cout << endl << "Written output to " << output << endl;
    return 0;
}
CPVector AutoPanoSiftMultiRow::automatch(CPDetectorSetting &setting, Panorama & pano, const UIntSet & imgs,
                                     int nFeatures, int & ret_value, wxWindow *parent)
{
    CPVector cps;
    if (imgs.size() < 2) 
    {
        return cps;
    };
    std::vector<wxString> keyFiles(pano.getNrOfImages());
    //generate cp for every consecutive image pair
    unsigned int counter=0;
    for(UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); )
    {
        if(counter==imgs.size()-1)
            break;
        counter++;
        UIntSet ImagePair;
        ImagePair.clear();
        ImagePair.insert(*it);
        it++;
        ImagePair.insert(*it);
        AutoPanoSift matcher;
        CPVector new_cps;
        new_cps.clear();
        if(setting.IsTwoStepDetector())
            new_cps=matcher.automatch(setting, pano, ImagePair, nFeatures, keyFiles, ret_value, parent);
        else
            new_cps=matcher.automatch(setting, pano, ImagePair, nFeatures, ret_value, parent);
        if(new_cps.size()>0)
            AddControlPointsWithCheck(cps,new_cps);
        if(ret_value!=0)
        {
            Cleanup(setting, pano, imgs, keyFiles, parent);
            return cps;
        };
    };
    // now connect all image groups
    // generate temporary panorama to add all found cps
    UIntSet allImgs;
    fill_set(allImgs, 0, pano.getNrOfImages()-1);
    Panorama optPano=pano.getSubset(allImgs);
    for (CPVector::const_iterator it=cps.begin();it!=cps.end();++it)
        optPano.addCtrlPoint(*it);

    CPGraph graph;
    createCPGraph(optPano, graph);
    CPComponents comps;
    int n = findCPComponents(graph, comps);
    if(n>1)
    {
        UIntSet ImagesGroups;
        for(unsigned int i=0;i<n;i++)
        {
            ImagesGroups.insert(*(comps[i].begin()));
            if(comps[i].size()>1)
                ImagesGroups.insert(*(comps[i].rbegin()));
        };
        AutoPanoSift matcher;
        CPVector new_cps;
        if(setting.IsTwoStepDetector())
            new_cps=matcher.automatch(setting, optPano, ImagesGroups, nFeatures, keyFiles, ret_value, parent);
        else
            new_cps=matcher.automatch(setting, optPano, ImagesGroups, nFeatures, ret_value, parent);
        if(new_cps.size()>0)
            AddControlPointsWithCheck(cps,new_cps,&optPano);
        if(ret_value!=0)
        {
            Cleanup(setting, pano, imgs, keyFiles, parent);
            return cps;
        };
        createCPGraph(optPano,graph);
        n=findCPComponents(graph, comps);
    };
    if(n==1 && setting.GetOption())
    {
        //next steps happens only when all images are connected;
        //now optimize panorama
        PanoramaOptions opts = pano.getOptions();
        opts.setProjection(PanoramaOptions::EQUIRECTANGULAR);
        // calculate proper scaling, 1:1 resolution.
        // Otherwise optimizer distances are meaningless.
        opts.setWidth(30000, false);
        opts.setHeight(15000);

        optPano.setOptions(opts);
        int w = optPano.calcOptimalWidth();
        opts.setWidth(w);
        opts.setHeight(w/2);
        optPano.setOptions(opts);

        //generate optimize vector, optimize only yaw and pitch
        OptimizeVector optvars;
        const SrcPanoImage & anchorImage = optPano.getImage(opts.optimizeReferenceImage);
        for (unsigned i=0; i < optPano.getNrOfImages(); i++) 
        {
            std::set<std::string> imgopt;
            if(i==opts.optimizeReferenceImage)
            {
                //optimize only anchors pitch, not yaw
                imgopt.insert("p");
            }
            else
            {
                // do not optimize anchor image's stack for position.
                if(!optPano.getImage(i).YawisLinkedWith(anchorImage))
                {
                    imgopt.insert("p");
                    imgopt.insert("y");
                };
            };
            optvars.push_back(imgopt);
        }
        optPano.setOptimizeVector(optvars);

        // remove vertical and horizontal control points
        CPVector backupOldCPS = optPano.getCtrlPoints();
        CPVector backupNewCPS;
        for (CPVector::const_iterator it = backupOldCPS.begin(); it != backupOldCPS.end(); it++) {
            if (it->mode == ControlPoint::X_Y)
            {
                backupNewCPS.push_back(*it);
            }
        }
        optPano.setCtrlPoints(backupNewCPS);
        // do a first pairwise optimisation step
        HuginBase::AutoOptimise::autoOptimise(optPano,false);
        HuginBase::PTools::optimize(optPano);
        optPano.setCtrlPoints(backupOldCPS);
        //and find cp on overlapping images
        //work only on image pairs, which are not yet connected
        AutoPanoSiftPreAlign matcher;
        CPDetectorSetting newSetting;
        newSetting.SetProg(setting.GetProg());
        newSetting.SetArgs(setting.GetArgs());
        if(setting.IsTwoStepDetector())
        {
            newSetting.SetProgMatcher(setting.GetProgMatcher());
            newSetting.SetArgsMatcher(setting.GetArgsMatcher());
        };
        newSetting.SetOption(true);
        CPVector new_cps;
        if(setting.IsTwoStepDetector())
            new_cps=matcher.automatch(newSetting, optPano, imgs, nFeatures, keyFiles, ret_value, parent);
        else
            new_cps=matcher.automatch(newSetting, optPano, imgs, nFeatures, ret_value, parent);
        if(new_cps.size()>0)
            AddControlPointsWithCheck(cps,new_cps);
    };
    Cleanup(setting, pano, imgs, keyFiles, parent);
    return cps;
};
CPVector AutoPanoSiftPreAlign::automatch(CPDetectorSetting &setting, Panorama & pano, const UIntSet & imgs,
                                         int nFeatures, std::vector<wxString> &keyFiles, int & ret_value, wxWindow *parent)
{
    CPVector cps;
    if (imgs.size()<2) 
        return cps;
    DEBUG_ASSERT(keyFiles.size()==pano.getNrOfImages());

    vector<UIntSet> usedImages;
    usedImages.resize(pano.getNrOfImages());
    if(setting.GetOption())
    {
        //only work on not connected image pairs
        CPVector oldCps=pano.getCtrlPoints();
        for(unsigned i=0;i<oldCps.size();i++)
        {
            if(oldCps[i].mode==ControlPoint::X_Y)
            {
                usedImages[oldCps[i].image1Nr].insert(oldCps[i].image2Nr);
                usedImages[oldCps[i].image2Nr].insert(oldCps[i].image1Nr);
            };
        };
    };
    HuginBase::CalculateImageOverlap overlap(&pano);
    overlap.calculate(10);
    for(UIntSet::const_iterator it=imgs.begin();it!=imgs.end();it++)
    {
        UIntSet images;
        images.clear();
        images.insert(*it);
        UIntSet::const_iterator it2=it;
        for(++it2;it2!=imgs.end();it2++)
        {
            //check if this image pair was yet used
            if(set_contains(usedImages[*it2],*it))
                continue;
            //now check position
            if(overlap.getOverlap(*it,*it2)>0)
            {
                images.insert(*it2);
            };
        };
        if(images.size()<2)
            continue;
        //remember image pairs for later
        for(UIntSet::const_iterator img_it=images.begin();img_it!=images.end();img_it++)
            for(UIntSet::const_iterator img_it2=images.begin();img_it2!=images.end();img_it2++)
                usedImages[*img_it].insert(*img_it2);
        AutoPanoSift matcher;
        CPVector new_cps;
        if(setting.IsTwoStepDetector())
            new_cps=matcher.automatch(setting, pano, images, nFeatures, keyFiles, ret_value, parent);
        else
            new_cps=matcher.automatch(setting, pano, images, nFeatures, ret_value, parent);
        if(new_cps.size()>0)
            AddControlPointsWithCheck(cps,new_cps);
        if(ret_value!=0)
        {
            Cleanup(setting, pano, imgs, keyFiles, parent);
            return cps;
        };
    };
    Cleanup(setting, pano, imgs, keyFiles, parent);
    return cps;
};