13 #include "../lib/args.h" 14 #include "../lib/json.h" 15 #include "../lib/filesystem.h" 16 #include "../lib/dataset.h" 17 #include "../lib/opencv.h" 18 #include "../lib/image_io.h" 40 feature_positions(features_count),
41 feature_status(features_count) { }
44 std::size_t valid_features_count()
const;
49 std::size_t count = 0;
50 for(uchar status : feature_status)
if(status) ++count;
62 return std::make_pair(i, idx);
68 if(origin_idx.
y < dest_idx.
y) dir =
'^';
69 else if(origin_idx.
y > dest_idx.
y) dir =
'v';
70 else if(origin_idx.
x < dest_idx.
x) dir =
'>';
71 else if(origin_idx.
x > dest_idx.
x) dir =
'<';
73 if(
verbose) std::cout << origin_idx <<
" --" << dir <<
"-- " << dest_idx << std::endl;
74 else std::cout << dir << std::flush;
83 cors[std::make_pair(i, state.
view_idx)] = pos;
90 static std::mutex disk_read_lock;
94 cv::Mat_<cv::Vec3b> col_img =
load_texture(image_filename);
95 cv::Mat_<uchar> gray_img;
96 cv::cvtColor(col_img, gray_img, CV_BGR2GRAY);
99 if(must_exist)
throw std::runtime_error(
"image for " +
encode_view_index(idx) +
" must exist, but does not");
100 else return cv::Mat_<uchar>();
110 cv::Mat_<uchar> orig_img;
113 cv::buildOpticalFlowPyramid(
121 cv::Mat_<uchar> dest_img =
load_image(datag, dest_idx, !may_skip);
122 if(may_skip && dest_img.empty()) {
126 flow_state dest_state(dest_idx, dest_img, features_count);
129 cv::buildOpticalFlowPyramid(
139 std::vector<float> dest_errs(features_count);
141 cv::TermCriteria term(cv::TermCriteria::COUNT | cv::TermCriteria::EPS, 30, 0.01);
142 cv::calcOpticalFlowPyrLK(
155 auto position_ok = [&](
const cv::Point2f& pos) ->
bool {
156 return (pos.x > 0.0) && (pos.y > 0.0) && (pos.x < dest_img.cols) && (pos.y < dest_img.rows);
159 for(std::ptrdiff_t feature = 0; feature < features_count; ++feature) {
162 dest_status[feature] &&
163 position_ok(dest_positions[feature]) &&
165 dest_status[feature] = status;
180 if(verb) std::cout <<
"horizontal optical flow by increasing x starting at mid_x..." << std::endl;
187 state = std::move(new_state);
189 if(state.valid_features_count() == 0)
break;
192 if(verb) std::cout <<
"\nhorizontal optical flow by decreasing x starting at mid_x..." << std::endl;
200 state = std::move(new_state);
202 if(state.valid_features_count() == 0)
break;
212 cv::Mat_<uchar> center_image =
load_image(datag, reference_idx,
true);
214 std::vector<cv::Point2f> center_positions = vec2_to_point2f(reference_points);
215 std::size_t features_count = center_positions.size();
217 flow_state center_state(reference_idx, center_image, features_count);
226 std::vector<flow_state> vertical_origins;
227 vertical_origins.push_back(center_state);
229 std::cout <<
"vertical optical flow by increasing y starting at mid_y..." << std::endl;
231 for(
int y = reference_idx.
y + datas.
y_step(); y <= y_max; y += datas.
y_step()) {
236 vertical_origins.push_back(new_state);
237 state = std::move(new_state);
242 std::cout <<
"\nvertical optical flow by decreasing y starting at mid_y..." << std::endl;
243 state = center_state;
244 for(
int y = reference_idx.
y - datas.
y_step(); y >= y_min; y -= datas.
y_step()) {
249 vertical_origins.push_back(new_state);
250 state = std::move(new_state);
254 std::cout <<
"\nnow doing horizontal flows..." << std::endl;
256 #pragma omp parallel for 257 for(std::ptrdiff_t i = 0; i < vertical_origins.size(); i++) {
260 const flow_state& origin_state = vertical_origins[i];
266 std::cout <<
'\n' << done <<
" of " << vertical_origins.size() << std::endl;
268 cors.insert(hcors.begin(), hcors.end());
283 int main(
int argc,
const char* argv[]) {
284 get_args(argc, argv,
"dataset_parameters.json reference_fpoints.json horiz_outreach vert_outreach out_cors.json [dataset_group]");
296 std::cout <<
"loading reference points" << std::endl;
297 std::vector<vec2> reference_feature_points;
298 std::map<local_feature_index, std::string> feature_names;
299 for(
const auto& kv : reference_fpoints.
points) {
300 const std::string& feature_name = kv.first;
302 feature_names[reference_feature_points.size()] = feature_name;
303 reference_feature_points.push_back(fpoint.
position);
307 std::cout <<
"doing optical flow from reference view " << reference_idx << std::endl;
311 std::cout <<
"\nsaving image correspondences" << std::endl;
314 for(
const auto& kv : cors) {
317 const vec2& position = kv.second;
319 std::string& feature_name = feature_names[local_feature_idx];
323 feature.
points[idx].position = position;
327 std::cout <<
"done" << std::endl;
bool file_exists(const std::string &filename)
std::string image_filename() const
std::string encode_view_index(view_index idx)
const cv::Size horizontal_optical_flow_window_size(20, 20)
Set of features, each on set of views.
void add_correspondences(correspondences_type &cors, const flow_state &state)
dataset_view view(int x) const
Points of different features, on one view.
std::vector< cv::Mat_< uchar > > image_pyramid
constexpr real max_flow_err
cv::Mat_< cv::Vec3b > load_texture(const std::string &filename)
std::pair< local_feature_index, view_index > correspondence_key_type
std::map< std::string, feature_point > points
std::size_t valid_features_count() const
std::map< std::string, image_correspondence_feature > features
std::vector< cv::Point2f > feature_positions
const cv::Size vertical_optical_flow_window_size(20, 20)
std::string dataset_group
correspondence_key_type cor_key(local_feature_index i, const view_index &idx)
std::size_t features_count() const
std::vector< uchar > feature_status
int main(int argc, const char *argv[])
view_index reference_view
void print_flow_indicator(const view_index &origin_idx, const view_index &dest_idx)
flow_state flow_to(flow_state &origin_state, view_index dest_idx, const dataset_group &datag, const cv::Size &window_size, bool may_skip)
constexpr real min_distance_between_features
std::map< correspondence_key_type, vec2 > correspondences_type
cv::Mat_< uchar > load_image(const dataset_group &datag, const view_index &idx, bool must_exist)
std::ptrdiff_t local_feature_index
flow_state(const view_index &idx, const cv::Mat_< uchar > &img, std::size_t features_count)
std::string out_filename_arg()
Feature on set of views. Optionally one view is "reference".
void do_horizontal_optical_flow(correspondences_type &cors, const view_index &reference_idx, const flow_state &mid_x_state, const dataset_group &datag, bool verb=false)
constexpr int max_pyramid_level
void export_image_corresponcences(const image_correspondences &cors, const std::string &filename)
correspondences_type do_2d_optical_flow(const dataset_group &datag, const view_index &reference_idx, const std::vector< vec2 > &reference_points)
feature_points feature_points_arg()
std::map< view_index, feature_point > points
dataset_group group(const std::string &grp) const
const dataset & set() const
std::string string_opt_arg(const std::string &def="")
void get_args(int argc, const char *argv[], const std::string &usage)