test_webcam.cpp
Go to the documentation of this file.
1 /*
2  * OpenVINS: An Open Platform for Visual-Inertial Research
3  * Copyright (C) 2018-2023 Patrick Geneva
4  * Copyright (C) 2018-2023 Guoquan Huang
5  * Copyright (C) 2018-2023 OpenVINS Contributors
6  * Copyright (C) 2018-2019 Kevin Eckenhoff
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <cmath>
23 #include <csignal>
24 #include <deque>
25 #include <fstream>
26 #include <iomanip>
27 #include <sstream>
28 #include <unistd.h>
29 #include <vector>
30 
31 #include <opencv2/core/core.hpp>
32 #include <opencv2/highgui/highgui.hpp>
33 
34 #include <boost/date_time/posix_time/posix_time.hpp>
35 #include <boost/filesystem.hpp>
36 
37 #include "cam/CamRadtan.h"
38 #include "feat/Feature.h"
39 #include "feat/FeatureDatabase.h"
40 #include "track/TrackAruco.h"
41 #include "track/TrackDescriptor.h"
42 #include "track/TrackKLT.h"
44 #include "utils/print.h"
45 
46 #if ROS_AVAILABLE == 1
47 #include <ros/ros.h>
48 #endif
49 
50 using namespace ov_core;
51 
52 // Our feature extractor
54 
55 // Define the function to be called when ctrl-c (SIGINT) is sent to process
56 void signal_callback_handler(int signum) { std::exit(signum); }
57 
58 // Main function
59 int main(int argc, char **argv) {
60 
61  // Ensure we have a path, if the user passes it then we should use it
62  std::string config_path = "unset_path.txt";
63  if (argc > 1) {
64  config_path = argv[1];
65  }
66 
67 #if ROS_AVAILABLE == 1
68  // Initialize this as a ROS node
69  ros::init(argc, argv, "test_webcam");
70  auto nh = std::make_shared<ros::NodeHandle>("~");
71  nh->param<std::string>("config_path", config_path, config_path);
72 #endif
73 
74  // Load parameters
75  auto parser = std::make_shared<ov_core::YamlParser>(config_path, false);
76 #if ROS_AVAILABLE == 1
77  parser->set_node_handler(nh);
78 #endif
79 
80  // Verbosity
81  std::string verbosity = "INFO";
82  parser->parse_config("verbosity", verbosity);
84 
85  // Defaults
86  int num_pts = 500;
87  int num_aruco = 1024;
88  int clone_states = 20;
89  int fast_threshold = 10;
90  int grid_x = 5;
91  int grid_y = 4;
92  int min_px_dist = 20;
93  double knn_ratio = 0.85;
94  bool do_downsizing = false;
95  bool use_stereo = false;
96  parser->parse_config("num_pts", num_pts, false);
97  parser->parse_config("num_aruco", num_aruco, false);
98  parser->parse_config("clone_states", clone_states, false);
99  parser->parse_config("fast_threshold", fast_threshold, false);
100  parser->parse_config("grid_x", grid_x, false);
101  parser->parse_config("grid_y", grid_y, false);
102  parser->parse_config("min_px_dist", min_px_dist, false);
103  parser->parse_config("knn_ratio", knn_ratio, false);
104  parser->parse_config("do_downsizing", do_downsizing, false);
105  parser->parse_config("use_stereo", use_stereo, false);
106 
107  // Histogram method
109  std::string histogram_method_str = "HISTOGRAM";
110  parser->parse_config("histogram_method", histogram_method_str, false);
111  if (histogram_method_str == "NONE") {
112  method = ov_core::TrackBase::NONE;
113  } else if (histogram_method_str == "HISTOGRAM") {
115  } else if (histogram_method_str == "CLAHE") {
116  method = ov_core::TrackBase::CLAHE;
117  } else {
118  printf(RED "invalid feature histogram specified:\n" RESET);
119  printf(RED "\t- NONE\n" RESET);
120  printf(RED "\t- HISTOGRAM\n" RESET);
121  printf(RED "\t- CLAHE\n" RESET);
122  std::exit(EXIT_FAILURE);
123  }
124 
125  // Debug print!
126  PRINT_DEBUG("max features: %d\n", num_pts);
127  PRINT_DEBUG("max aruco: %d\n", num_aruco);
128  PRINT_DEBUG("clone states: %d\n", clone_states);
129  PRINT_DEBUG("grid size: %d x %d\n", grid_x, grid_y);
130  PRINT_DEBUG("fast threshold: %d\n", fast_threshold);
131  PRINT_DEBUG("min pixel distance: %d\n", min_px_dist);
132  PRINT_DEBUG("downsize aruco image: %d\n", do_downsizing);
133 
134  // Fake camera info (we don't need this, as we are not using the normalized coordinates for anything)
135  std::unordered_map<size_t, std::shared_ptr<CamBase>> cameras;
136  for (int i = 0; i < 2; i++) {
137  Eigen::Matrix<double, 8, 1> cam0_calib;
138  cam0_calib << 1, 1, 0, 0, 0, 0, 0, 0;
139  std::shared_ptr<CamBase> camera_calib = std::make_shared<CamRadtan>(100, 100);
140  camera_calib->set_value(cam0_calib);
141  cameras.insert({i, camera_calib});
142  }
143 
144  // Lets make a feature extractor
145  extractor = new TrackKLT(cameras, num_pts, num_aruco, !use_stereo, method, fast_threshold, grid_x, grid_y, min_px_dist);
146  // extractor = new TrackDescriptor(cameras, num_pts, num_aruco, !use_stereo, method, fast_threshold, grid_x, grid_y, min_px_dist,
147  // knn_ratio); extractor = new TrackAruco(cameras, num_aruco, !use_stereo, method, do_downsizing);
148 
149  //===================================================================================
150  //===================================================================================
151  //===================================================================================
152 
153  // Open the first webcam (0=laptop cam, 1=usb device)
154  cv::VideoCapture cap;
155  if (!cap.open(0)) {
156  PRINT_ERROR(RED "Unable to open a webcam feed!\n" RESET);
157  return EXIT_FAILURE;
158  }
159 
160  //===================================================================================
161  //===================================================================================
162  //===================================================================================
163 
164  // Loop forever until we break out
165  double current_time = 0.0;
166  std::deque<double> clonetimes;
167  signal(SIGINT, signal_callback_handler);
168 #if ROS_AVAILABLE == 1
169  while (ros::ok()) {
170 #else
171  while (true) {
172 #endif
173 
174  // Get the next frame (and fake advance time forward)
175  cv::Mat frame;
176  cap >> frame;
177  current_time += 1.0 / 30.0;
178 
179  // Stop capture if no more image feed
180  if (frame.empty())
181  break;
182 
183  // Stop capturing by pressing ESC
184  if (cv::waitKey(10) == 27)
185  break;
186 
187  // Convert to grayscale if not
188  if (frame.channels() != 1)
189  cv::cvtColor(frame, frame, cv::COLOR_RGB2GRAY);
190 
191  // Else lets track this image
192  ov_core::CameraData message;
193  message.timestamp = current_time;
194  message.sensor_ids.push_back(0);
195  message.images.push_back(frame);
196  message.masks.push_back(cv::Mat::zeros(cv::Size(frame.cols, frame.rows), CV_8UC1));
197  extractor->feed_new_camera(message);
198 
199  // Display the resulting tracks
200  cv::Mat img_active, img_history;
201  extractor->display_active(img_active, 255, 0, 0, 0, 0, 255);
202  extractor->display_history(img_history, 255, 255, 0, 255, 255, 255);
203 
204  // Show our image!
205  cv::imshow("Active Tracks", img_active);
206  cv::imshow("Track History", img_history);
207  cv::waitKey(1);
208 
209  // Get lost tracks
210  std::shared_ptr<FeatureDatabase> database = extractor->get_feature_database();
211  std::vector<std::shared_ptr<Feature>> feats_lost = database->features_not_containing_newer(current_time);
212 
213  // Mark theses feature pointers as deleted
214  for (size_t i = 0; i < feats_lost.size(); i++) {
215  // Total number of measurements
216  int total_meas = 0;
217  for (auto const &pair : feats_lost[i]->timestamps) {
218  total_meas += (int)pair.second.size();
219  }
220  // Update stats
221  feats_lost[i]->to_delete = true;
222  }
223 
224  // Push back the current time, as a clone time
225  clonetimes.push_back(current_time);
226 
227  // Marginalized features if we have reached 5 frame tracks
228  if ((int)clonetimes.size() >= clone_states) {
229  // Remove features that have reached their max track length
230  double margtime = clonetimes.at(0);
231  clonetimes.pop_front();
232  std::vector<std::shared_ptr<Feature>> feats_marg = database->features_containing(margtime);
233  // Delete theses feature pointers
234  for (size_t i = 0; i < feats_marg.size(); i++) {
235  feats_marg[i]->to_delete = true;
236  }
237  }
238 
239  // Tell the feature database to delete old features
240  database->cleanup();
241  }
242 
243  // Done!
244  return EXIT_SUCCESS;
245 }
FeatureDatabase.h
ov_core::TrackBase::HistogramMethod
HistogramMethod
Desired pre-processing image method.
Definition: TrackBase.h:78
ov_core::TrackBase::NONE
@ NONE
Definition: TrackBase.h:78
ros::init
ROSCPP_DECL void init(const M_string &remappings, const std::string &name, uint32_t options=0)
ov_core::CameraData::images
std::vector< cv::Mat > images
Raw image we have collected for each camera.
Definition: sensor_data.h:64
extractor
TrackBase * extractor
Definition: test_webcam.cpp:53
ov_core::TrackBase::feed_new_camera
virtual void feed_new_camera(const CameraData &message)=0
Process a new image.
ros.h
PRINT_DEBUG
#define PRINT_DEBUG(x...)
Definition: print.h:97
Feature.h
TrackKLT.h
ov_core::CameraData
Struct for a collection of camera measurements.
Definition: sensor_data.h:55
CamRadtan.h
PRINT_ERROR
#define PRINT_ERROR(x...)
Definition: print.h:100
ros::ok
ROSCPP_DECL bool ok()
ov_core::CameraData::sensor_ids
std::vector< int > sensor_ids
Camera ids for each of the images collected.
Definition: sensor_data.h:61
ov_core::CameraData::timestamp
double timestamp
Timestamp of the reading.
Definition: sensor_data.h:58
ov_core::CameraData::masks
std::vector< cv::Mat > masks
Tracking masks for each camera we have.
Definition: sensor_data.h:67
ov_core::TrackBase::display_active
virtual void display_active(cv::Mat &img_out, int r1, int g1, int b1, int r2, int g2, int b2, std::string overlay="")
Shows features extracted in the last image.
Definition: TrackBase.cpp:43
signal_callback_handler
void signal_callback_handler(int signum)
Definition: test_webcam.cpp:56
ov_core::Printer::setPrintLevel
static void setPrintLevel(const std::string &level)
Set the print level to use for all future printing to stdout.
Definition: print.cpp:29
print.h
ov_core::TrackBase::CLAHE
@ CLAHE
Definition: TrackBase.h:78
RED
#define RED
Definition: colors.h:27
opencv_yaml_parse.h
clonetimes
std::deque< double > clonetimes
Definition: test_tracking.cpp:58
TrackDescriptor.h
ov_core::TrackBase::HISTOGRAM
@ HISTOGRAM
Definition: TrackBase.h:78
ov_core::TrackBase::get_feature_database
std::shared_ptr< FeatureDatabase > get_feature_database()
Get the feature database with all the track information.
Definition: TrackBase.h:123
RESET
#define RESET
Definition: colors.h:25
ov_core::TrackKLT
KLT tracking of features.
Definition: TrackKLT.h:39
ov_core::TrackBase::display_history
virtual void display_history(cv::Mat &img_out, int r1, int g1, int b1, int r2, int g2, int b2, std::vector< size_t > highlighted={}, std::string overlay="")
Shows a "trail" for each feature (i.e. its history)
Definition: TrackBase.cpp:119
main
int main(int argc, char **argv)
Definition: test_webcam.cpp:59
clone_states
int clone_states
Definition: test_tracking.cpp:57
ov_core
Core algorithms for OpenVINS.
Definition: CamBase.h:30
ov_core::TrackBase
Visual feature tracking base class.
Definition: TrackBase.h:72
TrackAruco.h


ov_core
Author(s): Patrick Geneva , Kevin Eckenhoff , Guoquan Huang
autogenerated on Mon Jan 22 2024 03:08:17