/* # # File : cvMat.h # ( C++ header file - CImg plug-in ) # # Description : CImg plug-in providing the CImg->cvMat and cvMat->CImg # conversions for generic image types # ( IPL = Intel Performance Library ) # This file is a part of the CImg Library project. # ( http://cimg.sourceforge.net ) # # Copyright : Alberto Albiol # alalbiol@iteam.upv.es # # How to use : In the main program include: # #include "cv.h" # #include "highgui.h" # #define cimg_plugin1 "cvMat.h" # #include "CImg.h" */ #ifndef cimg_plugin_cvMat #define cimg_plugin_cvMat // Conversion IPL -> CImg (constructor) CImg(const cv::Mat& src):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { assign(src); } // Conversion IPL -> CImg (in-place constructor) CImg& assign(const cv::Mat & src) { if (src.isContinuous()) { switch (src.depth()) { // case CV_1U: { // 1-bit int. // IplImage *src1 = cvCreateImage(cvGetSize(src),CV_8U,1); // cvConvert(src,src1); // CImg((unsigned char*)src1->imageData,src1->nChannels,src1.cols,src1.rows,1,true). // get_permute_axes("yzcx").move_to(*this); // cvReleaseImage(&src1); // } break; case CV_8U: // 8-bit unsigned int. if (src.channels()==1) { CImg((unsigned char*)src.ptr(),src.cols,src.rows,true).move_to(*this); } else { std::vector channels; cv::split(src,channels); CImg tmp(src.cols,src.rows,1,3), R = tmp.get_shared_channel(2), G = tmp.get_shared_channel(1), B = tmp.get_shared_channel(0); std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(uchar)); std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(uchar)); std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(uchar)); tmp.move_to(*this); } break; case CV_8S: // 8-bit signed int. if (src.channels()==1) { CImg((char*)src.ptr(),src.cols,src.rows,true).move_to(*this); } else { std::vector channels; cv::split(src,channels); CImg tmp(src.cols,src.rows,1,3), R = tmp.get_shared_channel(2), G = tmp.get_shared_channel(1), B = tmp.get_shared_channel(0); std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(char)); std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(char)); std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(char)); tmp.move_to(*this); } break; case CV_16U: // 16-bit unsigned int. if (src.channels()==1) { CImg((unsigned short*)src.ptr(),src.cols,src.rows,true).move_to(*this); } else { std::vector channels; cv::split(src,channels); CImg tmp(src.cols,src.rows,1,3), R = tmp.get_shared_channel(2), G = tmp.get_shared_channel(1), B = tmp.get_shared_channel(0); std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(unsigned short)); std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(unsigned short)); std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(unsigned short)); tmp.move_to(*this); } break; case CV_16S: // 16-bit signed int. if (src.channels()==1) { CImg((short*)src.ptr(),src.cols,src.rows,true).move_to(*this); } else { std::vector channels; cv::split(src,channels); CImg tmp(src.cols,src.rows,1,3), R = tmp.get_shared_channel(2), G = tmp.get_shared_channel(1), B = tmp.get_shared_channel(0); std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(short)); std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(short)); std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(short)); tmp.move_to(*this); } break; case CV_32S: // 32-bit signed int. if (src.channels()==1) { CImg((int*)src.ptr(),src.cols,src.rows,true).move_to(*this); } else { std::vector channels; cv::split(src,channels); CImg tmp(src.cols,src.rows,1,3), R = tmp.get_shared_channel(2), G = tmp.get_shared_channel(1), B = tmp.get_shared_channel(0); std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(int)); std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(int)); std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(int)); tmp.move_to(*this); } break; case CV_32F: // 32-bit float. if (src.channels()==1) { CImg((float*)src.ptr(),src.cols,src.rows,true).move_to(*this); } else { std::vector channels; cv::split(src,channels); CImg tmp(src.cols,src.rows,1,3), R = tmp.get_shared_channel(2), G = tmp.get_shared_channel(1), B = tmp.get_shared_channel(0); std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(float)); std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(float)); std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(float)); tmp.move_to(*this); } break; case CV_64F: // 64-bit double. if (src.channels()==1) { CImg((double*)src.ptr(),src.cols,src.rows,true).move_to(*this); } else { std::vector channels; cv::split(src,channels); CImg tmp(src.cols,src.rows,1,3), R = tmp.get_shared_channel(2), G = tmp.get_shared_channel(1), B = tmp.get_shared_channel(0); std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(double)); std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(double)); std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(double)); tmp.move_to(*this); } break; default: throw CImgInstanceException(_cimg_instance "assign(const cv::Mat&) : Mat depth is invalid.", cimg_instance); break; } } else { cv::Size size = src.size(); switch (src.depth()) { case CV_8U: // 8-bit unsigned int. if (src.channels()==1) { CImg tmp(src.cols,src.rows); for (int i = 0; i(i); unsigned char *row_o = tmp.data(0,i); std::memcpy(row_o,row_i,size.width*sizeof(unsigned char)); } tmp.move_to(*this); } else { CImg tmp(src.cols,src.rows,1,src.channels()); std::vector channels; cv::split(src,channels); for (int c = 0; c plane = tmp.get_shared_channel(src.channels()-1-c); for (int i = 0; i(i); unsigned char *row_o = plane.data(0,i); std::memcpy(row_o,row_i,size.width*sizeof(unsigned char)); } } tmp.move_to(*this); } break; case CV_8S: // 8-bit int. if (src.channels()==1) { CImg tmp(src.cols,src.rows); for (int i = 0; i(i); char* row_o = tmp.data(0,i); std::memcpy(row_o,row_i,size.width*sizeof(charT)); } tmp.move_to(*this); } else { CImg tmp(src.cols,src.rows,1,src.channels()); std::vector channels; cv::split(src,channels); for (int c = 0; c plane = tmp.get_shared_channel(src.channels()-1-c); for (int i = 0; i(i); char *row_o = plane.data(0,i); std::memcpy(row_o,row_i,size.width*sizeof(char)); } } tmp.move_to(*this); } break; case CV_16S: // 16-bit int. if (src.channels()==1) { CImg tmp(src.cols,src.rows); for (int i = 0; i(i); short *row_o = tmp.data(0,i); std::memcpy(row_o,row_i,size.width*sizeof(short)); } tmp.move_to(*this); } else { CImg tmp(src.cols,src.rows,1,src.channels()); std::vector channels; cv::split(src,channels); for (int c = 0; c plane = tmp.get_shared_channel(src.channels()-1-c); for (int i = 0; i(i); short *row_o = plane.data(0,i); std::memcpy(row_o,row_i,size.width*sizeof(short)); } } tmp.move_to(*this); } break; case CV_32F: // 32-bit float.float if (src.channels()==1) { CImg tmp(src.cols,src.rows); for (int i = 0; i(i); float *row_o = tmp.data(0,i); std::memcpy(row_o,row_i,size.width*sizeof(float)); } tmp.move_to(*this); } else { CImg tmp(src.cols,src.rows,1,src.channels()); std::vector channels; cv::split(src,channels); for (int c = 0; c plane = tmp.get_shared_channel(src.channels()-1-c); for (int i = 0; i(i); float *row_o = plane.data(0,i); std::memcpy(row_o,row_i,size.width*sizeof(float)); } } tmp.move_to(*this); } break; case CV_64F: // 64-bit double. if (src.channels()==1) { CImg tmp(src.cols,src.rows); for (int i = 0; i(i); double *row_o = tmp.data(0,i); std::memcpy(row_o,row_i,size.width*sizeof(double)); } tmp.move_to(*this); } else { CImg tmp(src.cols,src.rows,1,src.channels()); std::vector channels; cv::split(src,channels); for (int c = 0; c plane = tmp.get_shared_channel(src.channels()-1-c); for (int i = 0; i(i); double *row_o = plane.data(0,i); std::memcpy(row_o,row_i,size.width*sizeof(double)); } } tmp.move_to(*this); } break; default: throw CImgInstanceException(_cimg_instance "assign(const cv::Mat&) : Mat depth is invalid.", cimg_instance); break; } } // if (!std::strcmp(src->channelSeq,"BGR")) mirror('v'); // else if (!std::strcmp(src->channelSeq,"BGRA")) get_shared_channels(0,2).mirror('v'); return *this; } // Conversion CImg -> MAT cv::Mat get_MAT(const unsigned int z=0) const { if (is_empty()) throw CImgInstanceException(_cimg_instance "get_MAT() : instance image is empty.", cimg_instance); if (z>=_depth) throw CImgInstanceException(_cimg_instance "get_MAT() : specified slice %u is out of image bounds.", cimg_instance,z); const CImg _slice = _depth>1?get_slice(z):CImg(), &slice = _depth>1?_slice:*this; CImg buf(slice,true); int cols = buf.width(), rows = buf.height(), nchannels = buf.spectrum(), matType=-1; if (!cimg::strcasecmp(buf.pixel_type(),"unsigned char")) matType = CV_8UC1; if (!cimg::strcasecmp(buf.pixel_type(),"uint8")) matType = CV_8UC1; if (!cimg::strcasecmp(buf.pixel_type(),"char")) matType = CV_8SC1; if (!cimg::strcasecmp(buf.pixel_type(),"int8")) matType = CV_8SC1; if (!cimg::strcasecmp(buf.pixel_type(),"unsigned short")) matType = CV_16UC1; if (!cimg::strcasecmp(buf.pixel_type(),"uint16")) matType = CV_16UC1; if (!cimg::strcasecmp(buf.pixel_type(),"short")) matType = CV_16SC1; if (!cimg::strcasecmp(buf.pixel_type(),"int16")) matType = CV_16SC1; if (!cimg::strcasecmp(buf.pixel_type(),"int")) matType = CV_32SC1; if (!cimg::strcasecmp(buf.pixel_type(),"int32")) matType = CV_32SC1; if (!cimg::strcasecmp(buf.pixel_type(),"float")) matType = CV_32FC1; if (!cimg::strcasecmp(buf.pixel_type(),"float32")) matType = CV_32FC1; if (!cimg::strcasecmp(buf.pixel_type(),"double")) matType = CV_64FC1; if (!cimg::strcasecmp(buf.pixel_type(),"float64")) matType = CV_64FC1; if (matType<0) throw CImgInstanceException(_cimg_instance "get_MAT() : pixel type '%s' is not supported.", cimg_instance,buf.pixel_type()); cv::Mat out; std::vector channels(nchannels); if (nchannels>1) { for (int c = 0; c(buf.data()+rows*cols*(nchannels-1-c))); } // for channels cv::merge(channels,out); } else out = cv::Mat(rows,cols,matType,const_cast(buf.data())).clone(); return out; } #endif /* cimg_plugin_cvMat */