@@ -87,6 +87,8 @@ int aliceVision_main(int argc, char** argv)
8787 std::string outputFolder;
8888 std::vector<std::string> featuresFolders;
8989 std::vector<std::string> matchesFolders;
90+ std::string filterA = " " ;
91+ std::string filterB = " " ;
9092
9193 // user optional parameters
9294
@@ -107,7 +109,9 @@ int aliceVision_main(int argc, char** argv)
107109 po::options_description optionalParams (" Optional parameters" );
108110 optionalParams.add_options ()
109111 (" describerTypes,d" , po::value<std::string>(&describerTypesName)->default_value (describerTypesName),
110- EImageDescriberType_informations ().c_str ());
112+ EImageDescriberType_informations ().c_str ())
113+ (" filterA" , po::value<std::string>(&filterA)->default_value (filterA), " Restrict one of the two views to be this." )
114+ (" filterB" , po::value<std::string>(&filterB)->default_value (filterB), " Restrict one of the two views to be this." );
111115 // clang-format on
112116
113117 CmdLine cmdline (" AliceVision exportMatches" );
@@ -118,6 +122,7 @@ int aliceVision_main(int argc, char** argv)
118122 return EXIT_FAILURE;
119123 }
120124
125+ // Make sure we have somewhere to write images
121126 if (outputFolder.empty ())
122127 {
123128 ALICEVISION_LOG_ERROR (" It is an invalid output folder" );
@@ -131,9 +136,35 @@ int aliceVision_main(int argc, char** argv)
131136 ALICEVISION_LOG_ERROR (" The input SfMData file '" << sfmDataFilename << " ' cannot be read." );
132137 return EXIT_FAILURE;
133138 }
139+
140+ // Create filters from input parameters
141+ IndexT indexFilterA = UndefinedIndexT;
142+ IndexT indexFilterB = UndefinedIndexT;
134143
135- // load SfM Scene regions
144+ if (!filterA.empty () || !filterB.empty ())
145+ {
146+ if (!filterA.empty ())
147+ {
148+ indexFilterA = sfmData.findView (filterA);
149+ if (indexFilterA == UndefinedIndexT)
150+ {
151+ ALICEVISION_LOG_ERROR (" Could not find corresponding view for : " + filterA);
152+ return EXIT_FAILURE;
153+ }
154+ }
155+
156+ if (!filterB.empty ())
157+ {
158+ indexFilterB = sfmData.findView (filterB);
159+ if (indexFilterB == UndefinedIndexT)
160+ {
161+ ALICEVISION_LOG_ERROR (" Could not find corresponding view for : " + filterB);
162+ return EXIT_FAILURE;
163+ }
164+ }
165+ }
136166
167+ // load SfM Scene regions
137168 // get imageDescriberMethodType
138169 std::vector<EImageDescriberType> describerMethodTypes = EImageDescriberType_stringToEnums (describerTypesName);
139170
@@ -164,87 +195,126 @@ int aliceVision_main(int argc, char** argv)
164195 const std::size_t I = iter->first ;
165196 const std::size_t J = iter->second ;
166197
167- const View* viewI = sfmData.getViews ().at (I).get ();
168- const View* viewJ = sfmData.getViews ().at (J).get ();
169198
170- const std::string viewImagePathI = viewI->getImage ().getImagePath ();
171- const std::string viewImagePathJ = viewJ->getImage ().getImagePath ();
199+ // Apply filter A
200+ if (indexFilterA != UndefinedIndexT)
201+ {
202+ if (I != indexFilterA && J != indexFilterA)
203+ {
204+ continue ;
205+ }
206+ }
207+
208+ // Apply filter B
209+ if (indexFilterB != UndefinedIndexT)
210+ {
211+ if (I != indexFilterB && J != indexFilterB)
212+ {
213+ continue ;
214+ }
215+ }
216+
217+ const View & viewI = sfmData.getView (I);
218+ const View & viewJ = sfmData.getView (J);
219+
220+ const std::string viewImagePathI = viewI.getImage ().getImagePath ();
221+ const std::string viewImagePathJ = viewJ.getImage ().getImagePath ();
172222
173- std::string destFilename_I ;
174- std::string destFilename_J ;
223+ std::string destFilenameI ;
224+ std::string destFilenameJ ;
175225 {
176226 fs::path origImgPath (viewImagePathI);
177227 std::string origFilename = origImgPath.stem ().string ();
178228 image::Image<image::RGBfColor> originalImage;
179229 image::readImage (viewImagePathI, originalImage, image::EImageColorSpace::LINEAR);
180- destFilename_I = (fs::path (outputFolder) / (origFilename + " .png" )).string ();
181- image::writeImage (destFilename_I , originalImage, image::ImageWriteOptions ().toColorSpace (image::EImageColorSpace::SRGB));
230+ destFilenameI = (fs::path (outputFolder) / (origFilename + " .png" )).string ();
231+ image::writeImage (destFilenameI , originalImage, image::ImageWriteOptions ().toColorSpace (image::EImageColorSpace::SRGB));
182232 }
183233
184234 {
185235 fs::path origImgPath (viewImagePathJ);
186236 std::string origFilename = origImgPath.stem ().string ();
187237 image::Image<image::RGBfColor> originalImage;
188238 image::readImage (viewImagePathJ, originalImage, image::EImageColorSpace::LINEAR);
189- destFilename_J = (fs::path (outputFolder) / (origFilename + " .png" )).string ();
190- image::writeImage (destFilename_J , originalImage, image::ImageWriteOptions ().toColorSpace (image::EImageColorSpace::SRGB));
239+ destFilenameJ = (fs::path (outputFolder) / (origFilename + " .png" )).string ();
240+ image::writeImage (destFilenameJ , originalImage, image::ImageWriteOptions ().toColorSpace (image::EImageColorSpace::SRGB));
191241 }
192242
193- const std::pair<size_t , size_t > dimImageI = std::make_pair (viewI-> getImage ().getWidth (), viewI-> getImage ().getHeight ());
194- const std::pair<size_t , size_t > dimImageJ = std::make_pair (viewJ-> getImage ().getWidth (), viewJ-> getImage ().getHeight ());
243+ const std::pair<size_t , size_t > dimImageI = std::make_pair (viewI. getImage ().getWidth (), viewI. getImage ().getHeight ());
244+ const std::pair<size_t , size_t > dimImageJ = std::make_pair (viewJ. getImage ().getWidth (), viewJ. getImage ().getHeight ());
195245
196246 svgDrawer svgStream (dimImageI.first + dimImageJ.first , std::max (dimImageI.second , dimImageJ.second ));
197247
198- svgStream.drawImage (destFilename_I, dimImageI.first , dimImageI.second );
199- svgStream.drawImage (destFilename_J, dimImageJ.first , dimImageJ.second , dimImageI.first );
248+ svgStream.drawImage (destFilenameI, dimImageI.first , dimImageI.second );
249+ svgStream.drawImage (destFilenameJ, dimImageJ.first , dimImageJ.second , dimImageI.first );
250+
251+ struct PairInfo
252+ {
253+ Vec2 first;
254+ Vec2 second;
255+ feature::EImageDescriberType descType;
256+ };
200257
258+ std::vector<PairInfo> pairs;
201259 const matching::MatchesPerDescType& filteredMatches = pairwiseMatches.at (*iter);
202260
203261 ALICEVISION_LOG_INFO (" nb describer: " << filteredMatches.size ());
204262
205- if (filteredMatches.empty ())
206- continue ;
207-
208263 for (const auto & matchesIt : filteredMatches)
209264 {
210265 const feature::EImageDescriberType descType = matchesIt.first ;
211266 assert (descType != feature::EImageDescriberType::UNINITIALIZED);
212267 const matching::IndMatches& matches = matchesIt.second ;
213268 ALICEVISION_LOG_INFO (EImageDescriberType_enumToString (matchesIt.first ) << " : " << matches.size () << " matches" );
214269
215- const PointFeatures& featuresI = featuresPerView.getFeatures (viewI-> getViewId () , descType);
216- const PointFeatures& featuresJ = featuresPerView.getFeatures (viewJ-> getViewId () , descType);
270+ const PointFeatures& featuresI = featuresPerView.getFeatures (I , descType);
271+ const PointFeatures& featuresJ = featuresPerView.getFeatures (J , descType);
217272
218273 // draw link between features :
219274 for (std::size_t i = 0 ; i < matches.size (); ++i)
220275 {
221276 const PointFeature& imaA = featuresI[matches[i]._i ];
222277 const PointFeature& imaB = featuresJ[matches[i]._j ];
223278
224- // compute a flashy colour for the correspondence
225- unsigned char r, g, b;
226- hslToRgb ((rand () % 360 ) / 360 ., 1.0 , .5 , r, g, b);
227- std::ostringstream osCol;
228- osCol << " rgb(" << (int )r << ' ,' << (int )g << ' ,' << (int )b << " )" ;
229- svgStream.drawLine (imaA.x (), imaA.y (), imaB.x () + dimImageI.first , imaB.y (), svgStyle ().stroke (osCol.str (), 2.0 ));
230- }
279+ PairInfo pi;
231280
232- const std::string featColor = describerTypeColor (descType);
233- // draw features (in two loop, in order to have the features upper the link, svg layer order):
234- for (std::size_t i = 0 ; i < matches.size (); ++i)
235- {
236- const PointFeature& imaA = featuresI[matches[i]._i ];
237- const PointFeature& imaB = featuresJ[matches[i]._j ];
238- svgStream.drawCircle (imaA.x (), imaA.y (), 5.0 , svgStyle ().stroke (featColor, 2.0 ));
239- svgStream.drawCircle (imaB.x () + dimImageI.first , imaB.y (), 5.0 , svgStyle ().stroke (featColor, 2.0 ));
281+ pi.first = imaA.coords ().cast <double >();
282+ pi.second = imaB.coords ().cast <double >();
283+ pi.descType = descType;
284+
285+ pairs.push_back (pi);
240286 }
241287 }
242288
243- fs::path outputFilename = fs::path (outputFolder) / std::string (std::to_string (iter->first ) + " _" + std::to_string (iter->second ) + " _" +
244- std::to_string (filteredMatches.getNbAllMatches ()) + " .svg" );
289+ if (pairs.empty ())
290+ {
291+ continue ;
292+ }
293+
294+ for (const auto & pi : pairs)
295+ {
296+ // compute a flashy colour for the correspondence
297+ unsigned char r, g, b;
298+ hslToRgb ((rand () % 360 ) / 360 ., 1.0 , .5 , r, g, b);
299+ std::ostringstream osCol;
300+ osCol << " rgb(" << (int )r << ' ,' << (int )g << ' ,' << (int )b << " )" ;
301+ svgStream.drawLine (pi.first .x (), pi.first .y (), pi.second .x () + dimImageI.first , pi.second .y (), svgStyle ().stroke (osCol.str (), 2.0 ));
302+ }
303+
304+ // draw features (in two loop, in order to have the features upper the link, svg layer order):
305+ for (const auto & pi : pairs)
306+ {
307+ const std::string featColor = describerTypeColor (pi.descType );
308+ svgStream.drawCircle (pi.first .x (), pi.first .y (), 5.0 , svgStyle ().stroke (featColor, 2.0 ));
309+ svgStream.drawCircle (pi.second .x () + dimImageI.first , pi.second .y (), 5.0 , svgStyle ().stroke (featColor, 2.0 ));
310+ }
311+
312+ fs::path outputFilename = fs::path (outputFolder) / std::string (std::to_string (iter->first ) + " _" + std::to_string (iter->second ) + " _" +std::to_string (filteredMatches.getNbAllMatches ()) + " .svg" );
245313 std::ofstream svgFile (outputFilename.string ());
246314 svgFile << svgStream.closeSvgFile ().str ();
247315 svgFile.close ();
248316 }
317+
318+
249319 return EXIT_SUCCESS;
250320}
0 commit comments