ES-DE/external/CImg/plugins/cvMat.h

351 lines
14 KiB
C++

/*
#
# 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<T>& 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<ucharT>((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<ucharT>((unsigned char*)src.ptr(),src.cols,src.rows,true).move_to(*this);
} else {
std::vector<cv::Mat> channels;
cv::split(src,channels);
CImg<ucharT>
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<charT>((char*)src.ptr(),src.cols,src.rows,true).move_to(*this);
} else {
std::vector<cv::Mat> channels;
cv::split(src,channels);
CImg<ucharT>
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<ushortT>((unsigned short*)src.ptr(),src.cols,src.rows,true).move_to(*this);
} else {
std::vector<cv::Mat> channels;
cv::split(src,channels);
CImg<ushortT>
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<shortT>((short*)src.ptr(),src.cols,src.rows,true).move_to(*this);
} else {
std::vector<cv::Mat> channels;
cv::split(src,channels);
CImg<shortT>
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<intT>((int*)src.ptr(),src.cols,src.rows,true).move_to(*this);
} else {
std::vector<cv::Mat> channels;
cv::split(src,channels);
CImg<intT>
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<floatT>((float*)src.ptr(),src.cols,src.rows,true).move_to(*this);
} else {
std::vector<cv::Mat> channels;
cv::split(src,channels);
CImg<floatT>
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<doubleT>((double*)src.ptr(),src.cols,src.rows,true).move_to(*this);
} else {
std::vector<cv::Mat> channels;
cv::split(src,channels);
CImg<doubleT>
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<ucharT> tmp(src.cols,src.rows);
for (int i = 0; i<size.height; ++i) {
const unsigned char* row_i = src.ptr<unsigned char>(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<ucharT> tmp(src.cols,src.rows,1,src.channels());
std::vector<cv::Mat> channels;
cv::split(src,channels);
for (int c = 0; c<src.channels(); ++c) {
CImg<ucharT> plane = tmp.get_shared_channel(src.channels()-1-c);
for (int i = 0; i<size.height; ++i) {
const unsigned char* row_i = channels[c].ptr<unsigned char>(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<charT> tmp(src.cols,src.rows);
for (int i = 0; i<size.height; ++i) {
const char* row_i = src.ptr<char>(i);
char* row_o = tmp.data(0,i);
std::memcpy(row_o,row_i,size.width*sizeof(charT));
}
tmp.move_to(*this);
} else {
CImg<charT> tmp(src.cols,src.rows,1,src.channels());
std::vector<cv::Mat> channels;
cv::split(src,channels);
for (int c = 0; c<src.channels(); ++c) {
CImg<charT> plane = tmp.get_shared_channel(src.channels()-1-c);
for (int i = 0; i<size.height; ++i) {
const char* row_i = channels[c].ptr<char>(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<shortT> tmp(src.cols,src.rows);
for (int i = 0; i<size.height; ++i) {
const short* row_i = src.ptr<short>(i);
short *row_o = tmp.data(0,i);
std::memcpy(row_o,row_i,size.width*sizeof(short));
}
tmp.move_to(*this);
} else {
CImg<shortT> tmp(src.cols,src.rows,1,src.channels());
std::vector<cv::Mat> channels;
cv::split(src,channels);
for (int c = 0; c<src.channels(); ++c) {
CImg<shortT> plane = tmp.get_shared_channel(src.channels()-1-c);
for (int i = 0; i<size.height; ++i) {
const short* row_i = channels[c].ptr<short>(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<floatT> tmp(src.cols,src.rows);
for (int i = 0; i<size.height; ++i) {
const float* row_i = src.ptr<float>(i);
float *row_o = tmp.data(0,i);
std::memcpy(row_o,row_i,size.width*sizeof(float));
}
tmp.move_to(*this);
} else {
CImg<floatT> tmp(src.cols,src.rows,1,src.channels());
std::vector<cv::Mat> channels;
cv::split(src,channels);
for (int c = 0; c<src.channels(); ++c) {
CImg<floatT> plane = tmp.get_shared_channel(src.channels()-1-c);
for (int i = 0; i<size.height; ++i) {
const float* row_i = channels[c].ptr<float>(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<doubleT> tmp(src.cols,src.rows);
for (int i = 0; i<size.height; ++i) {
const double* row_i = src.ptr<double>(i);
double *row_o = tmp.data(0,i);
std::memcpy(row_o,row_i,size.width*sizeof(double));
}
tmp.move_to(*this);
} else {
CImg<doubleT> tmp(src.cols,src.rows,1,src.channels());
std::vector<cv::Mat> channels;
cv::split(src,channels);
for (int c = 0; c<src.channels(); ++c) {
CImg<doubleT> plane = tmp.get_shared_channel(src.channels()-1-c);
for (int i = 0; i<size.height; ++i) {
const double* row_i = channels[c].ptr<double>(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<T>
_slice = _depth>1?get_slice(z):CImg<T>(),
&slice = _depth>1?_slice:*this;
CImg<T> 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<cv::Mat> channels(nchannels);
if (nchannels>1) {
for (int c = 0; c<nchannels; ++c) {
channels[c] = cv::Mat(rows,cols,matType,const_cast<T*>(buf.data()+rows*cols*(nchannels-1-c)));
} // for channels
cv::merge(channels,out);
} else out = cv::Mat(rows,cols,matType,const_cast<T*>(buf.data())).clone();
return out;
}
#endif /* cimg_plugin_cvMat */