iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
OpenCVImpl.H
Go to the documentation of this file.
1 /*! @file
2  @author Unknown
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 namespace nrt
35 {
36  namespace cvhelpers
37  {
38  //! Decide whether the given OpenCV IPL depth ID (e.g. IPL_DEPTH_8U) matches the depth of the given NRT pixel type.
39  template<class T> inline bool matchesIplDepth(int depth)
40  { return false; }
41  template <> inline bool matchesIplDepth<uint8>(int depth)
42  { return depth == (int)IPL_DEPTH_8U; }
43  template <> inline bool matchesIplDepth<int8>(int depth)
44  { return depth == (int)IPL_DEPTH_8S; }
45  template <> inline bool matchesIplDepth<uint16>(int depth)
46  { return depth == (int)IPL_DEPTH_16U; }
47  template <> inline bool matchesIplDepth<int16>(int depth)
48  { return depth == (int)IPL_DEPTH_16S; }
49  template <> inline bool matchesIplDepth<int32>(int depth)
50  { return depth == (int)IPL_DEPTH_32S; }
51  template <> inline bool matchesIplDepth<float>(int depth)
52  { return depth == (int)IPL_DEPTH_32F; }
53  template <> inline bool matchesIplDepth<double>(int depth)
54  { return depth == (int)IPL_DEPTH_64F; }
55 
56  //! Decide whether the given OpenCV depth ID (e.g. CV_8U) matches the depth of the given NRT pixel type.
57  template<class T> inline bool matchesCvDepth(int depth)
58  { return false; }
59  template <> inline bool matchesCvDepth<uint8>(int depth)
60  { return depth == (int)CV_8U; }
61  template <> inline bool matchesCvDepth<int8>(int depth)
62  { return depth == (int)CV_8S; }
63  template <> inline bool matchesCvDepth<uint16>(int depth)
64  { return depth == (int)CV_16U; }
65  template <> inline bool matchesCvDepth<int16>(int depth)
66  { return depth == (int)CV_16S; }
67  template <> inline bool matchesCvDepth<int32>(int depth)
68  { return depth == (int)CV_32S; }
69  template <> inline bool matchesCvDepth<float>(int depth)
70  { return depth == (int)CV_32F; }
71  template <> inline bool matchesCvDepth<double>(int depth)
72  { return depth == (int)CV_64F; }
73 
74  //! Convert an OpenCV IPL depth ID to a string for error messages.
75  /*! (e.g. IPL_DEPTH_8U will convert to the string "IPL_DEPTH_8U") */
76  inline std::string iplDepth2String(int depth)
77  {
78  if(depth == (int)IPL_DEPTH_8U) return "IPL_DEPTH_8U";
79  if(depth == (int)IPL_DEPTH_8S) return "IPL_DEPTH_8S";
80  if(depth == (int)IPL_DEPTH_16U) return "IPL_DEPTH_16U";
81  if(depth == (int)IPL_DEPTH_16S) return "IPL_DEPTH_16S";
82  if(depth == (int)IPL_DEPTH_32S) return "IPL_DEPTH_32S";
83  if(depth == (int)IPL_DEPTH_32F) return "IPL_DEPTH_32F";
84  if(depth == (int)IPL_DEPTH_64F) return "IPL_DEPTH_64F";
85  return "Unknown Depth";
86  }
87 
88  //! Convert an OpenCV depth ID to a string for error messages.
89  /*! (e.g. CV_8U will convert to the string "CV_8U") */
90  inline std::string cvDepth2String(int depth)
91  {
92  if(depth == (int)CV_8U) return "CV_8U";
93  if(depth == (int)CV_8S) return "CV_8S";
94  if(depth == (int)CV_16U) return "CV_16U";
95  if(depth == (int)CV_16S) return "CV_16S";
96  if(depth == (int)CV_32S) return "CV_32S";
97  if(depth == (int)CV_32F) return "CV_32F";
98  if(depth == (int)CV_64F) return "CV_64F";
99  return "Unknown Depth";
100  }
101 
102  //! Convert a POD type to an OpenCV IPL type ID (e.g. float will convert to IPL_DEPTH_32F).
103  template<class T> inline int type2IplDepth()
104  { return -1; }
105  template <> inline int type2IplDepth<uint8>()
106  { return (int)IPL_DEPTH_8U; }
107  template <> inline int type2IplDepth<int8>()
108  { return (int)IPL_DEPTH_8S; }
109  template <> inline int type2IplDepth<uint16>()
110  { return (int)IPL_DEPTH_16U; }
111  template <> inline int type2IplDepth<int16>()
112  { return (int)IPL_DEPTH_16S; }
113  template <> inline int type2IplDepth<int32>()
114  { return (int)IPL_DEPTH_32S; }
115  template <> inline int type2IplDepth<float>()
116  { return (int)IPL_DEPTH_32F; }
117  template <> inline int type2IplDepth<double>()
118  { return (int)IPL_DEPTH_64F; }
119 
120  //! Convert a POD type to an OpenCV depth ID (e.g. float will convert to CV_32F).
121  template<class T> inline int type2CvDepth()
122  { return -1; }
123  template <> inline int type2CvDepth<uint8>()
124  { return (int)CV_8U; }
125  template <> inline int type2CvDepth<int8>()
126  { return (int)CV_8S; }
127  template <> inline int type2CvDepth<uint16>()
128  { return (int)CV_16U; }
129  template <> inline int type2CvDepth<int16>()
130  { return (int)CV_16S; }
131  template <> inline int type2CvDepth<int32>()
132  { return (int)CV_32S; }
133  template <> inline int type2CvDepth<float>()
134  { return (int)CV_32F; }
135  template <> inline int type2CvDepth<double>()
136  { return (int)CV_64F; }
137 
138  //! Convert an nrt pixel type to an OpenCV type ID (e.g. PixRGB<byte> will convert to CV_8UC3).
139  template<class PixType> inline
140  int pixType2CvType()
141  {
142  return CV_MAKETYPE(type2CvDepth<typename PixType::PODType>(), PixType::numChannels);
143  }
144  }
145 }
146 
147 // ######################################################################
148  template<class PixType> inline
149 nrt::Image<PixType> nrt::copyIpl2Image(IplImage const * const iplimage)
150 {
151  // Make sure the number of channels match up
152  if(iplimage->nChannels != int(PixType::numChannels))
154  nrt::sformat("Wrong number of channels in copyIpl2Image. Source iplimage has %d channel%s, "
155  "but target %s has %zu channel%s.",
156  iplimage->nChannels, iplimage->nChannels > 1 ? "s" : "",
157  nrt::demangledName<PixType>().c_str(),
158  PixType::numChannels, PixType::numChannels > 1 ? "s" : ""));
159 
160  // Make sure the POD type matches up
161  if(!nrt::cvhelpers::matchesIplDepth<typename PixType::PODType>(iplimage->depth))
163  "Wrong depth in copyIpl2Image. "
164  "Source iplimage has depth of " + nrt::cvhelpers::iplDepth2String(iplimage->depth) + ", "
165  "which is different from the requested " + nrt::demangledName<PixType>().c_str());
166 
167  nrt::Image<PixType> ret(iplimage->width, iplimage->height, ImageInitPolicy::None);
168 
169  // If the IplImage is tightly packed then we can do this copy in one memcpy. Otherwise,
170  // we'll need to copy row by row.
171  if((size_t)iplimage->imageSize ==
172  iplimage->width*iplimage->height*sizeof(typename PixType::PODType)*PixType::numChannels)
173  {
174  memcpy(ret.pod_begin(), iplimage->imageData, iplimage->imageSize);
175  }
176  else
177  {
178  typename PixType::PODType *cvRow = reinterpret_cast<typename PixType::PODType*>(iplimage->imageData);
179  typename nrt::Image<PixType>::col_iterator nrtRow = ret.col_begin(0);
180  while(nrtRow != ret.col_end(0))
181  {
182  memcpy(&(nrtRow->channels[0]), cvRow, iplimage->widthStep);
183  cvRow += iplimage->widthStep;
184  ++nrtRow;
185  }
186  }
187 
188  return ret;
189 }
190 
191 // ######################################################################
192  template<class PixType> inline
194 {
195  IplImage* iplimage = cvCreateImage(cvSize(img.width(),img.height()),
196  nrt::cvhelpers::type2IplDepth<typename PixType::PODType>(), PixType::numChannels);
197 
198  // If the IplImage is tightly packed then we can do this copy in one memcpy. Otherwise,
199  // we'll need to copy row by row.
200  if((size_t)iplimage->imageSize ==
201  iplimage->width*iplimage->height*sizeof(typename PixType::PODType)*PixType::numChannels)
202  {
203  memcpy(iplimage->imageData, img.pod_begin(), iplimage->imageSize);
204  }
205  else
206  {
207  typename PixType::PODType *cvRow = reinterpret_cast<typename PixType::PODType*>(iplimage->imageData);
208  typename nrt::Image<PixType>::const_col_iterator nrtRow = img.col_begin(0);
209  while(nrtRow != img.col_end(0))
210  {
211  memcpy(cvRow, &(nrtRow->channels[0]), sizeof(typename PixType::PODType)*PixType::numChannels*iplimage->width);
212  cvRow += iplimage->widthStep;
213  ++nrtRow;
214  }
215  }
216  return iplimage;
217 }
218 
219 // ######################################################################
220  template<class PixType> inline
221 nrt::Image<PixType> nrt::copyCvMat2Image(cv::Mat const mat)
222 {
223  // Make sure the number of channels match up
224  if(mat.channels() != int(PixType::numChannels))
226  nrt::sformat("Wrong number of channels in copyCvMat2Image. Source cv::Mat has %d channel%s, "
227  "but target %s has %zu channel%s.",
228  mat.channels(), mat.channels() > 1 ? "s" : "",
229  nrt::demangledName<PixType>().c_str(),
230  PixType::numChannels, PixType::numChannels > 1 ? "s" : ""));
231 
232  // Make sure the POD type matches up
233  if(!nrt::cvhelpers::matchesCvDepth<typename PixType::PODType>(mat.depth()))
235  "Wrong depth in copyCvMat2Image. "
236  "Source cv::Mat has depth of " + nrt::cvhelpers::cvDepth2String(mat.depth()) + ", "
237  "which is different from the requested " + nrt::demangledName<PixType>().c_str());
238 
239  nrt::Image<PixType> ret(mat.cols, mat.rows, nrt::ImageInitPolicy::None);
240 
241  // If the IplImage is tightly packed then we can do this copy in one memcpy. Otherwise,
242  // we'll need to copy row by row.
243  if(mat.isContinuous())
244  {
245  memcpy(ret.pod_begin(), mat.ptr(0), mat.elemSize() * mat.total());
246  }
247  else
248  {
249  typename PixType::PODType const *cvRow = reinterpret_cast<typename PixType::PODType const*>(mat.ptr(0));
250  typename nrt::Image<PixType>::col_iterator nrtRow = ret.col_begin(0);
251  while(nrtRow != ret.col_end(0))
252  {
253  memcpy(&(nrtRow->channels[0]), cvRow, mat.elemSize() * mat.cols);
254  cvRow += mat.step;
255  ++nrtRow;
256  }
257  }
258 
259  return ret;
260 }
261 
262 // ######################################################################
263  template<class PixType> inline
265 {
266  cv::Mat mat(img.height(), img.width(), nrt::cvhelpers::pixType2CvType<PixType>());
267 
268  // If the cv::Mat is tightly packed then we can do this copy in one memcpy. Otherwise,
269  // we'll need to copy row by row.
270  if(mat.isContinuous())
271  {
272  memcpy(mat.ptr(0), img.pod_begin(), mat.elemSize() * mat.total());
273  }
274  else
275  {
276  typename PixType::PODType *cvRow = reinterpret_cast<typename PixType::PODType*>(mat.ptr(0));
277  typename nrt::Image<PixType>::const_col_iterator nrtRow = img.col_begin(0);
278  while(nrtRow != img.col_end(0))
279  {
280  memcpy(cvRow, &(nrtRow->channels[0]), mat.elemSize() * mat.cols);
281  cvRow += mat.step;
282  ++nrtRow;
283  }
284  }
285  return mat;
286 }
287