Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: RZ_A2M_Mbed_samples
wimage.hpp
00001 /*M////////////////////////////////////////////////////////////////////////////// 00002 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 00003 // 00004 // By downloading, copying, installing or using the software you agree to 00005 // this license. If you do not agree to this license, do not download, 00006 // install, copy or use the software. 00007 // 00008 // License Agreement 00009 // For Open Source Computer Vision Library 00010 // 00011 // Copyright (C) 2008, Google, all rights reserved. 00012 // Third party copyrights are property of their respective owners. 00013 // 00014 // Redistribution and use in source and binary forms, with or without 00015 // modification, are permitted provided that the following conditions are met: 00016 // 00017 // * Redistribution's of source code must retain the above copyright notice, 00018 // this list of conditions and the following disclaimer. 00019 // 00020 // * Redistribution's in binary form must reproduce the above copyright notice, 00021 // this list of conditions and the following disclaimer in the documentation 00022 // and/or other materials provided with the distribution. 00023 // 00024 // * The name of Intel Corporation or contributors may not be used to endorse 00025 // or promote products derived from this software without specific 00026 // prior written permission. 00027 // 00028 // This software is provided by the copyright holders and contributors "as is" 00029 // and any express or implied warranties, including, but not limited to, the 00030 // implied warranties of merchantability and fitness for a particular purpose 00031 // are disclaimed. In no event shall the Intel Corporation or contributors be 00032 // liable for any direct, indirect, incidental, special, exemplary, or 00033 // consequential damages 00034 // (including, but not limited to, procurement of substitute goods or services; 00035 // loss of use, data, or profits; or business interruption) however caused 00036 // and on any theory of liability, whether in contract, strict liability, 00037 // or tort (including negligence or otherwise) arising in any way out of 00038 // the use of this software, even if advised of the possibility of such damage. 00039 ///////////////////////////////////////////////////////////////////////////////// 00040 //M*/ 00041 00042 #ifndef OPENCV_CORE_WIMAGE_HPP 00043 #define OPENCV_CORE_WIMAGE_HPP 00044 00045 #include "opencv2/core/core_c.h" 00046 00047 #ifdef __cplusplus 00048 00049 namespace cv { 00050 00051 //! @addtogroup core 00052 //! @{ 00053 00054 template <typename T> class WImage; 00055 template <typename T> class WImageBuffer; 00056 template <typename T> class WImageView; 00057 00058 template<typename T, int C> class WImageC; 00059 template<typename T, int C> class WImageBufferC; 00060 template<typename T, int C> class WImageViewC; 00061 00062 // Commonly used typedefs. 00063 typedef WImage<uchar> WImage_b; 00064 typedef WImageView<uchar> WImageView_b; 00065 typedef WImageBuffer<uchar> WImageBuffer_b; 00066 00067 typedef WImageC<uchar, 1> WImage1_b; 00068 typedef WImageViewC<uchar, 1> WImageView1_b; 00069 typedef WImageBufferC<uchar, 1> WImageBuffer1_b; 00070 00071 typedef WImageC<uchar, 3> WImage3_b; 00072 typedef WImageViewC<uchar, 3> WImageView3_b; 00073 typedef WImageBufferC<uchar, 3> WImageBuffer3_b; 00074 00075 typedef WImage<float> WImage_f; 00076 typedef WImageView<float> WImageView_f; 00077 typedef WImageBuffer<float> WImageBuffer_f; 00078 00079 typedef WImageC<float, 1> WImage1_f; 00080 typedef WImageViewC<float, 1> WImageView1_f; 00081 typedef WImageBufferC<float, 1> WImageBuffer1_f; 00082 00083 typedef WImageC<float, 3> WImage3_f; 00084 typedef WImageViewC<float, 3> WImageView3_f; 00085 typedef WImageBufferC<float, 3> WImageBuffer3_f; 00086 00087 // There isn't a standard for signed and unsigned short so be more 00088 // explicit in the typename for these cases. 00089 typedef WImage<short> WImage_16s; 00090 typedef WImageView<short> WImageView_16s; 00091 typedef WImageBuffer<short> WImageBuffer_16s; 00092 00093 typedef WImageC<short, 1> WImage1_16s; 00094 typedef WImageViewC<short, 1> WImageView1_16s; 00095 typedef WImageBufferC<short, 1> WImageBuffer1_16s; 00096 00097 typedef WImageC<short, 3> WImage3_16s; 00098 typedef WImageViewC<short, 3> WImageView3_16s; 00099 typedef WImageBufferC<short, 3> WImageBuffer3_16s; 00100 00101 typedef WImage<ushort> WImage_16u; 00102 typedef WImageView<ushort> WImageView_16u; 00103 typedef WImageBuffer<ushort> WImageBuffer_16u; 00104 00105 typedef WImageC<ushort, 1> WImage1_16u; 00106 typedef WImageViewC<ushort, 1> WImageView1_16u; 00107 typedef WImageBufferC<ushort, 1> WImageBuffer1_16u; 00108 00109 typedef WImageC<ushort, 3> WImage3_16u; 00110 typedef WImageViewC<ushort, 3> WImageView3_16u; 00111 typedef WImageBufferC<ushort, 3> WImageBuffer3_16u; 00112 00113 /** @brief Image class which provides a thin layer around an IplImage. 00114 00115 The goals of the class design are: 00116 00117 -# All the data has explicit ownership to avoid memory leaks 00118 -# No hidden allocations or copies for performance. 00119 -# Easy access to OpenCV methods (which will access IPP if available) 00120 -# Can easily treat external data as an image 00121 -# Easy to create images which are subsets of other images 00122 -# Fast pixel access which can take advantage of number of channels if known at compile time. 00123 00124 The WImage class is the image class which provides the data accessors. The 'W' comes from the fact 00125 that it is also a wrapper around the popular but inconvenient IplImage class. A WImage can be 00126 constructed either using a WImageBuffer class which allocates and frees the data, or using a 00127 WImageView class which constructs a subimage or a view into external data. The view class does no 00128 memory management. Each class actually has two versions, one when the number of channels is known 00129 at compile time and one when it isn't. Using the one with the number of channels specified can 00130 provide some compile time optimizations by using the fact that the number of channels is a 00131 constant. 00132 00133 We use the convention (c,r) to refer to column c and row r with (0,0) being the upper left corner. 00134 This is similar to standard Euclidean coordinates with the first coordinate varying in the 00135 horizontal direction and the second coordinate varying in the vertical direction. Thus (c,r) is 00136 usually in the domain [0, width) X [0, height) 00137 00138 Example usage: 00139 @code 00140 WImageBuffer3_b im(5,7); // Make a 5X7 3 channel image of type uchar 00141 WImageView3_b sub_im(im, 2,2, 3,3); // 3X3 submatrix 00142 vector<float> vec(10, 3.0f); 00143 WImageView1_f user_im(&vec[0], 2, 5); // 2X5 image w/ supplied data 00144 00145 im.SetZero(); // same as cvSetZero(im.Ipl()) 00146 *im(2, 3) = 15; // Modify the element at column 2, row 3 00147 MySetRand(&sub_im); 00148 00149 // Copy the second row into the first. This can be done with no memory 00150 // allocation and will use SSE if IPP is available. 00151 int w = im.Width(); 00152 im.View(0,0, w,1).CopyFrom(im.View(0,1, w,1)); 00153 00154 // Doesn't care about source of data since using WImage 00155 void MySetRand(WImage_b* im) { // Works with any number of channels 00156 for (int r = 0; r < im->Height(); ++r) { 00157 float* row = im->Row(r); 00158 for (int c = 0; c < im->Width(); ++c) { 00159 for (int ch = 0; ch < im->Channels(); ++ch, ++row) { 00160 *row = uchar(rand() & 255); 00161 } 00162 } 00163 } 00164 } 00165 @endcode 00166 00167 Functions that are not part of the basic image allocation, viewing, and access should come from 00168 OpenCV, except some useful functions that are not part of OpenCV can be found in wimage_util.h 00169 */ 00170 template<typename T> 00171 class WImage 00172 { 00173 public: 00174 typedef T BaseType; 00175 00176 // WImage is an abstract class with no other virtual methods so make the 00177 // destructor virtual. 00178 virtual ~WImage() = 0; 00179 00180 // Accessors 00181 IplImage* Ipl() {return image_; } 00182 const IplImage* Ipl() const {return image_; } 00183 T* ImageData() { return reinterpret_cast<T*>(image_->imageData); } 00184 const T* ImageData() const { 00185 return reinterpret_cast<const T*>(image_->imageData); 00186 } 00187 00188 int Width() const {return image_->width; } 00189 int Height() const {return image_->height; } 00190 00191 // WidthStep is the number of bytes to go to the pixel with the next y coord 00192 int WidthStep() const {return image_->widthStep; } 00193 00194 int Channels() const {return image_->nChannels; } 00195 int ChannelSize() const {return sizeof(T); } // number of bytes per channel 00196 00197 // Number of bytes per pixel 00198 int PixelSize() const {return Channels() * ChannelSize(); } 00199 00200 // Return depth type (e.g. IPL_DEPTH_8U, IPL_DEPTH_32F) which is the number 00201 // of bits per channel and with the signed bit set. 00202 // This is known at compile time using specializations. 00203 int Depth() const; 00204 00205 inline const T* Row(int r) const { 00206 return reinterpret_cast<T*>(image_->imageData + r*image_->widthStep); 00207 } 00208 00209 inline T* Row(int r) { 00210 return reinterpret_cast<T*>(image_->imageData + r*image_->widthStep); 00211 } 00212 00213 // Pixel accessors which returns a pointer to the start of the channel 00214 inline T* operator() (int c, int r) { 00215 return reinterpret_cast<T*>(image_->imageData + r*image_->widthStep) + 00216 c*Channels(); 00217 } 00218 00219 inline const T* operator() (int c, int r) const { 00220 return reinterpret_cast<T*>(image_->imageData + r*image_->widthStep) + 00221 c*Channels(); 00222 } 00223 00224 // Copy the contents from another image which is just a convenience to cvCopy 00225 void CopyFrom(const WImage<T>& src) { cvCopy(src.Ipl(), image_); } 00226 00227 // Set contents to zero which is just a convenient to cvSetZero 00228 void SetZero() { cvSetZero(image_); } 00229 00230 // Construct a view into a region of this image 00231 WImageView<T> View(int c, int r, int width, int height); 00232 00233 protected: 00234 // Disallow copy and assignment 00235 WImage(const WImage&); 00236 void operator=(const WImage&); 00237 00238 explicit WImage(IplImage* img) : image_(img) { 00239 assert(!img || img->depth == Depth()); 00240 } 00241 00242 void SetIpl(IplImage* image) { 00243 assert(!image || image->depth == Depth()); 00244 image_ = image; 00245 } 00246 00247 IplImage* image_; 00248 }; 00249 00250 00251 /** Image class when both the pixel type and number of channels 00252 are known at compile time. This wrapper will speed up some of the operations 00253 like accessing individual pixels using the () operator. 00254 */ 00255 template<typename T, int C> 00256 class WImageC : public WImage<T> 00257 { 00258 public: 00259 typedef typename WImage<T>::BaseType BaseType; 00260 enum { kChannels = C }; 00261 00262 explicit WImageC(IplImage* img) : WImage<T>(img) { 00263 assert(!img || img->nChannels == Channels()); 00264 } 00265 00266 // Construct a view into a region of this image 00267 WImageViewC<T, C> View(int c, int r, int width, int height); 00268 00269 // Copy the contents from another image which is just a convenience to cvCopy 00270 void CopyFrom(const WImageC<T, C>& src) { 00271 cvCopy(src.Ipl(), WImage<T>::image_); 00272 } 00273 00274 // WImageC is an abstract class with no other virtual methods so make the 00275 // destructor virtual. 00276 virtual ~WImageC() = 0; 00277 00278 int Channels() const {return C; } 00279 00280 protected: 00281 // Disallow copy and assignment 00282 WImageC(const WImageC&); 00283 void operator=(const WImageC&); 00284 00285 void SetIpl(IplImage* image) { 00286 assert(!image || image->depth == WImage<T>::Depth()); 00287 WImage<T>::SetIpl(image); 00288 } 00289 }; 00290 00291 /** Image class which owns the data, so it can be allocated and is always 00292 freed. It cannot be copied but can be explicity cloned. 00293 */ 00294 template<typename T> 00295 class WImageBuffer : public WImage<T> 00296 { 00297 public: 00298 typedef typename WImage<T>::BaseType BaseType; 00299 00300 // Default constructor which creates an object that can be 00301 WImageBuffer() : WImage<T>(0) {} 00302 00303 WImageBuffer(int width, int height, int nchannels) : WImage<T>(0) { 00304 Allocate(width, height, nchannels); 00305 } 00306 00307 // Constructor which takes ownership of a given IplImage so releases 00308 // the image on destruction. 00309 explicit WImageBuffer(IplImage* img) : WImage<T>(img) {} 00310 00311 // Allocate an image. Does nothing if current size is the same as 00312 // the new size. 00313 void Allocate(int width, int height, int nchannels); 00314 00315 // Set the data to point to an image, releasing the old data 00316 void SetIpl(IplImage* img) { 00317 ReleaseImage(); 00318 WImage<T>::SetIpl(img); 00319 } 00320 00321 // Clone an image which reallocates the image if of a different dimension. 00322 void CloneFrom(const WImage<T>& src) { 00323 Allocate(src.Width(), src.Height(), src.Channels()); 00324 CopyFrom(src); 00325 } 00326 00327 ~WImageBuffer() { 00328 ReleaseImage(); 00329 } 00330 00331 // Release the image if it isn't null. 00332 void ReleaseImage() { 00333 if (WImage<T>::image_) { 00334 IplImage* image = WImage<T>::image_; 00335 cvReleaseImage(&image); 00336 WImage<T>::SetIpl(0); 00337 } 00338 } 00339 00340 bool IsNull() const {return WImage<T>::image_ == NULL; } 00341 00342 private: 00343 // Disallow copy and assignment 00344 WImageBuffer(const WImageBuffer&); 00345 void operator=(const WImageBuffer&); 00346 }; 00347 00348 /** Like a WImageBuffer class but when the number of channels is known at compile time. 00349 */ 00350 template<typename T, int C> 00351 class WImageBufferC : public WImageC<T, C> 00352 { 00353 public: 00354 typedef typename WImage<T>::BaseType BaseType; 00355 enum { kChannels = C }; 00356 00357 // Default constructor which creates an object that can be 00358 WImageBufferC() : WImageC<T, C>(0) {} 00359 00360 WImageBufferC(int width, int height) : WImageC<T, C>(0) { 00361 Allocate(width, height); 00362 } 00363 00364 // Constructor which takes ownership of a given IplImage so releases 00365 // the image on destruction. 00366 explicit WImageBufferC(IplImage* img) : WImageC<T, C>(img) {} 00367 00368 // Allocate an image. Does nothing if current size is the same as 00369 // the new size. 00370 void Allocate(int width, int height); 00371 00372 // Set the data to point to an image, releasing the old data 00373 void SetIpl(IplImage* img) { 00374 ReleaseImage(); 00375 WImageC<T, C>::SetIpl(img); 00376 } 00377 00378 // Clone an image which reallocates the image if of a different dimension. 00379 void CloneFrom(const WImageC<T, C>& src) { 00380 Allocate(src.Width(), src.Height()); 00381 CopyFrom(src); 00382 } 00383 00384 ~WImageBufferC() { 00385 ReleaseImage(); 00386 } 00387 00388 // Release the image if it isn't null. 00389 void ReleaseImage() { 00390 if (WImage<T>::image_) { 00391 IplImage* image = WImage<T>::image_; 00392 cvReleaseImage(&image); 00393 WImageC<T, C>::SetIpl(0); 00394 } 00395 } 00396 00397 bool IsNull() const {return WImage<T>::image_ == NULL; } 00398 00399 private: 00400 // Disallow copy and assignment 00401 WImageBufferC(const WImageBufferC&); 00402 void operator=(const WImageBufferC&); 00403 }; 00404 00405 /** View into an image class which allows treating a subimage as an image or treating external data 00406 as an image 00407 */ 00408 template<typename T> class WImageView : public WImage<T> 00409 { 00410 public: 00411 typedef typename WImage<T>::BaseType BaseType; 00412 00413 // Construct a subimage. No checks are done that the subimage lies 00414 // completely inside the original image. 00415 WImageView(WImage<T>* img, int c, int r, int width, int height); 00416 00417 // Refer to external data. 00418 // If not given width_step assumed to be same as width. 00419 WImageView(T* data, int width, int height, int channels, int width_step = -1); 00420 00421 // Refer to external data. This does NOT take ownership 00422 // of the supplied IplImage. 00423 WImageView(IplImage* img) : WImage<T>(img) {} 00424 00425 // Copy constructor 00426 WImageView(const WImage<T>& img) : WImage<T>(0) { 00427 header_ = *(img.Ipl()); 00428 WImage<T>::SetIpl(&header_); 00429 } 00430 00431 WImageView& operator=(const WImage<T>& img) { 00432 header_ = *(img.Ipl()); 00433 WImage<T>::SetIpl(&header_); 00434 return *this; 00435 } 00436 00437 protected: 00438 IplImage header_; 00439 }; 00440 00441 00442 template<typename T, int C> 00443 class WImageViewC : public WImageC<T, C> 00444 { 00445 public: 00446 typedef typename WImage<T>::BaseType BaseType; 00447 enum { kChannels = C }; 00448 00449 // Default constructor needed for vectors of views. 00450 WImageViewC(); 00451 00452 virtual ~WImageViewC() {} 00453 00454 // Construct a subimage. No checks are done that the subimage lies 00455 // completely inside the original image. 00456 WImageViewC(WImageC<T, C>* img, 00457 int c, int r, int width, int height); 00458 00459 // Refer to external data 00460 WImageViewC(T* data, int width, int height, int width_step = -1); 00461 00462 // Refer to external data. This does NOT take ownership 00463 // of the supplied IplImage. 00464 WImageViewC(IplImage* img) : WImageC<T, C>(img) {} 00465 00466 // Copy constructor which does a shallow copy to allow multiple views 00467 // of same data. gcc-4.1.1 gets confused if both versions of 00468 // the constructor and assignment operator are not provided. 00469 WImageViewC(const WImageC<T, C>& img) : WImageC<T, C>(0) { 00470 header_ = *(img.Ipl()); 00471 WImageC<T, C>::SetIpl(&header_); 00472 } 00473 WImageViewC(const WImageViewC<T, C>& img) : WImageC<T, C>(0) { 00474 header_ = *(img.Ipl()); 00475 WImageC<T, C>::SetIpl(&header_); 00476 } 00477 00478 WImageViewC& operator=(const WImageC<T, C>& img) { 00479 header_ = *(img.Ipl()); 00480 WImageC<T, C>::SetIpl(&header_); 00481 return *this; 00482 } 00483 WImageViewC& operator=(const WImageViewC<T, C>& img) { 00484 header_ = *(img.Ipl()); 00485 WImageC<T, C>::SetIpl(&header_); 00486 return *this; 00487 } 00488 00489 protected: 00490 IplImage header_; 00491 }; 00492 00493 00494 // Specializations for depth 00495 template<> 00496 inline int WImage<uchar>::Depth() const {return IPL_DEPTH_8U; } 00497 template<> 00498 inline int WImage<signed char>::Depth() const {return IPL_DEPTH_8S; } 00499 template<> 00500 inline int WImage<short>::Depth() const {return IPL_DEPTH_16S; } 00501 template<> 00502 inline int WImage<ushort>::Depth() const {return IPL_DEPTH_16U; } 00503 template<> 00504 inline int WImage<int>::Depth() const {return IPL_DEPTH_32S; } 00505 template<> 00506 inline int WImage<float>::Depth() const {return IPL_DEPTH_32F; } 00507 template<> 00508 inline int WImage<double>::Depth() const {return IPL_DEPTH_64F; } 00509 00510 template<typename T> inline WImage<T>::~WImage() {} 00511 template<typename T, int C> inline WImageC<T, C>::~WImageC() {} 00512 00513 template<typename T> 00514 inline void WImageBuffer<T>::Allocate(int width, int height, int nchannels) 00515 { 00516 if (IsNull() || WImage<T>::Width() != width || 00517 WImage<T>::Height() != height || WImage<T>::Channels() != nchannels) { 00518 ReleaseImage(); 00519 WImage<T>::image_ = cvCreateImage(cvSize(width, height), 00520 WImage<T>::Depth(), nchannels); 00521 } 00522 } 00523 00524 template<typename T, int C> 00525 inline void WImageBufferC<T, C>::Allocate(int width, int height) 00526 { 00527 if (IsNull() || WImage<T>::Width() != width || WImage<T>::Height() != height) { 00528 ReleaseImage(); 00529 WImageC<T, C>::SetIpl(cvCreateImage(cvSize(width, height),WImage<T>::Depth(), C)); 00530 } 00531 } 00532 00533 template<typename T> 00534 WImageView<T>::WImageView(WImage<T>* img, int c, int r, int width, int height) 00535 : WImage<T>(0) 00536 { 00537 header_ = *(img->Ipl()); 00538 header_.imageData = reinterpret_cast<char*>((*img)(c, r)); 00539 header_.width = width; 00540 header_.height = height; 00541 WImage<T>::SetIpl(&header_); 00542 } 00543 00544 template<typename T> 00545 WImageView<T>::WImageView(T* data, int width, int height, int nchannels, int width_step) 00546 : WImage<T>(0) 00547 { 00548 cvInitImageHeader(&header_, cvSize(width, height), WImage<T>::Depth(), nchannels); 00549 header_.imageData = reinterpret_cast<char*>(data); 00550 if (width_step > 0) { 00551 header_.widthStep = width_step; 00552 } 00553 WImage<T>::SetIpl(&header_); 00554 } 00555 00556 template<typename T, int C> 00557 WImageViewC<T, C>::WImageViewC(WImageC<T, C>* img, int c, int r, int width, int height) 00558 : WImageC<T, C>(0) 00559 { 00560 header_ = *(img->Ipl()); 00561 header_.imageData = reinterpret_cast<char*>((*img)(c, r)); 00562 header_.width = width; 00563 header_.height = height; 00564 WImageC<T, C>::SetIpl(&header_); 00565 } 00566 00567 template<typename T, int C> 00568 WImageViewC<T, C>::WImageViewC() : WImageC<T, C>(0) { 00569 cvInitImageHeader(&header_, cvSize(0, 0), WImage<T>::Depth(), C); 00570 header_.imageData = reinterpret_cast<char*>(0); 00571 WImageC<T, C>::SetIpl(&header_); 00572 } 00573 00574 template<typename T, int C> 00575 WImageViewC<T, C>::WImageViewC(T* data, int width, int height, int width_step) 00576 : WImageC<T, C>(0) 00577 { 00578 cvInitImageHeader(&header_, cvSize(width, height), WImage<T>::Depth(), C); 00579 header_.imageData = reinterpret_cast<char*>(data); 00580 if (width_step > 0) { 00581 header_.widthStep = width_step; 00582 } 00583 WImageC<T, C>::SetIpl(&header_); 00584 } 00585 00586 // Construct a view into a region of an image 00587 template<typename T> 00588 WImageView<T> WImage<T>::View(int c, int r, int width, int height) { 00589 return WImageView<T>(this, c, r, width, height); 00590 } 00591 00592 template<typename T, int C> 00593 WImageViewC<T, C> WImageC<T, C>::View(int c, int r, int width, int height) { 00594 return WImageViewC<T, C>(this, c, r, width, height); 00595 } 00596 00597 //! @} core 00598 00599 } // end of namespace 00600 00601 #endif // __cplusplus 00602 00603 #endif
Generated on Tue Jul 12 2022 18:20:20 by
