From 08bcf721a9421ceaabe3cee55f6968058d9e5d92 Mon Sep 17 00:00:00 2001 From: Sebastian Hahta <joseha@utu.fi> Date: Tue, 13 Aug 2019 09:33:58 +0300 Subject: [PATCH] stereo image mode and video (frames) mode --- applications/groupview/src/main.cpp | 197 ++++++++++++++++++++++++++-- 1 file changed, 187 insertions(+), 10 deletions(-) diff --git a/applications/groupview/src/main.cpp b/applications/groupview/src/main.cpp index f57337183..66ff5d0d1 100644 --- a/applications/groupview/src/main.cpp +++ b/applications/groupview/src/main.cpp @@ -13,7 +13,11 @@ using Eigen::Matrix4d; using std::map; using std::string; +using std::vector; +using cv::Size; +using cv::Mat; +// TODO: remove code duplication (function from reconstruction) static void from_json(nlohmann::json &json, map<string, Matrix4d> &transformations) { for (auto it = json.begin(); it != json.end(); ++it) { Eigen::Matrix4d m; @@ -23,6 +27,7 @@ static void from_json(nlohmann::json &json, map<string, Matrix4d> &transformatio } } +// TODO: remove code duplication (function from reconstruction) static bool loadTransformations(const string &path, map<string, Matrix4d> &data) { std::ifstream file(path); if (!file.is_open()) { @@ -36,8 +41,106 @@ static bool loadTransformations(const string &path, map<string, Matrix4d> &data) return true; } -int main(int argc, char **argv) { - auto root = ftl::configure(argc, argv, "viewer_default"); +// TODO: remove code duplication (function from calibrate-multi) +void stack(const vector<Mat> &img, Mat &out, const int rows, const int cols) { + Size size = img[0].size(); + Size size_out = Size(size.width * cols, size.height * rows); + if (size_out != out.size() || out.type() != CV_8UC3) { + out = Mat(size_out, CV_8UC3, cv::Scalar(0, 0, 0)); + } + + for (size_t i = 0; i < img.size(); i++) { + int row = i % rows; + int col = i / rows; + auto rect = cv::Rect(size.width * col, size.height * row, size.width, size.height); + img[i].copyTo(out(rect)); + } +} + +// TODO: remove code duplication (function from calibrate-multi) +void stack(const vector<Mat> &img, Mat &out) { + // TODO + int rows = 2; + int cols = (img.size() + 1) / 2; + stack(img, out, rows, cols); +} + +void modeLeftRight(ftl::Configurable *root) { + ftl::net::Universe *net = ftl::create<ftl::net::Universe>(root, "net"); + + net->start(); + net->waitConnections(); + + auto sources = ftl::createArray<ftl::rgbd::Source>(root, "sources", net); + const string path = root->value<string>("save_to", "./"); + const string file_type = root->value<string>("file_type", "jpg"); + + const size_t n_cameras = sources.size() * 2; + ftl::rgbd::Group group; + + for (auto* src : sources) { + src->setChannel(ftl::rgbd::kChanRight); + group.addSource(src); + } + + std::mutex mutex; + std::atomic<bool> new_frames = false; + vector<Mat> rgb(n_cameras), rgb_new(n_cameras); + + group.sync([&mutex, &new_frames, &rgb_new](const ftl::rgbd::FrameSet &frames) { + mutex.lock(); + bool good = true; + for (size_t i = 0; i < frames.channel1.size(); i ++) { + if (frames.channel1[i].empty()) good = false; + if (frames.channel1[i].empty()) good = false; + if (frames.channel1[i].channels() != 3) good = false; // ASSERT + if (frames.channel2[i].channels() != 3) good = false; + if (!good) break; + + frames.channel1[i].copyTo(rgb_new[2 * i]); + frames.channel2[i].copyTo(rgb_new[2 * i + 1]); + } + + new_frames = good; + mutex.unlock(); + return true; + }); + + int idx = 0; + int key; + + Mat show; + cv::namedWindow("Cameras", cv::WINDOW_KEEPRATIO | cv::WINDOW_NORMAL); + + while (ftl::running) { + while (!new_frames) { + for (auto src : sources) { src->grab(30); } + key = cv::waitKey(10); + } + + mutex.lock(); + rgb.swap(rgb_new); + new_frames = false; + mutex.unlock(); + + stack(rgb, show); + + cv::imshow("Cameras", show); + + key = cv::waitKey(100); + // TODO: fix + if (key == 's') { + for (size_t c = 0; c < n_cameras; c++ ) { + cv::imwrite(path + "camera" + std::to_string(c) + "_" + std::to_string(idx) + "." + file_type, rgb[c]); + } + LOG(INFO) << "Saved (" << idx << ")"; + idx++; + } + if (key == 27) break; + } +} + +void modeFrame(ftl::Configurable *root, int frames=1) { ftl::net::Universe *net = ftl::create<ftl::net::Universe>(root, "net"); net->start(); @@ -66,10 +169,11 @@ int main(int argc, char **argv) { group.addSource(s); } - bool grab = false; + std::atomic<bool> grab = false; group.sync([&grab](const ftl::rgbd::FrameSet &fs) { LOG(INFO) << "Complete set: " << fs.timestamp; + if (!ftl::running) { return false; } if (grab) { grab = false; @@ -89,20 +193,93 @@ int main(int argc, char **argv) { return true; }); - int current = 0; + cv::Mat show; + vector<cv::Mat> rgb(sources.size()); + vector<cv::Mat> depth(sources.size()); + + cv::namedWindow("Cameras", cv::WINDOW_KEEPRATIO | cv::WINDOW_NORMAL); while (ftl::running) { - //std::this_thread::sleep_for(std::chrono::milliseconds(20)); for (auto s : sources) s->grab(30); - cv::Mat rgb,depth; - sources[current%sources.size()]->getFrames(rgb, depth); - if (!rgb.empty()) cv::imshow("View", rgb); - auto key = cv::waitKey(20); + for (size_t i = 0; i < sources.size(); i++) { + do { sources[i]->getFrames(rgb[i], depth[i]); } + while(rgb[i].empty()); + } + stack(rgb, show); + cv::imshow("Cameras", show); + + auto key = cv::waitKey(20); if (key == 27) break; - if (key == 'n') current++; if (key == 'g') grab = true; } +} + +void modeVideo(ftl::Configurable *root) { + + ftl::net::Universe *net = ftl::create<ftl::net::Universe>(root, "net"); + + net->start(); + net->waitConnections(); + + auto sources = ftl::createArray<ftl::rgbd::Source>(root, "sources", net); + const string path = root->value<string>("save_to", "./"); + + for (auto* src : sources) { src->setChannel(ftl::rgbd::kChanDepth); } + + cv::Mat show; + vector<cv::Mat> rgb(sources.size()); + vector<cv::Mat> depth(sources.size()); + + cv::namedWindow("Cameras", cv::WINDOW_KEEPRATIO | cv::WINDOW_NORMAL); + + int count = 0; + int remaining = 0; + + Mat depth_out; + + while (ftl::running) { + for (auto s : sources) s->grab(30); + for (size_t i = 0; i < sources.size(); i++) { + do { sources[i]->getFrames(rgb[i], depth[i]); } + while(rgb[i].empty() || depth[i].empty()); + } + + if (remaining > 0) { + for (size_t i = 0; i < sources.size(); i++) { + depth[i].convertTo(depth_out, CV_16UC1, 1000.0f); + cv::imwrite(path + "rgb-" + std::to_string(i) + "-" + std::to_string(count) + ".jpg", rgb[i]); + cv::imwrite(path + "depth-" + std::to_string(i) + "-" + std::to_string(count) + ".png", depth_out); + } + count++; + remaining--; + LOG(INFO) << "remaining: " << remaining; + } + + stack(rgb, show); + cv::imshow("Cameras", show); + + auto key = cv::waitKey(20); + if (key == 'g' && remaining == 0) { + remaining = 250; + } + if (key == 27) break; + } +} + +int main(int argc, char **argv) { + auto root = ftl::configure(argc, argv, "viewer_default"); + + if (root->value("stereo", false)) { + LOG(INFO) << "Stereo images mode"; + modeLeftRight(root); + } else if (root->value("video", false)) { + LOG(INFO) << "Video mode"; + modeVideo(root); + } else { + modeFrame(root); + } + ftl::running = false; return 0; } -- GitLab