rgbd
serialization.cpp
Go to the documentation of this file.
1 #include "rgbd/serialization.h"
2 #include "rgbd/image.h"
3 
4 #include <ros/console.h>
5 
8 
9 #include <opencv2/core.hpp>
10 #include <opencv2/imgcodecs.hpp>
11 
12 namespace rgbd
13 {
14 
15 const static int SERIALIZATION_VERSION = 2;
16 
17 // ----------------------------------------------------------------------------------------------------
18 //
19 // SERIALIZATION
20 //
21 // ----------------------------------------------------------------------------------------------------
22 
24  RGBStorageType rgb_type, DepthStorageType depth_type)
25 {
26  // - - - - - - - - - - - - - - - - GENERAL INFO - - - - - - - - - - - - - - - -
27 
29 
30  a << image.getFrameId();
31  a << image.getTimestamp();
32 
33  // - - - - - - - - - - - - - - - - CAMERA INFO - - - - - - - - - - - - - - - -
34 
35  const image_geometry::PinholeCameraModel& cam_model = image.cam_model_;
36 
37  if (cam_model.initialized())
38  {
40  a << cam_model.fx() << cam_model.fy();
41  a << cam_model.cx() << cam_model.cy();
42  a << cam_model.Tx() << cam_model.Ty();
43  a << cam_model.fullResolution().width << cam_model.fullResolution().height;
44  }
45  else
46  {
47  ROS_ERROR_NAMED("serialization", "rgbd::serialize: cam_model not initialized");
48  return false;
49  }
50 
51  // - - - - - - - - - - - - - - - - RGB IMAGE - - - - - - - - - - - - - - - -
52 
53  if (!image.rgb_image_.data)
54  rgb_type = RGB_STORAGE_NONE;
55 
56  a << rgb_type;
57 
58  if (rgb_type == RGB_STORAGE_NONE)
59  {
60  }
61  else if (rgb_type == RGB_STORAGE_LOSSLESS)
62  {
63  a << image.rgb_image_.cols;
64  a << image.rgb_image_.rows;
65 
66  int size = image.rgb_image_.rows * image.rgb_image_.cols * 3;
67  a.write((const char*)image.rgb_image_.data, size);
68  }
69  else if (rgb_type == RGB_STORAGE_JPG)
70  {
71  // OpenCV compression settings
72  std::vector<int> rgb_params;
73  rgb_params.resize(3, 0);
74 
75  rgb_params[0] = cv::IMWRITE_JPEG_QUALITY;
76  rgb_params[1] = 95; // default is 95
77 
79 
80  // Compress image
81  if (!cv::imencode(".jpg", image.rgb_image_, rgb_data, rgb_params)) {
82  ROS_ERROR_NAMED("serialization", "RGB image compression failed");
83  return false;
84  }
85 
86  a << (int)rgb_data.size();
87  a.write((const char*)&rgb_data[0], rgb_data.size());
88  }
89  else
90  {
91  ROS_ERROR_STREAM_NAMED("serialization", "Unsupported RGB STORAGE TYPE: " << rgb_type);
92  return false;
93  }
94 
95  // - - - - - - - - - - - - - - - - DEPTH IMAGE - - - - - - - - - - - - - - - -
96 
97  if (!image.depth_image_.data)
98  depth_type = DEPTH_STORAGE_NONE;
99 
100  a << depth_type;
101 
102  if (depth_type == DEPTH_STORAGE_NONE)
103  {
104  }
105  else if (depth_type == DEPTH_STORAGE_LOSSLESS)
106  {
107  a << image.depth_image_.cols;
108  a << image.depth_image_.rows;
109 
110  int size = image.depth_image_.rows * image.depth_image_.cols * 4;
111  a.write((const char*)image.depth_image_.data, size);
112  }
113  else if (depth_type == DEPTH_STORAGE_PNG)
114  {
115  float depthZ0 = 100; //config_.depth_quantization;
116  float depthMax = 10; //config_.depth_max;
117 
118  float depthQuantA = depthZ0 * (depthZ0 + 1.0f);
119  float depthQuantB = 1.0f - depthQuantA / depthMax;
120 
121  a << depthQuantA << depthQuantB;
122 
123  const cv::Mat& depth_image = image.depth_image_;
124  cv::Mat invDepthImg(depth_image.size(), CV_16UC1);
125 
126  // Matrix iterators
127  cv::MatConstIterator_<float> itDepthImg = depth_image.begin<float>(),
128  itDepthImg_end = depth_image.end<float>();
129  cv::MatIterator_<unsigned short> itInvDepthImg = invDepthImg.begin<unsigned short>(),
130  itInvDepthImg_end = invDepthImg.end<unsigned short>();
131 
132  // Quantization
133  for (; (itDepthImg != itDepthImg_end) && (itInvDepthImg != itInvDepthImg_end); ++itDepthImg, ++itInvDepthImg) {
134  // check for NaN & max depth
135  if (*itDepthImg < depthMax){
136  *itInvDepthImg = depthQuantA / *itDepthImg + depthQuantB;
137  } else{
138  *itInvDepthImg = 0;
139  }
140  }
141 
142  // Compression settings
143  std::vector<int> params;
144  params.resize(3, 0);
145 
146  params[0] = cv::IMWRITE_PNG_COMPRESSION;
147  params[1] = 1;
148 
149  std::vector<unsigned char> depth_data;
150 
151  if (!cv::imencode(".png", invDepthImg, depth_data, params)) {
152  ROS_ERROR_NAMED("serialization", "Depth image compression failed");
153  return false;
154  }
155 
156  a << static_cast<int>(depth_data.size());
157  a.write((const char*)&depth_data[0], depth_data.size());
158  }
159  else
160  {
161  ROS_ERROR_NAMED("serialization", "Unsupported DEPTH_STORAGE_TYPE");
162  return false;
163  }
164 
165  return true;
166 }
167 
168 // ----------------------------------------------------------------------------------------------------
169 //
170 // DESERIALIZATION
171 //
172 // ----------------------------------------------------------------------------------------------------
173 
175 {
176  // - - - - - - - - - - - - - - - - GENERAL INFO - - - - - - - - - - - - - - - -
177 
178  int version;
179  a >> version;
180 
181  a >> image.frame_id_;
182  a >> image.timestamp_;
183 
184  // - - - - - - - - - - - - - - - - CAMERA INFO - - - - - - - - - - - - - - - -
185 
186  int cam_type;
187  a >> cam_type;
188 
189  if (cam_type == CAMERA_MODEL_NONE)
190  {
191  }
192  else if (cam_type == CAMERA_MODEL_PINHOLE)
193  {
194  double fx, fy, cx, cy, tx, ty;
195  int width, height;
196  a >> fx >> fy;
197  a >> cx >> cy;
198  a >> tx >> ty;
199  if (version >=2)
200  a >> width >> height;
201 
202  sensor_msgs::CameraInfo cam_info_msg;
203 
204  cam_info_msg.D.resize(5, 0.0);
205  cam_info_msg.K.fill(0.0);
206  cam_info_msg.K[0] = fx; // fx
207  cam_info_msg.K[2] = cx; // cx
208  cam_info_msg.K[4] = fy; // fy
209  cam_info_msg.K[5] = cy; // cy
210  cam_info_msg.K[8] = 1.0;
211 
212  cam_info_msg.R.fill(0.0);
213  cam_info_msg.R[0] = 1.0;
214  cam_info_msg.R[4] = 1.0;
215  cam_info_msg.R[8] = 1.0;
216 
217  cam_info_msg.P.fill(0.0);
218  cam_info_msg.P[0] = fx; // fx
219  cam_info_msg.P[2] = cx; // cx
220  cam_info_msg.P[3] = tx; // Tx
221  cam_info_msg.P[5] = fy; // fy
222  cam_info_msg.P[6] = cy; // cy
223  cam_info_msg.P[7] = ty; // Ty
224  cam_info_msg.P[10] = 1.0;
225 
226  cam_info_msg.distortion_model = "plumb_bob";
227  if (version >= 2){
228  cam_info_msg.width = width;
229  cam_info_msg.height = height;
230  }
231  image.cam_model_.fromCameraInfo(cam_info_msg);
232  }
233  else
234  {
235  ROS_ERROR_STREAM_NAMED("serialization", "rgbd::deserialize: Unsupported camera model: " << cam_type);
236  return false;
237  }
238 
239  // - - - - - - - - - - - - - - - - RGB IMAGE - - - - - - - - - - - - - - - -
240 
241  int rgb_type;
242  a >> rgb_type;
243 
244  if (rgb_type == RGB_STORAGE_NONE)
245  {
246  }
247  else if (rgb_type == RGB_STORAGE_LOSSLESS)
248  {
249  int width, height;
250  a >> width;
251  a >> height;
252 
253  int size = width * height * 3;
254  image.rgb_image_ = cv::Mat(height, width, CV_8UC3);
255  for(int i = 0; i < size; ++i)
256  a >> image.rgb_image_.data[i];
257  }
258  else if (rgb_type == RGB_STORAGE_JPG)
259  {
260  int rgb_size;
261  a >> rgb_size;
262 
263  std::vector<unsigned char> rgb_data(rgb_size);
264  for(int i = 0; i < rgb_size; ++i)
265  a >> rgb_data[i];
266 
267  image.rgb_image_ = cv::imdecode(rgb_data, cv::IMREAD_UNCHANGED);
268  }
269  else
270  {
271  ROS_ERROR_STREAM_NAMED("serialization", "rgbd::deserialize: Unsupported rgb storage format: " << rgb_type);
272  return false;
273  }
274 
275  // - - - - - - - - - - - - - - - - DEPTH IMAGE - - - - - - - - - - - - - - - -
276 
277  int depth_type;
278  a >> depth_type;
279 
280  if (depth_type == DEPTH_STORAGE_NONE)
281  {
282  }
283  else if (depth_type == DEPTH_STORAGE_LOSSLESS)
284  {
285  int width, height;
286  a >> width;
287  a >> height;
288 
289  int size = width * height * 4;
290  image.depth_image_ = cv::Mat(height, width, CV_32FC1);
291  for(int i = 0; i < size; ++i)
292  a >> image.depth_image_.data[i];
293  }
294  else if (depth_type == DEPTH_STORAGE_PNG)
295  {
296  float depthQuantA, depthQuantB;
297  a >> depthQuantA >> depthQuantB;
298 
299  int depth_size;
300  a >> depth_size;
301 
302  std::vector<unsigned char> depth_data(depth_size);
303  for(int i = 0; i < depth_size; ++i)
304  a >> depth_data[i];
305 
306  cv::Mat decompressed = cv::imdecode(depth_data, cv::IMREAD_UNCHANGED);
307  cv::Mat& depth_image = image.depth_image_;
308  depth_image = cv::Mat(decompressed.size(), CV_32FC1);
309 
310  // Depth conversion
311  cv::MatIterator_<float> itDepthImg = depth_image.begin<float>(),
312  itDepthImg_end = depth_image.end<float>();
313  cv::MatConstIterator_<unsigned short> itInvDepthImg = decompressed.begin<unsigned short>(),
314  itInvDepthImg_end = decompressed.end<unsigned short>();
315 
316  for (; (itDepthImg != itDepthImg_end) && (itInvDepthImg != itInvDepthImg_end); ++itDepthImg, ++itInvDepthImg) {
317  // check for NaN & max depth
318  if (*itInvDepthImg) {
319  *itDepthImg = depthQuantA / ((float)*itInvDepthImg - depthQuantB);
320  } else {
322  }
323  }
324  }
325  else
326  {
327  ROS_ERROR_STREAM_NAMED("serialization", "rgbd::deserialize: Unsupported depth storage format: " << depth_type);
328  return false;
329  }
330 
331  return true;
332 }
333 
334 }
std::vector::resize
T resize(T... args)
input_archive.h
rgbd::Image::cam_model_
image_geometry::PinholeCameraModel cam_model_
Camera model Header in camera info should always be empty to prevent inconsistent behaviour of equali...
Definition: image.h:179
rgbd::Image::getTimestamp
double getTimestamp() const
Get the timestamp.
Definition: image.h:90
a
void a()
std::numeric_limits::quiet_NaN
T quiet_NaN(T... args)
std::vector
std::vector::size
T size(T... args)
rgbd::deserialize
bool deserialize(tue::serialization::InputArchive &a, Image &image)
Definition: serialization.cpp:174
tue::serialization::OutputArchive
rgbd::CAMERA_MODEL_PINHOLE
@ CAMERA_MODEL_PINHOLE
Definition: image.h:26
rgbd::SERIALIZATION_VERSION
const static int SERIALIZATION_VERSION
Definition: serialization.cpp:15
rgbd::serialize
bool serialize(const Image &image, tue::serialization::OutputArchive &a, RGBStorageType rgb_type=RGB_STORAGE_JPG, DepthStorageType depth_type=DEPTH_STORAGE_PNG)
Definition: serialization.cpp:23
rgbd::DepthStorageType
DepthStorageType
Definition: image.h:36
rgbd::Image::frame_id_
std::string frame_id_
Definition: image.h:181
rgbd::Image
Definition: image.h:43
rgbd::RGB_STORAGE_JPG
@ RGB_STORAGE_JPG
Definition: image.h:33
rgbd
Definition: client.h:24
rgbd::RGBStorageType
RGBStorageType
Definition: image.h:29
rgbd::DEPTH_STORAGE_NONE
@ DEPTH_STORAGE_NONE
Definition: image.h:38
image.h
rgbd::DEPTH_STORAGE_PNG
@ DEPTH_STORAGE_PNG
Definition: image.h:40
tue::serialization::InputArchive
rgbd::Image::depth_image_
cv::Mat depth_image_
Definition: image.h:173
rgbd::RGB_STORAGE_LOSSLESS
@ RGB_STORAGE_LOSSLESS
Definition: image.h:32
rgbd::Image::timestamp_
double timestamp_
Definition: image.h:182
rgbd::Image::getFrameId
const std::string & getFrameId() const
Get the frame_id.
Definition: image.h:84
serialization.h
rgbd::DEPTH_STORAGE_LOSSLESS
@ DEPTH_STORAGE_LOSSLESS
Definition: image.h:39
rgbd::CAMERA_MODEL_NONE
@ CAMERA_MODEL_NONE
Definition: image.h:25
output_archive.h
rgbd::RGB_STORAGE_NONE
@ RGB_STORAGE_NONE
Definition: image.h:31
rgbd::Image::rgb_image_
cv::Mat rgb_image_
Definition: image.h:172