Skip to content

Commit d1d03a3

Browse files
committed
Add utility for fetching RGB & depth frames with more generic names
1 parent be484e8 commit d1d03a3

File tree

6 files changed

+252
-9
lines changed

6 files changed

+252
-9
lines changed

apps/surfelwarp_app/main.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ int main(int argc, char** argv) {
3030
//auto context = initCudaContext();
3131

3232
//Save offline
33-
bool offline_rendering = false;
33+
bool offline_rendering = true;
3434

3535
//The processing loop
3636
SurfelWarpSerial fusion;

core/SurfelWarpSerial.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,17 @@
99
#include "core/geometry/SurfelNodeDeformer.h"
1010
#include "visualization/Visualizer.h"
1111
#include "imgproc/frameio/FetchInterface.h"
12-
12+
#include "imgproc/frameio/GenericFileFetch.h"
1313

1414
#include <thread>
1515
#include <fstream>
1616

17-
1817
surfelwarp::SurfelWarpSerial::SurfelWarpSerial() {
1918
//The config is assumed to be updated
2019
const auto& config = ConfigParser::Instance();
2120

2221
//Construct the image processor
23-
FetchInterface::Ptr fetcher = std::make_shared<VolumeDeformFileFetch>(config.data_path());
22+
FetchInterface::Ptr fetcher = std::make_shared<GenericFileFetch>(config.data_path());
2423
m_image_processor = std::make_shared<ImageProcessor>(fetcher);
2524

2625
//Construct the holder for surfel geometry

imgproc/frameio/GenericFileFetch.cpp

+173
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
// ================================================================
2+
// Created by Gregory Kramida on 9/23/19.
3+
// Copyright (c) 2019 Gregory Kramida
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
// ================================================================
16+
17+
#include "GenericFileFetch.h"
18+
#include "common/OpenCV_CrossPlatform.h"
19+
20+
#include <opencv2/core.hpp>
21+
#include <boost/filesystem/operations.hpp>
22+
#include <exception>
23+
#include <regex>
24+
#include <iterator>
25+
#include <common/logging.h>
26+
27+
28+
namespace fs = boost::filesystem;
29+
30+
surfelwarp::GenericFileFetch::GenericFileFetch(const fs::path& data_path, std::string extension, bool force_no_masks) :
31+
m_mask_buffer_ix(SIZE_MAX)
32+
{
33+
std::vector<path> sorted_paths;
34+
if (extension.length() > 0 && extension[0] != '.') {
35+
extension = "." + extension;
36+
}
37+
std::copy(fs::directory_iterator(data_path), fs::directory_iterator(), std::back_inserter(sorted_paths));
38+
std::sort(sorted_paths.begin(), sorted_paths.end());
39+
bool unexpected_mask_frame_number = false;
40+
for (auto& path : sorted_paths) {
41+
if (FilenameIndicatesDepthImage(path.filename().string(), extension)) {
42+
int frame_number = GetFrameNumber(path);
43+
if (frame_number != m_depth_image_paths.size()) {
44+
throw std::runtime_error("Unexpected depth frame number encountered");
45+
}
46+
m_depth_image_paths.push_back(path);
47+
} else if (FilenameIndicatesRGBImage(path.filename().string(), extension)) {
48+
int frame_number = GetFrameNumber(path);
49+
if (frame_number != m_rgb_image_paths.size()) {
50+
throw std::runtime_error("Unexpected RGB frame number encountered");
51+
}
52+
m_rgb_image_paths.push_back(path);
53+
} else if (!force_no_masks && FilenameIndicatesMaskImage(path.filename().string(), extension)) {
54+
int frame_number = GetFrameNumber(path);
55+
if (frame_number != m_mask_image_paths.size()) {
56+
unexpected_mask_frame_number = true;
57+
}
58+
m_mask_image_paths.push_back(path);
59+
}
60+
}
61+
62+
if (m_depth_image_paths.size() != m_rgb_image_paths.size()) {
63+
LOG(FATAL) << "Presumed depth image count (" << m_depth_image_paths.size() <<
64+
") doesn't equal presumed rgb image count." << m_rgb_image_paths.size();
65+
}
66+
67+
if (!force_no_masks) {
68+
if (unexpected_mask_frame_number) {
69+
LOG(WARNING)
70+
<< "Warning: inconsistent mask frame numbers encountered in the filenames. Proceeding without masks.";
71+
} else if (m_depth_image_paths.size() != m_mask_image_paths.size() && !m_mask_image_paths.empty()) {
72+
LOG(WARNING) << "Warning: seems like there were some mask image files, but their number doesn't match the "
73+
"number of depth frames. Proceeding without masks.";
74+
} else {
75+
m_use_masks = true;
76+
}
77+
}
78+
}
79+
80+
bool surfelwarp::GenericFileFetch::HasSubstringFromSet(const std::string& string, const std::string* set, int set_size)
81+
{
82+
bool found_indicator = false;
83+
for (int i_target_string = 0; i_target_string < set_size; i_target_string++) {
84+
if (string.find(set[i_target_string]) != std::string::npos) {
85+
return true;
86+
}
87+
}
88+
return false;
89+
}
90+
91+
bool surfelwarp::GenericFileFetch::FilenameIndicatesDepthImage(const path& filename, const std::string& valid_extension)
92+
{
93+
if (filename.extension() != valid_extension) return false;
94+
const std::array<std::string, 3> possible_depth_indicators = {"depth", "DEPTH", "Depth"};
95+
return HasSubstringFromSet(filename.string(), possible_depth_indicators.data(), possible_depth_indicators.size());
96+
}
97+
98+
bool surfelwarp::GenericFileFetch::FilenameIndicatesRGBImage(const path& filename, const std::string& valid_extension)
99+
{
100+
if (filename.extension() != valid_extension) return false;
101+
const std::array<std::string, 5> possible_depth_indicators = {"color", "COLOR", "Color", "rgb", "RGB"};
102+
return HasSubstringFromSet(filename.string(), possible_depth_indicators.data(), possible_depth_indicators.size());
103+
}
104+
105+
106+
bool surfelwarp::GenericFileFetch::FilenameIndicatesMaskImage(const surfelwarp::GenericFileFetch::path& filename,
107+
const std::string& valid_extension)
108+
{
109+
if (filename.extension() != valid_extension) return false;
110+
const std::array<std::string, 3> possible_depth_indicators = {"mask", "Mask", "MASK"};
111+
return HasSubstringFromSet(filename.string(), possible_depth_indicators.data(), possible_depth_indicators.size());
112+
}
113+
114+
int surfelwarp::GenericFileFetch::GetFrameNumber(const surfelwarp::GenericFileFetch::path& filename)
115+
{
116+
const std::regex digits_regex("\\d+");
117+
std::smatch match_result;
118+
const std::string filename_stem = filename.stem().string();
119+
if (!std::regex_search(filename_stem, match_result, digits_regex)) {
120+
throw std::runtime_error("Could not find frame number in filename.");
121+
};
122+
return std::stoi(match_result.str(0));
123+
}
124+
125+
void surfelwarp::GenericFileFetch::FetchDepthImage(size_t frame_idx, cv::Mat& depth_img)
126+
{
127+
path file_path = this->m_depth_image_paths[frame_idx];
128+
//Read the image
129+
depth_img = cv::imread(file_path.string(), CV_ANYCOLOR | CV_ANYDEPTH); // NOLINT(hicpp-signed-bitwise)
130+
131+
if (this->m_use_masks) {
132+
mask_mutex.lock();
133+
// Apply mask to image
134+
if (this->m_mask_buffer_ix != frame_idx) {
135+
m_mask_image_buffer = cv::imread(this->m_mask_image_paths[frame_idx].string(),
136+
CV_ANYCOLOR | CV_ANYDEPTH); // NOLINT(hicpp-signed-bitwise)
137+
m_mask_buffer_ix = frame_idx;
138+
}
139+
cv::Mat masked;
140+
depth_img.copyTo(masked,m_mask_image_buffer);
141+
mask_mutex.unlock();
142+
depth_img = masked;
143+
}
144+
}
145+
146+
void surfelwarp::GenericFileFetch::FetchDepthImage(size_t frame_idx, void* depth_img)
147+
{
148+
149+
}
150+
151+
void surfelwarp::GenericFileFetch::FetchRGBImage(size_t frame_idx, cv::Mat& rgb_img)
152+
{
153+
path file_path = this->m_rgb_image_paths[frame_idx];
154+
//Read the image
155+
rgb_img = cv::imread(file_path.string(), CV_ANYCOLOR | CV_ANYDEPTH); // NOLINT(hicpp-signed-bitwise)
156+
if (this->m_use_masks) {
157+
mask_mutex.lock();
158+
if (this->m_mask_buffer_ix != frame_idx) {
159+
m_mask_image_buffer = cv::imread(this->m_mask_image_paths[frame_idx].string(),
160+
CV_ANYCOLOR | CV_ANYDEPTH); // NOLINT(hicpp-signed-bitwise)
161+
m_mask_buffer_ix = frame_idx;
162+
}
163+
cv::Mat masked;
164+
rgb_img.copyTo(masked,m_mask_image_buffer);
165+
mask_mutex.unlock();
166+
rgb_img = masked;
167+
}
168+
}
169+
170+
void surfelwarp::GenericFileFetch::FetchRGBImage(size_t frame_idx, void* rgb_img)
171+
{
172+
173+
}

imgproc/frameio/GenericFileFetch.h

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// ================================================================
2+
// Created by Gregory Kramida on 9/23/19.
3+
// Copyright (c) 2019 Gregory Kramida
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
// ================================================================
16+
#pragma once
17+
18+
#include "FetchInterface.h"
19+
20+
#include <boost/filesystem/path.hpp>
21+
#include <vector>
22+
#include <mutex>
23+
24+
namespace surfelwarp
25+
{
26+
/**
27+
* \brief Utility for fetching depth & RGB frames from images on disk, from the directory specified at construction.
28+
* \details The image filenames must include 0-based index, there must be the same number of RGB and depth frames,
29+
* RGB filenames must include one of {RGB, color, Color, COLOR, rgb} in the filename,
30+
* depth filenames must include one of {depth, DEPTH, Depth} in the filename.
31+
* If the source directory also contains a matching number of likewise-indexed mask images, with each filename
32+
* including one of {mask, Mask, MASK}, the masks are applied to both the RGB and depth images in memory as part
33+
* of the fetch operation.
34+
*/
35+
class GenericFileFetch : public FetchInterface
36+
{
37+
public:
38+
using Ptr = std::shared_ptr<GenericFileFetch>;
39+
using path = boost::filesystem::path;
40+
41+
explicit GenericFileFetch(const path& data_path, std::string file_extension = ".png", bool force_no_masks = false);
42+
~GenericFileFetch() override = default;
43+
44+
//Buffer may be maintained outside fetch object for thread safety
45+
void FetchDepthImage(size_t frame_idx, cv::Mat& depth_img) override;
46+
void FetchDepthImage(size_t frame_idx, void* depth_img) override;
47+
48+
//Should be rgb, in CV_8UC3 format
49+
void FetchRGBImage(size_t frame_idx, cv::Mat& rgb_img) override;
50+
void FetchRGBImage(size_t frame_idx, void* rgb_img) override;
51+
52+
private:
53+
static int GetFrameNumber(const path& filename);
54+
static bool HasSubstringFromSet(const std::string& string, const std::string* set, int set_size);
55+
static bool FilenameIndicatesDepthImage(const path& filename, const std::string& valid_extension);
56+
static bool FilenameIndicatesRGBImage(const path& filename, const std::string& valid_extension);
57+
static bool FilenameIndicatesMaskImage(const path& filename, const std::string& valid_extension);
58+
59+
std::vector<path> m_rgb_image_paths;
60+
std::vector<path> m_depth_image_paths;
61+
std::vector<path> m_mask_image_paths;
62+
63+
size_t m_mask_buffer_ix;
64+
cv::Mat m_mask_image_buffer;
65+
bool m_use_masks;
66+
std::mutex mask_mutex;
67+
};
68+
} // end namespace surfelwarp
69+

imgproc/frameio/VolumeDeformFileFetch.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ boost::filesystem::path surfelwarp::VolumeDeformFileFetch::FileNameVolumeDeform(
3030
{
3131
//Construct the file_name
3232
char frame_idx_str[20];
33-
sprintf(frame_idx_str, "%06d", frame_idx);
33+
sprintf(frame_idx_str, "%06d", static_cast<int>(frame_idx));
3434
std::string file_name = "frame-";
3535
file_name += std::string(frame_idx_str);
3636
if (is_depth_img) {

imgproc/frameio/VolumeDeformFileFetch.h

+6-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55

66
namespace surfelwarp
77
{
8+
/**
9+
* \brief Utility for fetching depth & RGB frames specifically in the format of the VolumeDeform dataset, i.e.
10+
* depth frames named as "frame-000000.depth.png" and RBG frames named as "frame-000000.color.png", where zeros are
11+
* replaced by the zero-based frame index padded on the left by zeroes to be 6 characters long.
12+
*/
813
class VolumeDeformFileFetch : public FetchInterface
914
{
1015
public:
@@ -16,7 +21,7 @@ namespace surfelwarp
1621
const path& data_path
1722
) : m_data_path(data_path) {}
1823

19-
24+
2025
~VolumeDeformFileFetch() = default;
2126

2227
//Main interface
@@ -32,7 +37,4 @@ namespace surfelwarp
3237
path FileNameVolumeDeform(size_t frame_idx, bool is_depth_img) const;
3338
path FileNameSurfelWarp(size_t frame_idx, bool is_depth_img) const;
3439
};
35-
36-
37-
3840
}

0 commit comments

Comments
 (0)