Commit f95e71ea authored by Alexey Spizhevoy's avatar Alexey Spizhevoy

added saving of matches graph into opencv_stitching (in DOT format)

parent 7820c343
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
// 3) Automatic Panoramic Image Stitching using Invariant Features. // 3) Automatic Panoramic Image Stitching using Invariant Features.
// Matthew Brown and David G. Lowe. 2007. // Matthew Brown and David G. Lowe. 2007.
#include <fstream>
#include "precomp.hpp" #include "precomp.hpp"
#include "util.hpp" #include "util.hpp"
#include "warpers.hpp" #include "warpers.hpp"
...@@ -83,6 +84,10 @@ void printUsage() ...@@ -83,6 +84,10 @@ void printUsage()
" Bundle adjustment cost function. The default is 'focal_ray'.\n" " Bundle adjustment cost function. The default is 'focal_ray'.\n"
" --wave_correct (no|yes)\n" " --wave_correct (no|yes)\n"
" Perform wave effect correction. The default is 'yes'.\n" " Perform wave effect correction. The default is 'yes'.\n"
" --save_graph <file_name>\n"
" Save matches graph represented in DOT language to <file_name> file.\n"
" Labels description: Nm is number of matches, Ni is number of inliers,\n"
" C is confidence.\n"
"\nCompositing Flags:\n" "\nCompositing Flags:\n"
" --warp (plane|cylindrical|spherical)\n" " --warp (plane|cylindrical|spherical)\n"
" Warp surface type. The default is 'spherical'.\n" " Warp surface type. The default is 'spherical'.\n"
...@@ -114,6 +119,8 @@ double compose_megapix = -1; ...@@ -114,6 +119,8 @@ double compose_megapix = -1;
int ba_space = BundleAdjuster::FOCAL_RAY_SPACE; int ba_space = BundleAdjuster::FOCAL_RAY_SPACE;
float conf_thresh = 1.f; float conf_thresh = 1.f;
bool wave_correct = true; bool wave_correct = true;
bool save_graph = false;
std::string save_graph_to;
int warp_type = Warper::SPHERICAL; int warp_type = Warper::SPHERICAL;
int expos_comp_type = ExposureCompensator::GAIN_BLOCKS; int expos_comp_type = ExposureCompensator::GAIN_BLOCKS;
float match_conf = 0.65f; float match_conf = 0.65f;
...@@ -209,6 +216,12 @@ int parseCmdArgs(int argc, char** argv) ...@@ -209,6 +216,12 @@ int parseCmdArgs(int argc, char** argv)
} }
i++; i++;
} }
else if (string(argv[i]) == "--save_graph")
{
save_graph = true;
save_graph_to = argv[i + 1];
i++;
}
else if (string(argv[i]) == "--warp") else if (string(argv[i]) == "--warp")
{ {
if (string(argv[i + 1]) == "plane") if (string(argv[i + 1]) == "plane")
...@@ -378,6 +391,14 @@ int main(int argc, char* argv[]) ...@@ -378,6 +391,14 @@ int main(int argc, char* argv[])
matcher.releaseMemory(); matcher.releaseMemory();
LOGLN("Pairwise matching, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec"); LOGLN("Pairwise matching, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
// Check if we should save matches graph
if (save_graph)
{
LOGLN("Saving matches graph...");
ofstream f(save_graph_to.c_str());
f << matchesGraphAsString(img_names, pairwise_matches, conf_thresh);
}
// Leave only images we are sure are from the same panorama // Leave only images we are sure are from the same panorama
vector<int> indices = leaveBiggestComponent(features, pairwise_matches, conf_thresh); vector<int> indices = leaveBiggestComponent(features, pairwise_matches, conf_thresh);
vector<Mat> img_subset; vector<Mat> img_subset;
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
// //
//M*/ //M*/
#include <algorithm> #include <algorithm>
#include <sstream>
#include "autocalib.hpp" #include "autocalib.hpp"
#include "motion_estimators.hpp" #include "motion_estimators.hpp"
#include "util.hpp" #include "util.hpp"
...@@ -407,6 +408,70 @@ void waveCorrect(vector<Mat> &rmats) ...@@ -407,6 +408,70 @@ void waveCorrect(vector<Mat> &rmats)
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
string matchesGraphAsString(vector<string> &pathes, vector<MatchesInfo> &pairwise_matches,
float conf_threshold)
{
stringstream str;
str << "graph matches_graph{\n";
set<int> added_imgs;
// Add matches
for (size_t i = 0; i < pairwise_matches.size(); ++i)
{
if (pairwise_matches[i].src_img_idx < pairwise_matches[i].dst_img_idx &&
pairwise_matches[i].confidence > conf_threshold)
{
string name_src = pathes[pairwise_matches[i].src_img_idx];
size_t prefix_len = name_src.find_last_of("/\\");
if (prefix_len != string::npos) prefix_len++; else prefix_len = 0;
name_src = name_src.substr(prefix_len, name_src.size() - prefix_len);
string name_dst = pathes[pairwise_matches[i].dst_img_idx];
prefix_len = name_dst.find_last_of("/\\");
if (prefix_len != string::npos) prefix_len++; else prefix_len = 0;
name_dst = name_dst.substr(prefix_len, name_dst.size() - prefix_len);
added_imgs.insert(pairwise_matches[i].src_img_idx);
added_imgs.insert(pairwise_matches[i].dst_img_idx);
str << "\"" << name_src << "\" -- \"" << name_dst << "\""
<< "[label=\"Nm=" << pairwise_matches[i].matches.size()
<< ", Ni=" << pairwise_matches[i].num_inliers
<< ", C=" << pairwise_matches[i].confidence << "\"];\n";
}
}
// Add unmatched images
for (size_t i = 0; i < pairwise_matches.size(); ++i)
{
if (pairwise_matches[i].src_img_idx < pairwise_matches[i].dst_img_idx)
{
if (added_imgs.find(pairwise_matches[i].src_img_idx) == added_imgs.end())
{
added_imgs.insert(pairwise_matches[i].src_img_idx);
string name = pathes[pairwise_matches[i].src_img_idx];
size_t prefix_len = name.find_last_of("/\\");
if (prefix_len != string::npos) prefix_len++; else prefix_len = 0;
name = name.substr(prefix_len, name.size() - prefix_len);
str << "\"" << name << "\";\n";
}
if (added_imgs.find(pairwise_matches[i].dst_img_idx) == added_imgs.end())
{
added_imgs.insert(pairwise_matches[i].dst_img_idx);
string name = pathes[pairwise_matches[i].dst_img_idx];
size_t prefix_len = name.find_last_of("/\\");
if (prefix_len != string::npos) prefix_len++; else prefix_len = 0;
name = name.substr(prefix_len, name.size() - prefix_len);
str << "\"" << name << "\";\n";
}
}
}
str << "}";
return str.str();
}
vector<int> leaveBiggestComponent(vector<ImageFeatures> &features, vector<MatchesInfo> &pairwise_matches, vector<int> leaveBiggestComponent(vector<ImageFeatures> &features, vector<MatchesInfo> &pairwise_matches,
float conf_threshold) float conf_threshold)
{ {
......
...@@ -122,6 +122,10 @@ void waveCorrect(std::vector<cv::Mat> &rmats); ...@@ -122,6 +122,10 @@ void waveCorrect(std::vector<cv::Mat> &rmats);
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// Auxiliary functions // Auxiliary functions
// Returns matches graph representation in DOT language
std::string matchesGraphAsString(std::vector<std::string> &pathes, std::vector<MatchesInfo> &pairwise_matches,
float conf_threshold);
std::vector<int> leaveBiggestComponent(std::vector<ImageFeatures> &features, std::vector<MatchesInfo> &pairwise_matches, std::vector<int> leaveBiggestComponent(std::vector<ImageFeatures> &features, std::vector<MatchesInfo> &pairwise_matches,
float conf_threshold); float conf_threshold);
......
...@@ -108,8 +108,9 @@ bool overlapRoi(cv::Point tl1, cv::Point tl2, cv::Size sz1, cv::Size sz2, cv::Re ...@@ -108,8 +108,9 @@ bool overlapRoi(cv::Point tl1, cv::Point tl2, cv::Size sz1, cv::Size sz2, cv::Re
cv::Rect resultRoi(const std::vector<cv::Point> &corners, const std::vector<cv::Mat> &images); cv::Rect resultRoi(const std::vector<cv::Point> &corners, const std::vector<cv::Mat> &images);
cv::Rect resultRoi(const std::vector<cv::Point> &corners, const std::vector<cv::Size> &sizes); cv::Rect resultRoi(const std::vector<cv::Point> &corners, const std::vector<cv::Size> &sizes);
cv::Point resultTl(const std::vector<cv::Point> &corners); cv::Point resultTl(const std::vector<cv::Point> &corners);
void selectRandomSubset(int count, int size, std::vector<int> &subset);
// Returns random 'count' element subset of the {0,1,...,size-1} set
void selectRandomSubset(int count, int size, std::vector<int> &subset);
#include "util_inl.hpp" #include "util_inl.hpp"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment