libalvision  2.8.7.4
 All Classes Namespaces Files Functions Variables Friends Macros Pages
alimage_opencv.h
Go to the documentation of this file.
1 
14 #ifndef LIBALVISION_ALVISION_ALIMAGE_OPENCV_H_
15 #define LIBALVISION_ALVISION_ALIMAGE_OPENCV_H_
16 
17 #include <cstring> // for std::memcpy
18 #include <opencv2/core.hpp>
19 #include <opencv2/imgcodecs.hpp>
20 
21 #include <alerror/alerror.h>
22 
23 #include "alimage.h"
24 #include "alvisiondefinitions.h"
25 
26 namespace AL
27 {
34 static inline cv::Mat aLImageToCvMat(const AL::ALImage & al_image, int cv_type = -1)
35 {
36  // OpenCV does not take a const void* because the object could be modified later. This pointer will only be used
37  // in a tmp local cv::Mat so it's fine
38  unsigned char *data = const_cast<unsigned char*>(al_image.getData());
39 
40  if (cv_type >= 0)
41  return cv::Mat(al_image.getHeight(), al_image.getWidth(), cv_type, data);
42 
43  // Check the types
44  int n_layers = AL::getNumLayersInColorSpace(al_image.getColorSpace());
45  int n_channels = AL::getNumChannelsInColorSpace(al_image.getColorSpace());
46  if ((n_layers < 0) || (n_channels < 0)) {
47  std::stringstream ss;
48  ss << "Color space \"" << al_image.getColorSpace() << "\" not supported";
49  throw AL::ALError("ALVision", "aLImageToCvMat", ss.str());
50  }
51  int cv_depth;
52  switch (n_layers / n_channels)
53  {
54  case 4:
55  cv_depth = CV_32F;
56  break;
57  case 2:
58  cv_depth = CV_16U;
59  break;
60  case 1:
61  cv_depth = CV_8U;
62  break;
63  default:
64  std::stringstream ss;
65  ss << "Depth \"" << (n_layers / n_channels) << "\" not supported";
66  throw AL::ALError("ALVision", "aLImageToCvMat", ss.str());
67  }
68 
69  return cv::Mat(al_image.getHeight(), al_image.getWidth(),
70  CV_MAKETYPE(cv_depth, n_channels), data);
71 }
72 
79 static inline AL::ALImage* cvMatToALImage(const cv::Mat & img,
80  int colorSpace,
81  float pLeftAngle = 0.0f, float pTopAngle = 0.0f,
82  float pRightAngle = 0.0f, float pBottomAngle = 0.0f)
83 {
84  // Check the number of channels
85  if (AL::getNumChannelsInColorSpace(colorSpace) != img.channels())
86  throw AL::ALError("ALVision", "cvMatToALImage",
87  "Channel number incompatibility between cv::Mat and colorSpace");
88 
89  // Check the channel type
90  switch (img.depth())
91  {
92  case CV_8U:
93  case CV_16U:
94  case CV_32F:
95  break;
96  default:
97  throw AL::ALError("ALVision", "cvMatToALImage",
98  "Type incompatibility between cv::Mat and colorSpace");
99  }
100 
101  // Create an ALImage with the buffer
102  AL::ALImage *al_image = new AL::ALImage(img.cols, img.rows, colorSpace, true,
103  pLeftAngle, pTopAngle, pRightAngle, pBottomAngle);
104  al_image->setData(img.data);
105 
106  return al_image;
107 }
108 
114 static inline AL::ALImage* cvMatToALImageCopy(const cv::Mat & img,
115  int colorSpace,
116  float pLeftAngle = 0.0f, float pTopAngle = 0.0f,
117  float pRightAngle = 0.0f, float pBottomAngle = 0.0f)
118 {
119  // Check the number of channels
120  if (AL::getNumChannelsInColorSpace(colorSpace) != img.channels())
121  throw AL::ALError("ALVision", "cvMatToALImage",
122  "Channel number incompatibility between cv::Mat and colorSpace");
123 
124  // Check the channel type
125  switch (img.depth())
126  {
127  case CV_8U:
128  case CV_16U:
129  case CV_32F:
130  break;
131  default:
132  throw AL::ALError("ALVision", "cvMatToALImage",
133  "Type incompatibility between cv::Mat and colorSpace");
134  }
135 
136  // Create an ALImage with the buffer
137  AL::ALImage *al_image = new AL::ALImage(img.cols, img.rows, colorSpace, false,
138  pLeftAngle, pTopAngle, pRightAngle, pBottomAngle);
139  std::memcpy(al_image->getData(), img.data, img.cols * img.rows * img.elemSize());
140 
141  return al_image;
142 }
143 
152 static inline bool writeALImageToFile(const std::string& path, const ALImage& al_image)
153 {
154  if(!cv::imwrite(path, aLImageToCvMat(al_image)))
155  {
156  throw AL::ALError("ALVision", "writeALImageToFile",
157  "Can't write image to "+path);
158  }
159 
160  const std::string path_data = path+".yml";
161  cv::FileStorage fs(path_data, cv::FileStorage::WRITE);
162  if(!fs.isOpened())
163  {
164  throw AL::ALError("ALVision", "writeALImageToFile",
165  "Can't open "+path_data+" to write metadata");
166  }
167  try {
168  fs << "width" << al_image.getWidth();
169  fs << "height" << al_image.getHeight();
170 // fs << "nb_layers" << al_image.getNbLayers(); // unused
171  fs << "colorspace" << al_image.getColorSpace();
172  long long timestamp = al_image.getTimeStamp();
173  fs << "timestamp_s" << static_cast<int>(timestamp/1000000ll);
174  fs << "timestamp_us" << static_cast<int>(timestamp%1000000ll);
175  fs << "camera_id" << static_cast<int>(al_image.getCameraId());
176  fs << "fov_left" << al_image.getLeftAngle();
177  fs << "fov_top" << al_image.getTopAngle();
178  fs << "fov_right" << al_image.getRightAngle();
179  fs << "fov_bottom" << al_image.getBottomAngle();
180  fs << "roi_enabled" << al_image.isROIEnabled();
181  fs << "rois" << "[";
182  for(int i = 0; i < al_image.getNumOfROIs(); ++i)
183  {
184  const ALImage::ROI* roi = al_image.getROI(i);
185  fs << "{"
186  << "x" << roi->x
187  << "y" << roi->y
188  << "width" << roi->w
189  << "height" << roi->h
190  << "leftAngle" << roi->leftAngle
191  << "topAngle" << roi->topAngle
192  << "rightAngle" << roi->rightAngle
193  << "bottomAngle" << roi->bottomAngle
194  << "}";
195  }
196  fs << "]";
197  fs.release();
198  } catch(const cv::Exception& e)
199  {
200  throw AL::ALError("ALVision", "writeALImageToFile",
201  "Exception caught when writing metadata to "+path_data+": "+e.what());
202  }
203 
204  return true;
205 }
206 
214 static inline ALImage readALImageFromFile(const std::string& path, int pColorspace = -1)
215 {
216  const cv::Mat img = cv::imread(path, cv::IMREAD_ANYCOLOR);
217 
218  const std::string path_data = path+".yml";
219  cv::FileStorage fs(path_data, cv::FileStorage::READ);
220 
221  if(!fs.isOpened())
222  {
223  if(pColorspace == -1)
224  {
225  throw AL::ALError("ALVision", "readALImageFromFile",
226  "Can't open "+path_data+" to read metadata");
227  }
228  else
229  {
230  ALImage al_image(img.cols, img.rows, pColorspace, false);
231  unsigned char* data = al_image.getData();
232  const size_t data_size = img.cols * img.rows * img.elemSize();
233  std::memcpy(data, img.data, data_size);
234  return al_image;
235  }
236  }
237 
238  int width, height, /*nb_layers, */colorspace, timestamp_s, timestamp_us, camera_id;
239  float fov_left, fov_top, fov_right, fov_bottom;
240  bool roi_enabled;
241  std::vector<ALImage::ROI> rois;
242  try {
243  fs["width"] >> width;
244  fs["height"] >> height;
245 // fs["nb_layers"] >> nb_layers; // unused
246  fs["colorspace"] >> colorspace;
247  fs["timestamp_s"] >> timestamp_s;
248  fs["timestamp_us"] >> timestamp_us;
249  fs["camera_id"] >> camera_id;
250  fs["fov_left"] >> fov_left;
251  fs["fov_top"] >> fov_top;
252  fs["fov_right"] >> fov_right;
253  fs["fov_bottom"] >> fov_bottom;
254  fs["roi_enabled"] >> roi_enabled;
255  cv::FileNode fn_rois = fs["rois"];
256  cv::FileNodeIterator it = fn_rois.begin();
257  for(; it != fn_rois.end(); ++it)
258  {
259  const int roi_x = (*it)["x"];
260  const int roi_y = (*it)["y"];
261  const int roi_w = (*it)["width"];
262  const int roi_h = (*it)["height"];
263  const float roi_leftAngle = (*it)["leftAngle"];
264  const float roi_topAngle = (*it)["topAngle"];
265  const float roi_rightAngle = (*it)["rightAngle"];
266  const float roi_bottomAngle = (*it)["bottomAngle"];
267  const ALImage::ROI roi(roi_x, roi_y, roi_w, roi_h,
268  roi_leftAngle, roi_topAngle, roi_rightAngle, roi_bottomAngle);
269  rois.push_back(roi);
270  }
271  fs.release();
272  } catch(const cv::Exception& e)
273  {
274  throw AL::ALError("ALVision", "readALImageFromFile",
275  "Exception caught when reading metadata from "+path_data+": "+e.what());
276  }
277 
278  if(width != img.cols || height != img.rows)
279  {
280  throw AL::ALError("ALVision", "readALImageFromFile",
281  "Image dimensions do not match metadata");
282  }
283 
284  ALImage al_image(img.cols, img.rows, colorspace, false);
285  unsigned char* data = al_image.getData();
286  const size_t data_size = img.cols * img.rows * img.elemSize();
287  std::memcpy(data, img.data, data_size);
288  al_image.setTimeStamp(timestamp_s, timestamp_us);
289  al_image.setCameraId(static_cast<char>(camera_id));
290  al_image.setAngles(fov_left, fov_top, fov_right, fov_bottom);
291  al_image.setEnableROIs(roi_enabled);
292  for(size_t i = 0; i < rois.size(); ++i)
293  {
294  al_image.addROI(rois[i]);
295  }
296  return al_image;
297 }
298 
299 }
300 
301 #endif /* LIBALVISION_ALVISION_ALIMAGE_OPENCV_H_ */
int getNumChannelsInColorSpace(const int colorSpace)
Utility function that returns the number of channels for a given color space.
int getNumLayersInColorSpace(const int colorSpace)
Utility function that returns the number of layers for a given color space.
void setData(unsigned char *pData)
set the image data pointer to point to the specified buffer.
Definition: alimage.h:196
vision defines
const unsigned char * getData() const
return the reference to the image data.
Definition: alimage.h:171
handle image
int getWidth(void) const
Definition: alimage.h:249
int getHeight(void) const
Definition: alimage.h:250
int getColorSpace(void) const
Definition: alimage.h:252