00001 #pragma once 00002 00003 #include "opencv2/opencv.hpp" 00004 00005 #include "cinder/Cinder.h" 00006 #include "cinder/ImageIo.h" 00007 00008 namespace cinder { 00009 00010 class ImageTargetCvMat : public ImageTarget { 00011 public: 00012 static std::shared_ptr<ImageTargetCvMat> createRef( cv::Mat *mat ) { return std::shared_ptr<ImageTargetCvMat>( new ImageTargetCvMat( mat ) ); } 00013 00014 virtual bool hasAlpha() const { return mMat->channels() == 4; } 00015 virtual void* getRowPointer( int32_t row ) { return reinterpret_cast<void*>( reinterpret_cast<uint8_t*>(mMat->data) + row * mMat->step ); } 00016 00017 protected: 00018 ImageTargetCvMat( cv::Mat *mat ); 00019 00020 cv::Mat *mMat; 00021 }; 00022 00023 class ImageSourceCvMat : public ImageSource { 00024 public: 00025 ImageSourceCvMat( const cv::Mat &mat ) 00026 : ImageSource() 00027 { 00028 mWidth = mat.cols; 00029 mHeight = mat.rows; 00030 if( (mat.channels() == 3) || (mat.channels() == 4) ) { 00031 setColorModel( ImageIo::CM_RGB ); 00032 if( mat.channels() == 4 ) 00033 setChannelOrder( ImageIo::BGRA ); 00034 else 00035 setChannelOrder( ImageIo::BGR ); 00036 } 00037 else if( mat.channels() == 1 ) { 00038 setColorModel( ImageIo::CM_GRAY ); 00039 setChannelOrder( ImageIo::Y ); 00040 } 00041 00042 switch( mat.depth() ) { 00043 case CV_8U: setDataType( ImageIo::UINT8 ); break; 00044 case CV_16U: setDataType( ImageIo::UINT16 ); break; 00045 case CV_32F: setDataType( ImageIo::FLOAT32 ); break; 00046 default: 00047 throw ImageIoExceptionIllegalDataType(); 00048 } 00049 00050 mRowBytes = mat.step; 00051 mData = reinterpret_cast<const uint8_t*>( mat.data ); 00052 } 00053 00054 void load( ImageTargetRef target ) { 00055 // get a pointer to the ImageSource function appropriate for handling our data configuration 00056 ImageSource::RowFunc func = setupRowFunc( target ); 00057 00058 const uint8_t *data = mData; 00059 for( int32_t row = 0; row < mHeight; ++row ) { 00060 ((*this).*func)( target, row, data ); 00061 data += mRowBytes; 00062 } 00063 } 00064 00065 const uint8_t *mData; 00066 int32_t mRowBytes; 00067 }; 00068 00070 // ImageTargetCvMat 00071 inline ImageTargetCvMat::ImageTargetCvMat( cv::Mat *mat ) 00072 : ImageTarget(), mMat( mat ) 00073 { 00074 switch( mat->depth() ) { 00075 case CV_8U: setDataType( ImageIo::UINT8 ); break; 00076 case CV_16U: setDataType( ImageIo::UINT16 ); break; 00077 case CV_32F: setDataType( ImageIo::FLOAT32 ); break; 00078 default: 00079 throw ImageIoExceptionIllegalDataType(); 00080 } 00081 00082 switch( mat->channels() ) { 00083 case 1: 00084 setColorModel( ImageIo::CM_GRAY ); 00085 setChannelOrder( ImageIo::Y ); 00086 break; 00087 case 3: 00088 setColorModel( ImageIo::CM_RGB ); 00089 setChannelOrder( ImageIo::BGR ); 00090 break; 00091 case 4: 00092 setColorModel( ImageIo::CM_RGB ); 00093 setChannelOrder( ImageIo::BGRA ); 00094 break; 00095 default: 00096 throw ImageIoExceptionIllegalColorModel(); 00097 break; 00098 } 00099 } 00100 00101 inline cv::Mat toOcv( ci::ImageSourceRef sourceRef, int type = -1 ) 00102 { 00103 if( type == -1 ) { 00104 int depth = CV_8U; 00105 if( sourceRef->getDataType() == ImageIo::UINT16 ) 00106 depth = CV_16U; 00107 else if( sourceRef->getDataType() == ImageIo::FLOAT32 ) 00108 depth = CV_32F; 00109 int channels = ImageIo::channelOrderNumChannels( sourceRef->getChannelOrder() ); 00110 type = CV_MAKETYPE( depth, channels ); 00111 } 00112 00113 cv::Mat result( sourceRef->getHeight(), sourceRef->getWidth(), type ); 00114 ImageTargetRef target = ImageTargetCvMat::createRef( &result ); 00115 sourceRef->load( target ); 00116 return result; 00117 } 00118 00119 inline cv::Mat toOcvRef( Channel8u &channel ) 00120 { 00121 return cv::Mat( channel.getHeight(), channel.getWidth(), CV_MAKETYPE( CV_8U, 1 ), channel.getData(), channel.getRowBytes() ); 00122 } 00123 00124 inline cv::Mat toOcvRef( Channel32f &channel ) 00125 { 00126 return cv::Mat( channel.getHeight(), channel.getWidth(), CV_MAKETYPE( CV_32F, 1 ), channel.getData(), channel.getRowBytes() ); 00127 } 00128 00129 inline cv::Mat toOcvRef( Surface8u &surface ) 00130 { 00131 return cv::Mat( surface.getHeight(), surface.getWidth(), CV_MAKETYPE( CV_8U, surface.hasAlpha()?4:3), surface.getData(), surface.getRowBytes() ); 00132 } 00133 00134 inline cv::Mat toOcvRef( Surface32f &surface ) 00135 { 00136 return cv::Mat( surface.getHeight(), surface.getWidth(), CV_MAKETYPE( CV_32F, surface.hasAlpha()?4:3), surface.getData(), surface.getRowBytes() ); 00137 } 00138 00139 inline ImageSourceRef fromOcv( cv::Mat &mat ) 00140 { 00141 return ImageSourceRef( new ImageSourceCvMat( mat ) ); 00142 } 00143 00144 inline cv::Scalar toOcv( const Color &color ) 00145 { 00146 return CV_RGB( color.r * 255, color.g * 255, color.b * 255 ); 00147 } 00148 00149 inline Vec2f fromOcv( const cv::Point2f &point ) 00150 { 00151 return Vec2f( point.x, point.y ); 00152 } 00153 00154 inline cv::Point2f toOcv( const Vec2f &point ) 00155 { 00156 return cv::Point2f( point.x, point.y ); 00157 } 00158 00159 inline Vec2i fromOcv( const cv::Point &point ) 00160 { 00161 return Vec2i( point.x, point.y ); 00162 } 00163 00164 inline cv::Point toOcv( const Vec2i &point ) 00165 { 00166 return cv::Point( point.x, point.y ); 00167 } 00168 00169 inline cv::Rect toOcv( const ci::Area &r ) 00170 { 00171 return cv::Rect( r.x1, r.y1, r.getWidth(), r.getHeight() ); 00172 } 00173 00174 inline ci::Area fromOcv( const cv::Rect &r ) 00175 { 00176 return Area( r.x, r.y, r.x + r.width, r.y + r.height ); 00177 } 00178 00179 } // namespace cinder