47#include "../include/image_loading.h"
48#include "../include/Config.h"
50#include <opencv2/imgproc.hpp>
51#include <opencv2/imgcodecs.hpp>
62 using detail::ColorSpace;
63 using detail::g_color_space;
65 void read_raw(std::ifstream& stream, cv::Mat image)
67 CV_Assert(stream.good() && !image.empty() && image.isContinuous());
68 stream.read(
reinterpret_cast<char*
>(image.data), image.size().area() * image.elemSize());
71 cv::Mat read_color_YUV(std::string filepath,
int frame, Parameters
const& parameters) {
72 auto size = parameters.getPaddedSize();
73 auto bit_depth = parameters.getColorBitDepth();
74 auto type = CV_MAKETYPE(cvdepth_from_bit_depth(bit_depth), 1);
75 cv::Mat y_channel(size, type);
76 cv::Mat cb_channel(size / 2, type);
77 cv::Mat cr_channel(size / 2, type);
79 std::ifstream stream(filepath, std::ios::binary);
81 std::ostringstream what;
82 what <<
"Failed to read raw YUV color file \"" << filepath <<
"\"";
83 throw std::runtime_error(what.str());
85 stream.seekg(size.area() * y_channel.elemSize() * 3 / 2 * frame);
86 read_raw(stream, y_channel);
87 read_raw(stream, cb_channel);
88 read_raw(stream, cr_channel);
90 cv::resize(cb_channel, cb_channel, size, 0, 0, cv::INTER_CUBIC);
91 cv::resize(cr_channel, cr_channel, size, 0, 0, cv::INTER_CUBIC);
93 cv::Mat image(size, CV_MAKETYPE(cvdepth_from_bit_depth(bit_depth), 3));
94 cv::Mat src[] = { y_channel, cr_channel, cb_channel };
95 cv::merge(src, 3, image);
99 cv::Mat read_depth_YUV(std::string filepath,
int frame, Parameters
const& parameters) {
100 auto size = parameters.getPaddedSize();
101 auto bit_depth = parameters.getDepthBitDepth();
102 cv::Mat image(size, CV_MAKETYPE(cvdepth_from_bit_depth(bit_depth), 1));
103 std::ifstream stream(filepath, std::ios_base::binary);
104 if (!stream.good()) {
105 std::ostringstream what;
106 what <<
"Failed to read raw YUV depth file \"" << filepath <<
"\"";
107 throw std::runtime_error(what.str());
110 switch (parameters.getDepthColorFormat()) {
111 case ColorFormat::YUV420:
112 stream.seekg(size.area() * image.elemSize() * 3 / 2 * frame);
114 case ColorFormat::YUV400:
115 stream.seekg(size.area() * image.elemSize() * frame);
118 throw std::logic_error(
"Unknown depth map color format");
121 read_raw(stream, image);
125 cv::Mat read_color_RGB(std::string filepath, Parameters
const& parameters) {
126 cv::Mat image = cv::imread(filepath, cv::IMREAD_UNCHANGED);
129 throw std::runtime_error(
"Failed to read color file");
130 if (image.size() != parameters.getPaddedSize())
131 throw std::runtime_error(
"Color file does not have the expected size");
132 if (image.depth() != cvdepth_from_bit_depth(parameters.getColorBitDepth()))
133 throw std::runtime_error(
"Color file has wrong bit depth");
134 if (image.channels() != 3)
135 throw std::runtime_error(
"Color file has wrong number of channels");
140 cv::Mat read_depth_RGB(std::string filepath, Parameters
const& parameters) {
141 cv::Mat image = cv::imread(filepath, cv::IMREAD_UNCHANGED);
144 throw std::runtime_error(
"Failed to read depth file");
145 if (image.size() != parameters.getPaddedSize())
146 throw std::runtime_error(
"Depth file does not have the expected size");
147 if (image.depth() != cvdepth_from_bit_depth(parameters.getDepthBitDepth()))
148 throw std::runtime_error(
"Depth file has the wrong bit depth");
149 if (image.channels() != 1)
150 throw std::runtime_error(
"Depth file has the wrong number of channels");
156 int cvdepth_from_bit_depth(
int bit_depth)
158 if (bit_depth >= 1 && bit_depth <= 8)
160 else if (bit_depth >= 9 && bit_depth <= 16)
162 else if (bit_depth == 32)
164 else throw std::invalid_argument(
"invalid raw image bit depth");
167 unsigned max_level(
int bit_depth)
169 assert(bit_depth > 0 && bit_depth <= 16);
170 return (1u << bit_depth) - 1u;
173 cv::Mat3f read_color(std::string filepath,
int frame, Parameters
const& parameters)
177 ColorSpace color_space;
178 if (filepath.substr(filepath.size() - 4, 4) ==
".yuv") {
179 image = read_color_YUV(filepath, frame, parameters);
180 color_space = ColorSpace::YUV;
182 else if (frame == 0) {
183 image = read_color_RGB(filepath, parameters);
184 color_space = ColorSpace::RGB;
187 throw std::runtime_error(
"Readig multiple frames not (yet) supported for image files");
191 if (parameters.getPaddedSize() != parameters.getSize()) {
192 image = image(parameters.getCropRegion()).clone();
197 if (image.depth() == CV_32F) {
201 image.convertTo(color, CV_32F, 1. / max_level(parameters.getColorBitDepth()));
205 if (color_space == ColorSpace::YUV && g_color_space == ColorSpace::RGB) {
206 cv::cvtColor(color, color, cv::COLOR_YCrCb2BGR);
208 else if (color_space == ColorSpace::RGB && g_color_space == ColorSpace::YUV) {
209 cv::cvtColor(color, color, cv::COLOR_BGR2YCrCb);
215 cv::Mat1f read_depth(std::string filepath,
int frame, Parameters
const& parameters)
219 if (filepath.substr(filepath.size() - 4, 4) ==
".yuv") {
220 image = read_depth_YUV(filepath, frame, parameters);
222 else if (frame == 0) {
223 image = read_depth_RGB(filepath, parameters);
226 throw std::runtime_error(
"Readig multiple frames not (yet) supported for image files");
230 if (parameters.getPaddedSize() != parameters.getSize()) {
231 image = image(parameters.getCropRegion()).clone();
235 if (image.depth() == CV_32F) {
241 image.convertTo(depth, CV_32F, 1. / max_level(parameters.getDepthBitDepth()));
244 auto near = parameters.getDepthRange()[0];
245 auto far = parameters.getDepthRange()[1];
247 depth = near / depth;
250 depth = far * near / (near + depth * (far - near));
254 if (parameters.hasInvalidDepth()) {
257 auto const NaN = std::numeric_limits<float>::quiet_NaN();
258 depth.setTo(NaN, image == 0);