| /////////////////////////////////////////////////////////////////////////////// |
| // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. |
| // |
| // By downloading, copying, installing or using the software you agree to |
| // this license. If you do not agree to this license, do not download, |
| // install, copy or use the software. |
| // |
| // License Agreement |
| // For Open Source Computer Vision Library |
| // |
| // Copyright (C) 2008, Google, all rights reserved. |
| // Third party copyrights are property of their respective owners. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are met: |
| // |
| // * Redistribution's of source code must retain the above copyright notice, |
| // this list of conditions and the following disclaimer. |
| // |
| // * Redistribution's in binary form must reproduce the above copyright notice, |
| // this list of conditions and the following disclaimer in the documentation |
| // and/or other materials provided with the distribution. |
| // |
| // * The name of Intel Corporation or contributors may not be used to endorse |
| // or promote products derived from this software without specific |
| // prior written permission. |
| // |
| // This software is provided by the copyright holders and contributors "as is" |
| // and any express or implied warranties, including, but not limited to, the |
| // implied warranties of merchantability and fitness for a particular purpose |
| // are disclaimed. In no event shall the Intel Corporation or contributors be |
| // liable for any direct, indirect, incidental, special, exemplary, or |
| // consequential damages |
| // (including, but not limited to, procurement of substitute goods or services; |
| // loss of use, data, or profits; or business interruption) however caused |
| // and on any theory of liability, whether in contract, strict liability, |
| // or tort (including negligence or otherwise) arising in any way out of |
| // the use of this software, even if advised of the possibility of such damage. |
| |
| |
| ///////////////////////////////////////////////////////////////////////////////// |
| // |
| // Image class which provides a thin layer around an IplImage. The goals |
| // of the class design are: |
| // 1. All the data has explicit ownership to avoid memory leaks |
| // 2. No hidden allocations or copies for performance. |
| // 3. Easy access to OpenCV methods (which will access IPP if available) |
| // 4. Can easily treat external data as an image |
| // 5. Easy to create images which are subsets of other images |
| // 6. Fast pixel access which can take advantage of number of channels |
| // if known at compile time. |
| // |
| // The WImage class is the image class which provides the data accessors. |
| // The 'W' comes from the fact that it is also a wrapper around the popular |
| // but inconvenient IplImage class. A WImage can be constructed either using a |
| // WImageBuffer class which allocates and frees the data, |
| // or using a WImageView class which constructs a subimage or a view into |
| // external data. The view class does no memory management. Each class |
| // actually has two versions, one when the number of channels is known at |
| // compile time and one when it isn't. Using the one with the number of |
| // channels specified can provide some compile time optimizations by using the |
| // fact that the number of channels is a constant. |
| // |
| // We use the convention (c,r) to refer to column c and row r with (0,0) being |
| // the upper left corner. This is similar to standard Euclidean coordinates |
| // with the first coordinate varying in the horizontal direction and the second |
| // coordinate varying in the vertical direction. |
| // Thus (c,r) is usually in the domain [0, width) X [0, height) |
| // |
| // Example usage: |
| // WImageBuffer3_b im(5,7); // Make a 5X7 3 channel image of type uchar |
| // WImageView3_b sub_im(im, 2,2, 3,3); // 3X3 submatrix |
| // vector<float> vec(10, 3.0f); |
| // WImageView1_f user_im(&vec[0], 2, 5); // 2X5 image w/ supplied data |
| // |
| // im.SetZero(); // same as cvSetZero(im.Ipl()) |
| // *im(2, 3) = 15; // Modify the element at column 2, row 3 |
| // MySetRand(&sub_im); |
| // |
| // // Copy the second row into the first. This can be done with no memory |
| // // allocation and will use SSE if IPP is available. |
| // int w = im.Width(); |
| // im.View(0,0, w,1).CopyFrom(im.View(0,1, w,1)); |
| // |
| // // Doesn't care about source of data since using WImage |
| // void MySetRand(WImage_b* im) { // Works with any number of channels |
| // for (int r = 0; r < im->Height(); ++r) { |
| // float* row = im->Row(r); |
| // for (int c = 0; c < im->Width(); ++c) { |
| // for (int ch = 0; ch < im->Channels(); ++ch, ++row) { |
| // *row = uchar(rand() & 255); |
| // } |
| // } |
| // } |
| // } |
| // |
| // Functions that are not part of the basic image allocation, viewing, and |
| // access should come from OpenCV, except some useful functions that are not |
| // part of OpenCV can be found in wimage_util.h |
| #ifndef _CV_WIMAGE_H_ |
| #define _CV_WIMAGE_H_ |
| |
| #include "cxcore.h" |
| |
| #ifdef __cplusplus |
| |
| namespace cv { |
| |
| template <typename T> class WImage; |
| template <typename T> class WImageBuffer; |
| template <typename T> class WImageView; |
| |
| template<typename T, int C> class WImageC; |
| template<typename T, int C> class WImageBufferC; |
| template<typename T, int C> class WImageViewC; |
| |
| // Commonly used typedefs. |
| typedef WImage<uchar> WImage_b; |
| typedef WImageView<uchar> WImageView_b; |
| typedef WImageBuffer<uchar> WImageBuffer_b; |
| |
| typedef WImageC<uchar, 1> WImage1_b; |
| typedef WImageViewC<uchar, 1> WImageView1_b; |
| typedef WImageBufferC<uchar, 1> WImageBuffer1_b; |
| |
| typedef WImageC<uchar, 3> WImage3_b; |
| typedef WImageViewC<uchar, 3> WImageView3_b; |
| typedef WImageBufferC<uchar, 3> WImageBuffer3_b; |
| |
| typedef WImage<float> WImage_f; |
| typedef WImageView<float> WImageView_f; |
| typedef WImageBuffer<float> WImageBuffer_f; |
| |
| typedef WImageC<float, 1> WImage1_f; |
| typedef WImageViewC<float, 1> WImageView1_f; |
| typedef WImageBufferC<float, 1> WImageBuffer1_f; |
| |
| typedef WImageC<float, 3> WImage3_f; |
| typedef WImageViewC<float, 3> WImageView3_f; |
| typedef WImageBufferC<float, 3> WImageBuffer3_f; |
| |
| // There isn't a standard for signed and unsigned short so be more |
| // explicit in the typename for these cases. |
| typedef WImage<short> WImage_16s; |
| typedef WImageView<short> WImageView_16s; |
| typedef WImageBuffer<short> WImageBuffer_16s; |
| |
| typedef WImageC<short, 1> WImage1_16s; |
| typedef WImageViewC<short, 1> WImageView1_16s; |
| typedef WImageBufferC<short, 1> WImageBuffer1_16s; |
| |
| typedef WImageC<short, 3> WImage3_16s; |
| typedef WImageViewC<short, 3> WImageView3_16s; |
| typedef WImageBufferC<short, 3> WImageBuffer3_16s; |
| |
| typedef WImage<ushort> WImage_16u; |
| typedef WImageView<ushort> WImageView_16u; |
| typedef WImageBuffer<ushort> WImageBuffer_16u; |
| |
| typedef WImageC<ushort, 1> WImage1_16u; |
| typedef WImageViewC<ushort, 1> WImageView1_16u; |
| typedef WImageBufferC<ushort, 1> WImageBuffer1_16u; |
| |
| typedef WImageC<ushort, 3> WImage3_16u; |
| typedef WImageViewC<ushort, 3> WImageView3_16u; |
| typedef WImageBufferC<ushort, 3> WImageBuffer3_16u; |
| |
| // |
| // WImage definitions |
| // |
| // This WImage class gives access to the data it refers to. It can be |
| // constructed either by allocating the data with a WImageBuffer class or |
| // using the WImageView class to refer to a subimage or outside data. |
| template<typename T> |
| class WImage |
| { |
| public: |
| typedef T BaseType; |
| |
| // WImage is an abstract class with no other virtual methods so make the |
| // destructor virtual. |
| virtual ~WImage() = 0; |
| |
| // Accessors |
| IplImage* Ipl() {return image_; } |
| const IplImage* Ipl() const {return image_; } |
| T* ImageData() { return reinterpret_cast<T*>(image_->imageData); } |
| const T* ImageData() const { |
| return reinterpret_cast<const T*>(image_->imageData); |
| } |
| |
| int Width() const {return image_->width; } |
| int Height() const {return image_->height; } |
| |
| // WidthStep is the number of bytes to go to the pixel with the next y coord |
| int WidthStep() const {return image_->widthStep; } |
| |
| int Channels() const {return image_->nChannels; } |
| int ChannelSize() const {return sizeof(T); } // number of bytes per channel |
| |
| // Number of bytes per pixel |
| int PixelSize() const {return Channels() * ChannelSize(); } |
| |
| // Return depth type (e.g. IPL_DEPTH_8U, IPL_DEPTH_32F) which is the number |
| // of bits per channel and with the signed bit set. |
| // This is known at compile time using specializations. |
| int Depth() const; |
| |
| inline const T* Row(int r) const { |
| return reinterpret_cast<T*>(image_->imageData + r*image_->widthStep); |
| } |
| |
| inline T* Row(int r) { |
| return reinterpret_cast<T*>(image_->imageData + r*image_->widthStep); |
| } |
| |
| // Pixel accessors which returns a pointer to the start of the channel |
| inline T* operator() (int c, int r) { |
| return reinterpret_cast<T*>(image_->imageData + r*image_->widthStep) + |
| c*Channels(); |
| } |
| |
| inline const T* operator() (int c, int r) const { |
| return reinterpret_cast<T*>(image_->imageData + r*image_->widthStep) + |
| c*Channels(); |
| } |
| |
| // Copy the contents from another image which is just a convenience to cvCopy |
| void CopyFrom(const WImage<T>& src) { cvCopy(src.Ipl(), image_); } |
| |
| // Set contents to zero which is just a convenient to cvSetZero |
| void SetZero() { cvSetZero(image_); } |
| |
| // Construct a view into a region of this image |
| WImageView<T> View(int c, int r, int width, int height); |
| |
| protected: |
| // Disallow copy and assignment |
| WImage(const WImage&); |
| void operator=(const WImage&); |
| |
| explicit WImage(IplImage* img) : image_(img) { |
| assert(!img || img->depth == Depth()); |
| } |
| |
| void SetIpl(IplImage* image) { |
| assert(!image || image->depth == Depth()); |
| image_ = image; |
| } |
| |
| IplImage* image_; |
| }; |
| |
| |
| |
| // Image class when both the pixel type and number of channels |
| // are known at compile time. This wrapper will speed up some of the operations |
| // like accessing individual pixels using the () operator. |
| template<typename T, int C> |
| class WImageC : public WImage<T> |
| { |
| public: |
| typedef typename WImage<T>::BaseType BaseType; |
| enum { kChannels = C }; |
| |
| explicit WImageC(IplImage* img) : WImage<T>(img) { |
| assert(!img || img->nChannels == Channels()); |
| } |
| |
| // Construct a view into a region of this image |
| WImageViewC<T, C> View(int c, int r, int width, int height); |
| |
| // Copy the contents from another image which is just a convenience to cvCopy |
| void CopyFrom(const WImageC<T, C>& src) { |
| cvCopy(src.Ipl(), WImage<T>::image_); |
| } |
| |
| // WImageC is an abstract class with no other virtual methods so make the |
| // destructor virtual. |
| virtual ~WImageC() = 0; |
| |
| int Channels() const {return C; } |
| |
| protected: |
| // Disallow copy and assignment |
| WImageC(const WImageC&); |
| void operator=(const WImageC&); |
| |
| void SetIpl(IplImage* image) { |
| assert(!image || image->depth == WImage<T>::Depth()); |
| WImage<T>::SetIpl(image); |
| } |
| }; |
| |
| // |
| // WImageBuffer definitions |
| // |
| // Image class which owns the data, so it can be allocated and is always |
| // freed. It cannot be copied but can be explicity cloned. |
| // |
| template<typename T> |
| class WImageBuffer : public WImage<T> |
| { |
| public: |
| typedef typename WImage<T>::BaseType BaseType; |
| |
| // Default constructor which creates an object that can be |
| WImageBuffer() : WImage<T>(0) {} |
| |
| WImageBuffer(int width, int height, int nchannels) : WImage<T>(0) { |
| Allocate(width, height, nchannels); |
| } |
| |
| // Constructor which takes ownership of a given IplImage so releases |
| // the image on destruction. |
| explicit WImageBuffer(IplImage* img) : WImage<T>(img) {} |
| |
| // Allocate an image. Does nothing if current size is the same as |
| // the new size. |
| void Allocate(int width, int height, int nchannels); |
| |
| // Set the data to point to an image, releasing the old data |
| void SetIpl(IplImage* img) { |
| ReleaseImage(); |
| WImage<T>::SetIpl(img); |
| } |
| |
| // Clone an image which reallocates the image if of a different dimension. |
| void CloneFrom(const WImage<T>& src) { |
| Allocate(src.Width(), src.Height()); |
| CopyFrom(src); |
| } |
| |
| ~WImageBuffer() { |
| ReleaseImage(); |
| } |
| |
| // Release the image if it isn't null. |
| void ReleaseImage() { |
| if (WImage<T>::image_) { |
| IplImage* image = WImage<T>::image_; |
| cvReleaseImage(&image); |
| WImage<T>::SetIpl(0); |
| } |
| } |
| |
| bool IsNull() const {return WImage<T>::image_ == NULL; } |
| |
| private: |
| // Disallow copy and assignment |
| WImageBuffer(const WImageBuffer&); |
| void operator=(const WImageBuffer&); |
| }; |
| |
| // Like a WImageBuffer class but when the number of channels is known |
| // at compile time. |
| template<typename T, int C> |
| class WImageBufferC : public WImageC<T, C> |
| { |
| public: |
| typedef typename WImage<T>::BaseType BaseType; |
| enum { kChannels = C }; |
| |
| // Default constructor which creates an object that can be |
| WImageBufferC() : WImageC<T, C>(0) {} |
| |
| WImageBufferC(int width, int height) : WImageC<T, C>(0) { |
| Allocate(width, height); |
| } |
| |
| // Constructor which takes ownership of a given IplImage so releases |
| // the image on destruction. |
| explicit WImageBufferC(IplImage* img) : WImageC<T, C>(img) {} |
| |
| // Allocate an image. Does nothing if current size is the same as |
| // the new size. |
| void Allocate(int width, int height); |
| |
| // Set the data to point to an image, releasing the old data |
| void SetIpl(IplImage* img) { |
| ReleaseImage(); |
| WImageC<T, C>::SetIpl(img); |
| } |
| |
| // Clone an image which reallocates the image if of a different dimension. |
| void CloneFrom(const WImageC<T, C>& src) { |
| Allocate(src.Width(), src.Height()); |
| CopyFrom(src); |
| } |
| |
| ~WImageBufferC() { |
| ReleaseImage(); |
| } |
| |
| // Release the image if it isn't null. |
| void ReleaseImage() { |
| if (WImage<T>::image_) { |
| IplImage* image = WImage<T>::image_; |
| cvReleaseImage(&image); |
| WImageC<T, C>::SetIpl(0); |
| } |
| } |
| |
| bool IsNull() const {return WImage<T>::image_ == NULL; } |
| |
| private: |
| // Disallow copy and assignment |
| WImageBufferC(const WImageBufferC&); |
| void operator=(const WImageBufferC&); |
| }; |
| |
| // |
| // WImageView definitions |
| // |
| // View into an image class which allows treating a subimage as an image |
| // or treating external data as an image |
| // |
| template<typename T> |
| class WImageView : public WImage<T> |
| { |
| public: |
| typedef typename WImage<T>::BaseType BaseType; |
| |
| // Construct a subimage. No checks are done that the subimage lies |
| // completely inside the original image. |
| WImageView(WImage<T>* img, int c, int r, int width, int height); |
| |
| // Refer to external data. |
| // If not given width_step assumed to be same as width. |
| WImageView(T* data, int width, int height, int channels, int width_step = -1); |
| |
| // Refer to external data. This does NOT take ownership |
| // of the supplied IplImage. |
| WImageView(IplImage* img) : WImage<T>(img) {} |
| |
| // Copy constructor |
| WImageView(const WImage<T>& img) : WImage<T>(0) { |
| header_ = *(img.Ipl()); |
| WImage<T>::SetIpl(&header_); |
| } |
| |
| WImageView& operator=(const WImage<T>& img) { |
| header_ = *(img.Ipl()); |
| WImage<T>::SetIpl(&header_); |
| return *this; |
| } |
| |
| protected: |
| IplImage header_; |
| }; |
| |
| |
| template<typename T, int C> |
| class WImageViewC : public WImageC<T, C> |
| { |
| public: |
| typedef typename WImage<T>::BaseType BaseType; |
| enum { kChannels = C }; |
| |
| // Default constructor needed for vectors of views. |
| WImageViewC(); |
| |
| virtual ~WImageViewC() {} |
| |
| // Construct a subimage. No checks are done that the subimage lies |
| // completely inside the original image. |
| WImageViewC(WImageC<T, C>* img, |
| int c, int r, int width, int height); |
| |
| // Refer to external data |
| WImageViewC(T* data, int width, int height, int width_step = -1); |
| |
| // Refer to external data. This does NOT take ownership |
| // of the supplied IplImage. |
| WImageViewC(IplImage* img) : WImageC<T, C>(img) {} |
| |
| // Copy constructor which does a shallow copy to allow multiple views |
| // of same data. gcc-4.1.1 gets confused if both versions of |
| // the constructor and assignment operator are not provided. |
| WImageViewC(const WImageC<T, C>& img) : WImageC<T, C>(0) { |
| header_ = *(img.Ipl()); |
| WImageC<T, C>::SetIpl(&header_); |
| } |
| WImageViewC(const WImageViewC<T, C>& img) : WImageC<T, C>(0) { |
| header_ = *(img.Ipl()); |
| WImageC<T, C>::SetIpl(&header_); |
| } |
| |
| WImageViewC& operator=(const WImageC<T, C>& img) { |
| header_ = *(img.Ipl()); |
| WImageC<T, C>::SetIpl(&header_); |
| return *this; |
| } |
| WImageViewC& operator=(const WImageViewC<T, C>& img) { |
| header_ = *(img.Ipl()); |
| WImageC<T, C>::SetIpl(&header_); |
| return *this; |
| } |
| |
| protected: |
| IplImage header_; |
| }; |
| |
| |
| // Specializations for depth |
| template<> |
| inline int WImage<uchar>::Depth() const {return IPL_DEPTH_8U; } |
| template<> |
| inline int WImage<schar>::Depth() const {return IPL_DEPTH_8S; } |
| template<> |
| inline int WImage<short>::Depth() const {return IPL_DEPTH_16S; } |
| template<> |
| inline int WImage<ushort>::Depth() const {return IPL_DEPTH_16U; } |
| template<> |
| inline int WImage<int>::Depth() const {return IPL_DEPTH_32S; } |
| template<> |
| inline int WImage<float>::Depth() const {return IPL_DEPTH_32F; } |
| template<> |
| inline int WImage<double>::Depth() const {return IPL_DEPTH_64F; } |
| |
| // |
| // Pure virtual destructors still need to be defined. |
| // |
| template<typename T> inline WImage<T>::~WImage() {} |
| template<typename T, int C> inline WImageC<T, C>::~WImageC() {} |
| |
| // |
| // Allocate ImageData |
| // |
| template<typename T> |
| inline void WImageBuffer<T>::Allocate(int width, int height, int nchannels) |
| { |
| if (IsNull() || WImage<T>::Width() != width || |
| WImage<T>::Height() != height || WImage<T>::Channels() != nchannels) { |
| ReleaseImage(); |
| WImage<T>::image_ = cvCreateImage(cvSize(width, height), |
| WImage<T>::Depth(), nchannels); |
| } |
| } |
| |
| template<typename T, int C> |
| inline void WImageBufferC<T, C>::Allocate(int width, int height) |
| { |
| if (IsNull() || WImage<T>::Width() != width || WImage<T>::Height() != height) { |
| ReleaseImage(); |
| WImageC<T, C>::SetIpl(cvCreateImage(cvSize(width, height),WImage<T>::Depth(), C)); |
| } |
| } |
| |
| // |
| // ImageView methods |
| // |
| template<typename T> |
| WImageView<T>::WImageView(WImage<T>* img, int c, int r, int width, int height) |
| : WImage<T>(0) |
| { |
| header_ = *(img->Ipl()); |
| header_.imageData = reinterpret_cast<char*>((*img)(c, r)); |
| header_.width = width; |
| header_.height = height; |
| WImage<T>::SetIpl(&header_); |
| } |
| |
| template<typename T> |
| WImageView<T>::WImageView(T* data, int width, int height, int nchannels, int width_step) |
| : WImage<T>(0) |
| { |
| cvInitImageHeader(&header_, cvSize(width, height), WImage<T>::Depth(), nchannels); |
| header_.imageData = reinterpret_cast<char*>(data); |
| if (width_step > 0) { |
| header_.widthStep = width_step; |
| } |
| WImage<T>::SetIpl(&header_); |
| } |
| |
| template<typename T, int C> |
| WImageViewC<T, C>::WImageViewC(WImageC<T, C>* img, int c, int r, int width, int height) |
| : WImageC<T, C>(0) |
| { |
| header_ = *(img->Ipl()); |
| header_.imageData = reinterpret_cast<char*>((*img)(c, r)); |
| header_.width = width; |
| header_.height = height; |
| WImageC<T, C>::SetIpl(&header_); |
| } |
| |
| template<typename T, int C> |
| WImageViewC<T, C>::WImageViewC() : WImageC<T, C>(0) { |
| cvInitImageHeader(&header_, cvSize(0, 0), WImage<T>::Depth(), C); |
| header_.imageData = reinterpret_cast<char*>(0); |
| WImageC<T, C>::SetIpl(&header_); |
| } |
| |
| template<typename T, int C> |
| WImageViewC<T, C>::WImageViewC(T* data, int width, int height, int width_step) |
| : WImageC<T, C>(0) |
| { |
| cvInitImageHeader(&header_, cvSize(width, height), WImage<T>::Depth(), C); |
| header_.imageData = reinterpret_cast<char*>(data); |
| if (width_step > 0) { |
| header_.widthStep = width_step; |
| } |
| WImageC<T, C>::SetIpl(&header_); |
| } |
| |
| // Construct a view into a region of an image |
| template<typename T> |
| WImageView<T> WImage<T>::View(int c, int r, int width, int height) { |
| return WImageView<T>(this, c, r, width, height); |
| } |
| |
| template<typename T, int C> |
| WImageViewC<T, C> WImageC<T, C>::View(int c, int r, int width, int height) { |
| return WImageViewC<T, C>(this, c, r, width, height); |
| } |
| |
| } // end of namespace |
| |
| #endif // __cplusplus |
| |
| #endif // _CV_WIMAGE_H_ |