1 /*
2 #
3 # File : cvMat.h
4 # ( C++ header file - CImg plug-in )
5 #
6 # Description : CImg plug-in providing the CImg->cvMat and cvMat->CImg
7 # conversions for generic image types
8 # ( IPL = Intel Performance Library )
9 # This file is a part of the CImg Library project.
10 # ( http://cimg.eu )
11 #
12 # Copyright : Alberto Albiol
13 # alalbiol@iteam.upv.es
14 #
15 # How to use : In the main program include:
16 # OPENCV 2.4.x
17 # #include "cv.h"
18 # #include "highgui.h"
19 # #define cimg_plugin1 "cvMat.h"
20 # #include "CImg.h"
21 #
22 # OPENCV 3.x.x
23 # #include <opencv2/core.hpp>
24 # #define cimg_plugin1 "cvMat.h"
25 # #include "CImg.h"
26
27 */
28 #ifndef cimg_plugin_cvMat
29 #define cimg_plugin_cvMat
30
31 // Conversion IPL -> CImg (constructor)
CImg(const cv::Mat & src)32 CImg(const cv::Mat& src):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
33 assign(src);
34 }
35
36 // Conversion IPL -> CImg (in-place constructor)
assign(const cv::Mat & src)37 CImg<T>& assign(const cv::Mat & src) {
38 if (src.isContinuous()) {
39 switch (src.depth()) {
40 // case CV_1U: { // 1-bit int
41 // IplImage *src1 = cvCreateImage(cvGetSize(src),CV_8U,1);
42 // cvConvert(src,src1);
43 // CImg<ucharT>((unsigned char*)src1->imageData,src1->nChannels,src1.cols,src1.rows,1,true).
44 // get_permute_axes("yzcx").move_to(*this);
45 // cvReleaseImage(&src1);
46 // } break;
47 case CV_8U: // 8-bit unsigned int
48 if (src.channels()==1) {
49 CImg<ucharT>((unsigned char*)src.ptr(),src.cols,src.rows,true).move_to(*this);
50 } else {
51 std::vector<cv::Mat> channels;
52 cv::split(src,channels);
53 CImg<ucharT>
54 tmp(src.cols,src.rows,1,3),
55 R = tmp.get_shared_channel(2),
56 G = tmp.get_shared_channel(1),
57 B = tmp.get_shared_channel(0);
58 std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(uchar));
59 std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(uchar));
60 std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(uchar));
61 tmp.move_to(*this);
62 }
63 break;
64 case CV_8S: // 8-bit signed int
65 if (src.channels()==1) {
66 CImg<charT>((char*)src.ptr(),src.cols,src.rows,true).move_to(*this);
67 } else {
68 std::vector<cv::Mat> channels;
69 cv::split(src,channels);
70 CImg<ucharT>
71 tmp(src.cols,src.rows,1,3),
72 R = tmp.get_shared_channel(2),
73 G = tmp.get_shared_channel(1),
74 B = tmp.get_shared_channel(0);
75 std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(char));
76 std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(char));
77 std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(char));
78 tmp.move_to(*this);
79 }
80 break;
81 case CV_16U: // 16-bit unsigned int
82 if (src.channels()==1) {
83 CImg<ushortT>((unsigned short*)src.ptr(),src.cols,src.rows,true).move_to(*this);
84 } else {
85 std::vector<cv::Mat> channels;
86 cv::split(src,channels);
87 CImg<ushortT>
88 tmp(src.cols,src.rows,1,3),
89 R = tmp.get_shared_channel(2),
90 G = tmp.get_shared_channel(1),
91 B = tmp.get_shared_channel(0);
92 std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(unsigned short));
93 std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(unsigned short));
94 std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(unsigned short));
95 tmp.move_to(*this);
96 }
97 break;
98 case CV_16S: // 16-bit signed int
99 if (src.channels()==1) {
100 CImg<shortT>((short*)src.ptr(),src.cols,src.rows,true).move_to(*this);
101 } else {
102 std::vector<cv::Mat> channels;
103 cv::split(src,channels);
104 CImg<shortT>
105 tmp(src.cols,src.rows,1,3),
106 R = tmp.get_shared_channel(2),
107 G = tmp.get_shared_channel(1),
108 B = tmp.get_shared_channel(0);
109 std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(short));
110 std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(short));
111 std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(short));
112 tmp.move_to(*this);
113 }
114 break;
115 case CV_32S: // 32-bit signed int
116 if (src.channels()==1) {
117 CImg<intT>((int*)src.ptr(),src.cols,src.rows,true).move_to(*this);
118 } else {
119 std::vector<cv::Mat> channels;
120 cv::split(src,channels);
121 CImg<intT>
122 tmp(src.cols,src.rows,1,3),
123 R = tmp.get_shared_channel(2),
124 G = tmp.get_shared_channel(1),
125 B = tmp.get_shared_channel(0);
126 std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(int));
127 std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(int));
128 std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(int));
129 tmp.move_to(*this);
130 }
131 break;
132 case CV_32F: // 32-bit float
133 if (src.channels()==1) {
134 CImg<floatT>((float*)src.ptr(),src.cols,src.rows,true).move_to(*this);
135 } else {
136 std::vector<cv::Mat> channels;
137 cv::split(src,channels);
138 CImg<floatT>
139 tmp(src.cols,src.rows,1,3),
140 R = tmp.get_shared_channel(2),
141 G = tmp.get_shared_channel(1),
142 B = tmp.get_shared_channel(0);
143 std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(float));
144 std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(float));
145 std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(float));
146 tmp.move_to(*this);
147 }
148 break;
149 case CV_64F: // 64-bit double
150 if (src.channels()==1) {
151 CImg<doubleT>((double*)src.ptr(),src.cols,src.rows,true).move_to(*this);
152 } else {
153 std::vector<cv::Mat> channels;
154 cv::split(src,channels);
155 CImg<doubleT>
156 tmp(src.cols,src.rows,1,3),
157 R = tmp.get_shared_channel(2),
158 G = tmp.get_shared_channel(1),
159 B = tmp.get_shared_channel(0);
160 std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(double));
161 std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(double));
162 std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(double));
163 tmp.move_to(*this);
164 }
165 break;
166 default:
167 throw CImgInstanceException(_cimg_instance
168 "assign(const cv::Mat&) : Mat depth is invalid.",
169 cimg_instance);
170 break;
171 }
172 } else {
173 cv::Size size = src.size();
174 switch (src.depth()) {
175 case CV_8U: // 8-bit unsigned int
176 if (src.channels()==1) {
177 CImg<ucharT> tmp(src.cols,src.rows);
178 for (int i = 0; i<size.height; ++i) {
179 const unsigned char* row_i = src.ptr<unsigned char>(i);
180 unsigned char *row_o = tmp.data(0,i);
181 std::memcpy(row_o,row_i,size.width*sizeof(unsigned char));
182 }
183 tmp.move_to(*this);
184 } else {
185 CImg<ucharT> tmp(src.cols,src.rows,1,src.channels());
186 std::vector<cv::Mat> channels;
187 cv::split(src,channels);
188 for (int c = 0; c<src.channels(); ++c) {
189 CImg<ucharT> plane = tmp.get_shared_channel(src.channels() - 1 - c);
190 for (int i = 0; i<size.height; ++i) {
191 const unsigned char* row_i = channels[c].ptr<unsigned char>(i);
192 unsigned char *row_o = plane.data(0,i);
193 std::memcpy(row_o,row_i,size.width*sizeof(unsigned char));
194 }
195 }
196 tmp.move_to(*this);
197 }
198 break;
199 case CV_8S: // 8-bit int
200 if (src.channels()==1) {
201 CImg<charT> tmp(src.cols,src.rows);
202 for (int i = 0; i<size.height; ++i) {
203 const char* row_i = src.ptr<char>(i);
204 char* row_o = tmp.data(0,i);
205 std::memcpy(row_o,row_i,size.width*sizeof(charT));
206 }
207 tmp.move_to(*this);
208 } else {
209 CImg<charT> tmp(src.cols,src.rows,1,src.channels());
210 std::vector<cv::Mat> channels;
211 cv::split(src,channels);
212 for (int c = 0; c<src.channels(); ++c) {
213 CImg<charT> plane = tmp.get_shared_channel(src.channels() - 1 - c);
214 for (int i = 0; i<size.height; ++i) {
215 const char* row_i = channels[c].ptr<char>(i);
216 char *row_o = plane.data(0,i);
217 std::memcpy(row_o,row_i,size.width*sizeof(char));
218 }
219 }
220 tmp.move_to(*this);
221 }
222 break;
223 case CV_16S: // 16-bit int
224 if (src.channels()==1) {
225 CImg<shortT> tmp(src.cols,src.rows);
226 for (int i = 0; i<size.height; ++i) {
227 const short* row_i = src.ptr<short>(i);
228 short *row_o = tmp.data(0,i);
229 std::memcpy(row_o,row_i,size.width*sizeof(short));
230 }
231 tmp.move_to(*this);
232 } else {
233 CImg<shortT> tmp(src.cols,src.rows,1,src.channels());
234 std::vector<cv::Mat> channels;
235 cv::split(src,channels);
236 for (int c = 0; c<src.channels(); ++c) {
237 CImg<shortT> plane = tmp.get_shared_channel(src.channels() - 1 - c);
238 for (int i = 0; i<size.height; ++i) {
239 const short* row_i = channels[c].ptr<short>(i);
240 short *row_o = plane.data(0,i);
241 std::memcpy(row_o,row_i,size.width*sizeof(short));
242 }
243 }
244 tmp.move_to(*this);
245 }
246 break;
247 case CV_32F: // 32-bit float
248 if (src.channels()==1) {
249 CImg<floatT> tmp(src.cols,src.rows);
250 for (int i = 0; i<size.height; ++i) {
251 const float* row_i = src.ptr<float>(i);
252 float *row_o = tmp.data(0,i);
253 std::memcpy(row_o,row_i,size.width*sizeof(float));
254 }
255 tmp.move_to(*this);
256 } else {
257 CImg<floatT> tmp(src.cols,src.rows,1,src.channels());
258 std::vector<cv::Mat> channels;
259 cv::split(src,channels);
260 for (int c = 0; c<src.channels(); ++c) {
261 CImg<floatT> plane = tmp.get_shared_channel(src.channels() - 1 - c);
262 for (int i = 0; i<size.height; ++i) {
263 const float* row_i = channels[c].ptr<float>(i);
264 float *row_o = plane.data(0,i);
265 std::memcpy(row_o,row_i,size.width*sizeof(float));
266 }
267 }
268 tmp.move_to(*this);
269 }
270 break;
271 case CV_64F: // 64-bit double
272 if (src.channels()==1) {
273 CImg<doubleT> tmp(src.cols,src.rows);
274 for (int i = 0; i<size.height; ++i) {
275 const double* row_i = src.ptr<double>(i);
276 double *row_o = tmp.data(0,i);
277 std::memcpy(row_o,row_i,size.width*sizeof(double));
278 }
279 tmp.move_to(*this);
280 } else {
281 CImg<doubleT> tmp(src.cols,src.rows,1,src.channels());
282 std::vector<cv::Mat> channels;
283 cv::split(src,channels);
284 for (int c = 0; c<src.channels(); ++c) {
285 CImg<doubleT> plane = tmp.get_shared_channel(src.channels() - 1 - c);
286 for (int i = 0; i<size.height; ++i) {
287 const double* row_i = channels[c].ptr<double>(i);
288 double *row_o = plane.data(0,i);
289 std::memcpy(row_o,row_i,size.width*sizeof(double));
290 }
291 }
292 tmp.move_to(*this);
293 }
294 break;
295 default:
296 throw CImgInstanceException(_cimg_instance
297 "assign(const cv::Mat&) : Mat depth is invalid.",
298 cimg_instance);
299 break;
300 }
301 }
302
303 // if (!std::strcmp(src->channelSeq,"BGR")) mirror('v');
304 // else if (!std::strcmp(src->channelSeq,"BGRA")) get_shared_channels(0,2).mirror('v');
305 return *this;
306 }
307
308 // Conversion CImg -> MAT
309 cv::Mat get_MAT(const unsigned int z=0) const {
310 if (is_empty())
311 throw CImgInstanceException(_cimg_instance
312 "get_MAT() : instance image is empty.",
313 cimg_instance);
314 if (z>=_depth)
315 throw CImgInstanceException(_cimg_instance
316 "get_MAT() : specified slice %u is out of image bounds.",
317 cimg_instance,z);
318 const CImg<T>
319 _slice = _depth>1?get_slice(z):CImg<T>(),
320 &slice = _depth>1?_slice:*this;
321 CImg<T> buf(slice,true);
322 int
323 cols = buf.width(),
324 rows = buf.height(),
325 nchannels = buf.spectrum(),
326 matType=-1;
327
328 if (!cimg::strcasecmp(buf.pixel_type(),"unsigned char")) matType = CV_8UC1;
329 if (!cimg::strcasecmp(buf.pixel_type(),"char")) matType = CV_8SC1;
330 if (!cimg::strcasecmp(buf.pixel_type(),"unsigned short")) matType = CV_16UC1;
331 if (!cimg::strcasecmp(buf.pixel_type(),"short")) matType = CV_16SC1;
332 if (!cimg::strcasecmp(buf.pixel_type(),"int")) matType = CV_32SC1;
333 if (!cimg::strcasecmp(buf.pixel_type(),"float")) matType = CV_32FC1;
334 if (!cimg::strcasecmp(buf.pixel_type(),"double")) matType = CV_64FC1;
335 if (matType<0)
336 throw CImgInstanceException(_cimg_instance
337 "get_MAT() : pixel type '%s' is not supported.",
338 cimg_instance,buf.pixel_type());
339 cv::Mat out;
340 std::vector<cv::Mat> channels(nchannels);
341 if (nchannels>1) {
342 for (int c = 0; c<nchannels; ++c) {
343 channels[c] = cv::Mat(rows,cols,matType,const_cast<T*>(buf.data() + rows*cols*(nchannels - 1 - c)));
344 } // for channels
345 cv::merge(channels,out);
346 } else out = cv::Mat(rows,cols,matType,const_cast<T*>(buf.data())).clone();
347 return out;
348 }
349
350 #endif /* cimg_plugin_cvMat */
351