1 // -*- c-basic-offset: 4 -*-
2 
3 /** @file ExtractPoints.h
4  *
5  *  @brief helper procedure for photometric optimizer on command line
6  *
7  *  @author Pablo d'Angelo <pablo.dangelo@web.de>
8  *
9  *  $Id$
10  *
11  */
12 
13 /**
14  *  This program is free software; you can redistribute it and/or
15  *  modify it under the terms of the GNU General Public
16  *  License as published by the Free Software Foundation; either
17  *  version 2 of the License, or (at your option) any later version.
18  *
19  *  This software is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  *  General Public License for more details.
23  *
24  *  You should have received a copy of the GNU General Public
25  *  License along with this software. If not, see
26  *  <http://www.gnu.org/licenses/>.
27  *
28  */
29 
30 #include <hugin_basic.h>
31 
32 #include <vigra/error.hxx>
33 #include <vigra/impex.hxx>
34 
35 #include <vigra_ext/Pyramid.h>
36 #include <vigra_ext/impexalpha.hxx>
37 #include <algorithms/point_sampler/PointSampler.h>
38 
39 template<class ImageType>
loadImagesPyr(std::vector<std::string> files,int pyrLevel,int verbose,HuginBase::LimitIntensityVector & limits,float & imageStepSize)40 std::vector<ImageType *> loadImagesPyr(std::vector<std::string> files, int pyrLevel, int verbose, HuginBase::LimitIntensityVector& limits, float& imageStepSize)
41 {
42     std::vector<ImageType *> srcImgs(files.size());
43     limits.resize(srcImgs.size());
44 #ifdef _WIN32
45     // init vigra codec manager before threaded section
46     // otherwise there could be sometimes race conditions
47     // which results in exceptions
48     std::string s = vigra::impexListExtensions();
49 #endif
50 #pragma omp parallel for schedule(dynamic)
51     for (int i=0; i < files.size(); i++) {
52         ImageType * tImg = new ImageType();
53         ImageType * tImg2 = new ImageType();
54         std::ostringstream buf;
55         vigra::ImageImportInfo info(files[i].c_str());
56         tImg->resize(info.size());
57         if (verbose)
58             buf << "loading: " << files[i] << std::endl;
59 
60         const std::string pixelType(info.getPixelType());
61         if (info.numExtraBands() == 1) {
62             // dummy mask
63             vigra::BImage mask(info.size());
64             vigra::importImageAlpha(info, vigra::destImage(*tImg), vigra::destImage(mask));
65             if (pixelType == "FLOAT" || pixelType == "DOUBLE")
66             {
67                 vigra_ext::FindComponentsMinMax<float> minmax;
68                 vigra::inspectImageIf(vigra::srcImageRange(*tImg), vigra::srcImage(mask), minmax);
69                 imageStepSize = std::min(imageStepSize, (minmax.max - minmax.min) / 16384.0f);
70             };
71         } else {
72             vigra::importImage(info, vigra::destImage(*tImg));
73             if (pixelType == "FLOAT" || pixelType == "DOUBLE")
74             {
75                 vigra_ext::FindComponentsMinMax<float> minmax;
76                 vigra::inspectImage(vigra::srcImageRange(*tImg), minmax);
77                 imageStepSize = std::min(imageStepSize, (minmax.max - minmax.min) / 16384.0f);
78             };
79         }
80         float div = 1;
81         limits[i] = HuginBase::LimitIntensity(HuginBase::LimitIntensity::LIMIT_FLOAT);
82         if (pixelType== "UINT8") {
83             div = 255;
84             limits[i] = HuginBase::LimitIntensity(HuginBase::LimitIntensity::LIMIT_UINT8);
85             imageStepSize = std::min(imageStepSize, 1 / 255.0f);
86 
87         } else if (pixelType=="UINT16") {
88             div = (1<<16)-1;
89             limits[i] = HuginBase::LimitIntensity(HuginBase::LimitIntensity::LIMIT_UINT16);
90             imageStepSize = std::min(imageStepSize, 1 / 65536.0f);
91         }
92 
93         if (pyrLevel) {
94             ImageType * swap;
95             // create downscaled image
96             if (verbose > 0) {
97                 buf << "downscaling: ";
98             }
99             for (int l=pyrLevel; l > 0; l--) {
100                 if (verbose > 0) {
101                     buf << tImg->size().x << "x" << tImg->size().y << "  " << std::flush;
102                 }
103                 vigra_ext::reduceToNextLevel(*tImg, *tImg2);
104                 swap = tImg;
105                 tImg = tImg2;
106                 tImg2 = swap;
107             }
108             if (verbose > 0)
109                 buf << std::endl;
110         }
111         if (div > 1) {
112             div = 1/div;
113             transformImage(vigra::srcImageRange(*tImg), vigra::destImage(*tImg),
114                            vigra::functor::Arg1()*vigra::functor::Param(div));
115         }
116         srcImgs[i]=tImg;
117         delete tImg2;
118         if (verbose > 0)
119         {
120             std::cout << buf.str();
121         };
122     }
123     return srcImgs;
124 }
125 
126 
127 // needs 2.0 progress steps
loadImgsAndExtractPoints(HuginBase::Panorama pano,int nPoints,int pyrLevel,bool randomPoints,AppBase::ProgressDisplay & progress,std::vector<vigra_ext::PointPairRGB> & points,int verbose,float & imageStepSize)128 void loadImgsAndExtractPoints(HuginBase::Panorama pano, int nPoints, int pyrLevel, bool randomPoints, AppBase::ProgressDisplay& progress, std::vector<vigra_ext::PointPairRGB> & points, int verbose, float& imageStepSize)
129 {
130     // extract file names
131     std::vector<std::string> files;
132     for (size_t i=0; i < pano.getNrOfImages(); i++)
133         files.push_back(pano.getImage(i).getFilename());
134 
135     std::vector<vigra::FRGBImage*> images;
136     HuginBase::LimitIntensityVector limits;
137     imageStepSize = 1 / 255.0f;
138 
139     // try to load the images.
140     images = loadImagesPyr<vigra::FRGBImage>(files, pyrLevel, verbose, limits, imageStepSize);
141 
142     progress.setMessage("Sampling points");
143     if(randomPoints)
144         points = HuginBase::RandomPointSampler(pano, &progress, images, limits, nPoints).execute().getResultPoints();
145     else
146         points = HuginBase::AllPointSampler(pano, &progress, images, limits, nPoints).execute().getResultPoints();
147     progress.taskFinished();
148 }
149