libalvision  2.5.11.14a
 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/core.hpp>
19 #include <opencv2/highgui/highgui.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, int colorSpace,
80  float pLeftAngle = 0.0f, float pTopAngle = 0.0f,
81  float pRightAngle = 0.0f, float pBottomAngle = 0.0f)
82 {
83  // Check the number of channels
84  if (AL::getNumChannelsInColorSpace(colorSpace) != img.channels())
85  throw AL::ALError("ALVision", "cvMatToALImage",
86  "Channel number incompatibility between cv::Mat and colorSpace");
87 
88  // Check the type
89  switch (img.depth())
90  {
91  case CV_8U:
92  case CV_16U:
93  case CV_32F:
94  break;
95  default:
96  throw AL::ALError("ALVision", "cvMatToALImage",
97  "Type incompatibility between cv::Mat and colorSpace");
98  }
99 
100  // Create an ALImage with the buffer
101  AL::ALImage *al_image = new AL::ALImage(img.cols, img.rows, colorSpace, true,
102  pLeftAngle, pTopAngle, pRightAngle, pBottomAngle);
103  al_image->setData(img.data);
104 
105  return al_image;
106 }
107 
113 static inline AL::ALImage* cvMatToALImageCopy(const cv::Mat & img,
114  int colorSpace,
115  float pLeftAngle = 0.0f, float pTopAngle = 0.0f,
116  float pRightAngle = 0.0f, float pBottomAngle = 0.0f)
117 {
118  // Check the number of channels
119  if (AL::getNumChannelsInColorSpace(colorSpace) != img.channels())
120  throw AL::ALError("ALVision", "cvMatToALImage",
121  "Channel number incompatibility between cv::Mat and colorSpace");
122 
123  // Check the type
124  switch (img.type())
125  {
126  case CV_8U:
127  case CV_16U:
128  case CV_32F:
129  break;
130  default:
131  throw AL::ALError("ALVision", "cvMatToALImage",
132  "Type incompatibility between cv::Mat and colorSpace");
133  }
134 
135  // Copy the image data in a buffer
136  size_t data_size = img.cols * img.rows * img.elemSize();
137  unsigned char *data = new unsigned char[data_size];
138  std::memcpy(data, img.data, data_size);
139 
140  // Create an ALImage with the buffer
141  AL::ALImage *al_image = new AL::ALImage(img.cols, img.rows, colorSpace, false,
142  pLeftAngle, pTopAngle, pRightAngle, pBottomAngle);
143  al_image->setData(data);
144 
145  return al_image;
146 }
147 
156 static inline bool writeALImageToFile(const std::string& path, const ALImage& al_image)
157 {
158  if(!cv::imwrite(path, aLImageToCvMat(al_image)))
159  {
160  throw AL::ALError("ALVision", "writeALImageToFile",
161  "Can't write image to "+path);
162  }
163 
164  const std::string path_data = path+".yml";
165  cv::FileStorage fs(path_data, cv::FileStorage::WRITE);
166  if(!fs.isOpened())
167  {
168  throw AL::ALError("ALVision", "writeALImageToFile",
169  "Can't open "+path_data+" to write metadata");
170  }
171  try {
172  fs << "width" << al_image.getWidth();
173  fs << "height" << al_image.getHeight();
174 // fs << "nb_layers" << al_image.getNbLayers(); // unused
175  fs << "colorspace" << al_image.getColorSpace();
176  long long timestamp = al_image.getTimeStamp();
177  fs << "timestamp_s" << static_cast<int>(timestamp/1000000ll);
178  fs << "timestamp_us" << static_cast<int>(timestamp%1000000ll);
179  fs << "camera_id" << static_cast<int>(al_image.getCameraId());
180  fs << "fov_left" << al_image.getLeftAngle();
181  fs << "fov_top" << al_image.getTopAngle();
182  fs << "fov_right" << al_image.getRightAngle();
183  fs << "fov_bottom" << al_image.getBottomAngle();
184  fs << "roi_enabled" << al_image.isROIEnabled();
185  fs << "rois" << "[";
186  for(int i = 0; i < al_image.getNumOfROIs(); ++i)
187  {
188  const ALImage::ROI* roi = al_image.getROI(i);
189  fs << "{"
190  << "x" << roi->x
191  << "y" << roi->y
192  << "width" << roi->w
193  << "height" << roi->h
194  << "leftAngle" << roi->leftAngle
195  << "topAngle" << roi->topAngle
196  << "rightAngle" << roi->rightAngle
197  << "bottomAngle" << roi->bottomAngle
198  << "}";
199  }
200  fs << "]";
201  fs.release();
202  } catch(const cv::Exception& e)
203  {
204  throw AL::ALError("ALVision", "writeALImageToFile",
205  "Exception caught when writing metadata to "+path_data+": "+e.what());
206  }
207 
208  return true;
209 }
210 
218 static inline ALImage readALImageFromFile(const std::string& path, int pColorspace = -1)
219 {
220  const cv::Mat img = cv::imread(path, cv::IMREAD_ANYCOLOR);
221 
222  const std::string path_data = path+".yml";
223  cv::FileStorage fs(path_data, cv::FileStorage::READ);
224 
225  if(!fs.isOpened())
226  {
227  if(pColorspace == -1)
228  {
229  throw AL::ALError("ALVision", "readALImageFromFile",
230  "Can't open "+path_data+" to read metadata");
231  }
232  else
233  {
234  ALImage al_image(img.cols, img.rows, pColorspace, false);
235  unsigned char* data = al_image.getData();
236  const size_t data_size = img.cols * img.rows * img.elemSize();
237  std::memcpy(data, img.data, data_size);
238  return al_image;
239  }
240  }
241 
242  int width, height, /*nb_layers, */colorspace, timestamp_s, timestamp_us, camera_id;
243  float fov_left, fov_top, fov_right, fov_bottom;
244  bool roi_enabled;
245  std::vector<ALImage::ROI> rois;
246  try {
247  fs["width"] >> width;
248  fs["height"] >> height;
249 // fs["nb_layers"] >> nb_layers; // unused
250  fs["colorspace"] >> colorspace;
251  fs["timestamp_s"] >> timestamp_s;
252  fs["timestamp_us"] >> timestamp_us;
253  fs["camera_id"] >> camera_id;
254  fs["fov_left"] >> fov_left;
255  fs["fov_top"] >> fov_top;
256  fs["fov_right"] >> fov_right;
257  fs["fov_bottom"] >> fov_bottom;
258  fs["roi_enabled"] >> roi_enabled;
259  cv::FileNode fn_rois = fs["rois"];
260  cv::FileNodeIterator it = fn_rois.begin();
261  for(; it != fn_rois.end(); ++it)
262  {
263  const int roi_x = (*it)["x"];
264  const int roi_y = (*it)["y"];
265  const int roi_w = (*it)["width"];
266  const int roi_h = (*it)["height"];
267  const float roi_leftAngle = (*it)["leftAngle"];
268  const float roi_topAngle = (*it)["topAngle"];
269  const float roi_rightAngle = (*it)["rightAngle"];
270  const float roi_bottomAngle = (*it)["bottomAngle"];
271  const ALImage::ROI roi(roi_x, roi_y, roi_w, roi_h,
272  roi_leftAngle, roi_topAngle, roi_rightAngle, roi_bottomAngle);
273  rois.push_back(roi);
274  }
275  fs.release();
276  } catch(const cv::Exception& e)
277  {
278  throw AL::ALError("ALVision", "readALImageFromFile",
279  "Exception caught when reading metadata from "+path_data+": "+e.what());
280  }
281 
282  if(width != img.cols || height != img.rows)
283  {
284  throw AL::ALError("ALVision", "readALImageFromFile",
285  "Image dimensions do not match metadata");
286  }
287 
288  ALImage al_image(img.cols, img.rows, colorspace, false);
289  unsigned char* data = al_image.getData();
290  const size_t data_size = img.cols * img.rows * img.elemSize();
291  std::memcpy(data, img.data, data_size);
292  al_image.setTimeStamp(timestamp_s, timestamp_us);
293  al_image.setCameraId(static_cast<char>(camera_id));
294  al_image.setAngles(fov_left, fov_top, fov_right, fov_bottom);
295  al_image.setEnableROIs(roi_enabled);
296  for(size_t i = 0; i < rois.size(); ++i)
297  {
298  al_image.addROI(rois[i]);
299  }
300  return al_image;
301 }
302 
303 }
304 
305 #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