cimg.cxx 3.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,323 @@
1
+ /*
2
+ #
3
+ # File : chlpca.cpp
4
+ # ( C++ source file )
5
+ #
6
+ # Description : Example of use for the CImg plugin 'plugins/chlpca.h'.
7
+ # This file is a part of the CImg Library project.
8
+ # ( http://cimg.eu )
9
+ #
10
+ # Copyright : Jerome Boulanger
11
+ # ( http://www.irisa.fr/vista/Equipe/People/Jerome.Boulanger.html )
12
+ #
13
+ #
14
+ # License : CeCILL v2.0
15
+ # ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
16
+ #
17
+ # This software is governed by the CeCILL license under French law and
18
+ # abiding by the rules of distribution of free software. You can use,
19
+ # modify and/ or redistribute the software under the terms of the CeCILL
20
+ # license as circulated by CEA, CNRS and INRIA at the following URL
21
+ # "http://www.cecill.info".
22
+ #
23
+ # As a counterpart to the access to the source code and rights to copy,
24
+ # modify and redistribute granted by the license, users are provided only
25
+ # with a limited warranty and the software's author, the holder of the
26
+ # economic rights, and the successive licensors have only limited
27
+ # liability.
28
+ #
29
+ # In this respect, the user's attention is drawn to the risks associated
30
+ # with loading, using, modifying and/or developing or reproducing the
31
+ # software by the user in light of its specific status of free software,
32
+ # that may mean that it is complicated to manipulate, and that also
33
+ # therefore means that it is reserved for developers and experienced
34
+ # professionals having in-depth computer knowledge. Users are therefore
35
+ # encouraged to load and test the software's suitability as regards their
36
+ # requirements in conditions enabling the security of their systems and/or
37
+ # data to be ensured and, more generally, to use and operate it in the
38
+ # same conditions as regards security.
39
+ #
40
+ # The fact that you are presently reading this means that you have had
41
+ # knowledge of the CeCILL license and that you accept its terms.
42
+ #
43
+ */
44
+
45
+ #ifndef cimg_plugin_chlpca
46
+ #define cimg_plugin_chlpca
47
+
48
+ // Define some useful macros.
49
+
50
+ //! Some loops
51
+ #define cimg_for_step1(bound,i,step) for (int i = 0; i<(int)(bound); i+=step)
52
+ #define cimg_for_stepX(img,x,step) cimg_for_step1((img)._width,x,step)
53
+ #define cimg_for_stepY(img,y,step) cimg_for_step1((img)._height,y,step)
54
+ #define cimg_for_stepZ(img,z,step) cimg_for_step1((img)._depth,z,step)
55
+ #define cimg_for_stepXY(img,x,y,step) cimg_for_stepY(img,y,step) cimg_for_stepX(img,x,step)
56
+ #define cimg_for_stepXYZ(img,x,y,step) cimg_for_stepZ(img,z,step) cimg_for_stepY(img,y,step) cimg_for_stepX(img,x,step)
57
+
58
+ //! Loop for point J(xj,yj) in the neighborhood of a point I(xi,yi) of size (2*rx+1,2*ry+1)
59
+ /**
60
+ Point J is kept inside the boundaries of the image img.
61
+ example of summing the pixels values in a neighborhood 11x11
62
+ cimg_forXY(img,xi,yi) cimg_for_windowXY(img,xi,yi,xj,yj,5,5) dest(yi,yi) += src(xj,yj);
63
+ **/
64
+ #define cimg_forXY_window(img,xi,yi,xj,yj,rx,ry) \
65
+ for (int yi0 = std::max(0,yi-ry), yi1=std::min(yi + ry,(int)img.height() - 1), yj=yi0;yj<=yi1;++yj) \
66
+ for (int xi0 = std::max(0,xi-rx), xi1=std::min(xi + rx,(int)img.width() - 1), xj=xi0;xj<=xi1;++xj)
67
+
68
+ #define cimg_forXYZ_window(img,xi,yi,zi,xj,yj,zj,rx,ry,rz) \
69
+ for (int zi0 = std::max(0,zi-rz), zi1=std::min(zi + rz,(int)img.depth() - 1) , zj=zi0;zj<=zi1;++zj) \
70
+ for (int yi0 = std::max(0,yi-ry), yi1=std::min(yi + ry,(int)img.height() - 1), yj=yi0;yj<=yi1;++yj) \
71
+ for (int xi0 = std::max(0,xi-rx), xi1=std::min(xi + rx,(int)img.width() - 1) , xj=xi0;xj<=xi1;++xj)
72
+
73
+ //! Crop a patch in the image around position x,y,z and return a column vector
74
+ /**
75
+ \param x x-coordinate of the center of the patch
76
+ \param y y-coordinate of the center of the patch
77
+ \param z z-coordinate of the center of the patch
78
+ \param px the patch half width
79
+ \param px the patch half height
80
+ \param px the patch half depth
81
+ \return img.get_crop(x0,y0,z0,x1,y1,z1).unroll('y');
82
+ **/
83
+ CImg<T> get_patch(int x, int y, int z,
84
+ int px, int py, int pz) const {
85
+ if (depth() == 1){
86
+ const int x0 = x - px, y0 = y - py, x1 = x + px, y1 = y + py;
87
+ return get_crop(x0, y0, x1, y1).unroll('y');
88
+ } else {
89
+ const int
90
+ x0 = x - px, y0 = y - py, z0 = z - pz,
91
+ x1 = x + px, y1 = y + py, z1 = z + pz;
92
+ return get_crop(x0, y0, z0, x1, y1, z1).unroll('y');
93
+ }
94
+ }
95
+
96
+ //! Extract a local patch dictionnary around point xi,yi,zi
97
+ CImg<T> get_patch_dictionnary(const int xi, const int yi, const int zi,
98
+ const int px, const int py, const int pz,
99
+ const int wx, const int wy, const int wz,
100
+ int & idc) const {
101
+ const int
102
+ n = (2*wx + 1) * (2*wy + 1) * (2 * (depth()==1?0:wz) + 1),
103
+ d = (2*px + 1) * (2*py + 1) * (2 * (depth()==1?0:px) + 1) * spectrum();
104
+ CImg<> S(n, d);
105
+ int idx = 0;
106
+ if (depth() == 1) {
107
+ cimg_forXY_window((*this), xi, yi, xj, yj, wx, wy){
108
+ CImg<T> patch = get_patch(xj, yj, 0, px, py, 1);
109
+ cimg_forY(S,y) S(idx,y) = patch(y);
110
+ if (xj==xi && yj==yi) idc = idx;
111
+ idx++;
112
+ }
113
+ } else {
114
+ cimg_forXYZ_window((*this), xi,yi,zi,xj,yj,zj,wx,wy,wz){
115
+ CImg<T> patch = get_patch(xj, yj, zj, px, py, pz);
116
+ cimg_forY(S,y) S(idx,y) = patch(y);
117
+ if (xj==xi && yj==yi && zj==zi) idc = idx;
118
+ idx++;
119
+ }
120
+ }
121
+ S.columns(0, idx - 1);
122
+ return S;
123
+ }
124
+
125
+ //! Add a patch to the image
126
+ /**
127
+ \param x x-coordinate of the center of the patch
128
+ \param y y-coordinate of the center of the patch
129
+ \param z z-coordinate of the center of the patch
130
+ \param img the patch as a 1D column vector
131
+ \param px the patch half width
132
+ \param px the patch half height
133
+ \param px the patch half depth
134
+ **/
135
+ CImg<T> & add_patch(const int xi, const int yi, const int zi,
136
+ const CImg<T> & patch,
137
+ const int px, const int py, const int pz) {
138
+ const int
139
+ x0 = xi - px, y0 = yi - py, z0 = (depth() == 1 ? 0 : zi - pz),
140
+ sx = 2 * px + 1, sy = 2 * py + 1, sz = (depth() == 1 ? 1 : 2 * pz +1);
141
+ draw_image(x0, y0, z0, 0, patch.get_resize(sx, sy, sz, spectrum(), -1), -1);
142
+ return (*this);
143
+ }
144
+
145
+ //! Add a constant patch to the image
146
+ /**
147
+ \param x x-coordinate of the center of the patch
148
+ \param y y-coordinate of the center of the patch
149
+ \param z z-coordinate of the center of the patch
150
+ \param value in the patch
151
+ \param px the patch half width
152
+ \param px the patch half height
153
+ \param px the patch half depth
154
+ **/
155
+ CImg<T> & add_patch(const int xi, const int yi, const int zi, const T value,
156
+ const int px, const int py, const int pz) {
157
+ const int
158
+ x0 = xi - px, y0 = yi - py, z0 = (depth() == 1 ? 0 : zi - pz),
159
+ x1 = xi + px, y1 = yi + py, z1 = (depth() == 1 ? 0 : zi + pz);
160
+ draw_rectangle(x0, y0, z0, 0, x1, y1, z1, spectrum()-1, value, -1);
161
+ return (*this);
162
+ }
163
+
164
+ //! CHLPCA denoising from the PhD thesis of Hu Haijuan
165
+ /**
166
+ \param px the patch half width
167
+ \param py the patch half height
168
+ \param pz the patch half depth
169
+ \param wx the training region half width
170
+ \param wy the training region half height
171
+ \param wz the training region half depth
172
+ \param nstep the subsampling of the image domain
173
+ \param nsim the number of patches used for training as a factor of the patch size
174
+ \param lambda_min the threshold on the eigen values of the PCA for dimension reduction
175
+ \param threshold the threshold on the value of the coefficients
176
+ \param pca_use_svd if true use the svd approach to perform the pca otherwise use the covariance method
177
+ \note please cite the PhD thesis of Hu Haijuan http://www.univ-ubs.fr/soutenance-de-these-hu-haijuan-337653.kjsp?RH=1318498222799
178
+ **/
179
+ CImg<T> get_chlpca(const int px, const int py, const int pz,
180
+ const int wx, const int wy, const int wz,
181
+ const int nstep, const float nsim,
182
+ const float lambda_min, const float threshold,
183
+ const float noise_std, const bool pca_use_svd) const {
184
+ const int
185
+ nd = (2*px + 1) * (2*py + 1) * (depth()==1?1:2*pz + 1) * spectrum(),
186
+ K = (int)(nsim * nd);
187
+ #ifdef DEBUG
188
+ fprintf(stderr,"chlpca: p:%dx%dx%d,w:%dx%dx%d,nd:%d,K:%d\n",
189
+ 2*px + 1,2*py + 1,2*pz + 1,2*wx + 1,2*wy + 1,2*wz + 1,nd,K);
190
+ #endif
191
+ float sigma;
192
+ if (noise_std<0) sigma = (float)std::sqrt(variance_noise());
193
+ else sigma = noise_std;
194
+ CImg<T> dest(*this), count(*this);
195
+ dest.fill(0);
196
+ count.fill(0);
197
+ cimg_for_stepZ(*this,zi,(depth()==1||pz==0)?1:nstep){
198
+ #ifdef cimg_use_openmp
199
+
200
+ cimg_pragma_openmp(parallel for)
201
+ #endif
202
+ cimg_for_stepXY((*this),xi,yi,nstep){
203
+ // extract the training region X
204
+ int idc = 0;
205
+ CImg<T> S = get_patch_dictionnary(xi,yi,zi,px,py,pz,wx,wy,wz,idc);
206
+ // select the K most similar patches within the training set
207
+ CImg<T> Sk(S);
208
+ CImg<unsigned int> a_index(S.width());
209
+ if (K < Sk.width() - 1){
210
+ CImg<T> mse(S.width());
211
+ CImg<unsigned int> perms;
212
+ cimg_forX(S,x) { mse(x) = (T)S.get_column(idc).MSE(S.get_column(x)); }
213
+ mse.sort(perms,true);
214
+ cimg_foroff(perms,i) {
215
+ cimg_forY(S,j) Sk(i,j) = S(perms(i),j);
216
+ a_index(perms(i)) = i;
217
+ }
218
+ Sk.columns(0, K);
219
+ perms.threshold(K);
220
+ } else {
221
+ cimg_foroff(a_index,i) a_index(i)=i;
222
+ }
223
+ // centering the patches
224
+ CImg<T> M(1, Sk.height(), 1, 1, 0);
225
+ cimg_forXY(Sk,x,y) { M(y) += Sk(x,y); }
226
+ M /= (T)Sk.width();
227
+ cimg_forXY(Sk,x,y) { Sk(x,y) -= M(y); }
228
+ // compute the principal component of the training set S
229
+ CImg<T> P, lambda;
230
+ if (pca_use_svd) {
231
+ CImg<T> V;
232
+ Sk.get_transpose().SVD(V,lambda,P,true,100);
233
+ } else {
234
+ (Sk * Sk.get_transpose()).symmetric_eigen(lambda, P);
235
+ lambda.sqrt();
236
+ }
237
+ // dimension reduction
238
+ int s = 0;
239
+ const T tx = (T)(std::sqrt((double)Sk.width()-1.0) * lambda_min * sigma);
240
+ while((lambda(s) > tx) && (s < ((int)lambda.size() - 1))) { s++; }
241
+ P.columns(0,s);
242
+ // project all the patches on the basis (compute scalar product)
243
+ Sk = P.get_transpose() * Sk;
244
+ // threshold the coefficients
245
+ if (threshold > 0) { Sk.threshold(threshold, 1); }
246
+ // project back to pixel space
247
+ Sk = P * Sk;
248
+ // recenter the patches
249
+ cimg_forXY(Sk,x,y) { Sk(x,y) += M(y); }
250
+ int j = 0;
251
+ cimg_forXYZ_window((*this),xi,yi,zi,xj,yj,zj,wx,wy,wz){
252
+ const int id = a_index(j);
253
+ if (id < Sk.width()) {
254
+ dest.add_patch(xj, yj, zj, Sk.get_column(id), px, py, pz);
255
+ count.add_patch(xj, yj, zj, (T)1, px, py, pz);
256
+ }
257
+ j++;
258
+ }
259
+ }
260
+ }
261
+ cimg_foroff(dest, i) {
262
+ if(count(i) != 0) { dest(i) /= count(i); }
263
+ else { dest(i) = (*this)(i); }
264
+ }
265
+ return dest;
266
+ }
267
+
268
+ //! CHLPCA denoising from the PhD thesis of Hu Haijuan
269
+ /**
270
+ \param px the patch half width
271
+ \param px the patch half height
272
+ \param px the patch half depth
273
+ \param wx the training region half width
274
+ \param wy the training region half height
275
+ \param wz the training region half depth
276
+ \param nstep the subsampling of the image domain
277
+ \param nsim the number of patches used for training as a factor of the patch size
278
+ \param lambda_min the threshold on the eigen values of the PCA for dimension reduction
279
+ \param threshold the threshold on the value of the coefficients
280
+ \param pca_use_svd if true use the svd approach to perform the pca otherwise use the covariance method
281
+ \note please cite the PhD thesis of Hu Haijuan http://www.univ-ubs.fr/soutenance-de-these-hu-haijuan-337653.kjsp?RH=1318498222799
282
+ **/
283
+ CImg<T> & chlpca(const int px, const int py, const int pz,
284
+ const int wx, const int wy, const int wz,
285
+ const int nstep, const float nsim,
286
+ const float lambda_min, const float threshold,
287
+ const float noise_std, const bool pca_use_svd) {
288
+ (*this) = get_chlpca(px, py, pz, wx, wy, wz, nstep, nsim, lambda_min,
289
+ threshold, noise_std, pca_use_svd);
290
+ return (*this);
291
+ }
292
+
293
+ //! CHLPCA denoising from the PhD thesis of Hu Haijuan
294
+ /**
295
+ \param p the patch half size
296
+ \param w the training region half size
297
+ \param nstep the subsampling of the image domain
298
+ \param nsim the number of patches used for training as a factor of the patch size
299
+ \param lambda_min the threshold on the eigen values of the PCA for dimension reduction
300
+ \param threshold the threshold on the value of the coefficients
301
+ \param pca_use_svd if true use the svd approach to perform the pca otherwise use the covariance method
302
+ \note please cite the PhD thesis of Hu Haijuan http://www.univ-ubs.fr/soutenance-de-these-hu-haijuan-337653.kjsp?RH=1318498222799
303
+ **/
304
+ CImg<T> get_chlpca(const int p=3, const int w=10,
305
+ const int nstep=5, const float nsim=10,
306
+ const float lambda_min=2, const float threshold = -1,
307
+ const float noise_std=-1, const bool pca_use_svd=true) const {
308
+ if (depth()==1) return get_chlpca(p, p, 0, w, w, 0, nstep, nsim, lambda_min,
309
+ threshold, noise_std, pca_use_svd);
310
+ else return get_chlpca(p, p, p, w, w, w, nstep, nsim, lambda_min,
311
+ threshold, noise_std, pca_use_svd);
312
+ }
313
+
314
+ CImg<T> chlpca(const int p=3, const int w=10,
315
+ const int nstep=5, const float nsim=10,
316
+ const float lambda_min=2, const float threshold = -1,
317
+ const float noise_std=-1, const bool pca_use_svd=true) {
318
+ (*this) = get_chlpca(p, w, nstep, nsim, lambda_min,
319
+ threshold, noise_std, pca_use_svd);
320
+ return (*this);
321
+ }
322
+
323
+ #endif /* cimg_plugin_chlpca */
@@ -0,0 +1,350 @@
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.sourceforge.net )
11
+ #
12
+ # Copyright : Alberto Albiol
13
+ # alalbiol@iteam.upv.es
14
+ #
15
+ # How to use : In the main program include:
16
+ # #include "cv.h"
17
+ # #include "highgui.h"
18
+ # #define cimg_plugin1 "cvMat.h"
19
+ # #include "CImg.h"
20
+ */
21
+ #ifndef cimg_plugin_cvMat
22
+ #define cimg_plugin_cvMat
23
+
24
+ // Conversion IPL -> CImg (constructor)
25
+ CImg(const cv::Mat& src):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
26
+ assign(src);
27
+ }
28
+
29
+ // Conversion IPL -> CImg (in-place constructor)
30
+ CImg<T>& assign(const cv::Mat & src) {
31
+ if (src.isContinuous()) {
32
+ switch (src.depth()) {
33
+ // case CV_1U: { // 1-bit int.
34
+ // IplImage *src1 = cvCreateImage(cvGetSize(src),CV_8U,1);
35
+ // cvConvert(src,src1);
36
+ // CImg<ucharT>((unsigned char*)src1->imageData,src1->nChannels,src1.cols,src1.rows,1,true).
37
+ // get_permute_axes("yzcx").move_to(*this);
38
+ // cvReleaseImage(&src1);
39
+ // } break;
40
+ case CV_8U: // 8-bit unsigned int.
41
+ if (src.channels()==1) {
42
+ CImg<ucharT>((unsigned char*)src.ptr(),src.cols,src.rows,true).move_to(*this);
43
+ } else {
44
+ std::vector<cv::Mat> channels;
45
+ cv::split(src,channels);
46
+ CImg<ucharT>
47
+ tmp(src.cols,src.rows,1,3),
48
+ R = tmp.get_shared_channel(2),
49
+ G = tmp.get_shared_channel(1),
50
+ B = tmp.get_shared_channel(0);
51
+ std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(uchar));
52
+ std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(uchar));
53
+ std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(uchar));
54
+ tmp.move_to(*this);
55
+ }
56
+ break;
57
+ case CV_8S: // 8-bit signed int.
58
+ if (src.channels()==1) {
59
+ CImg<charT>((char*)src.ptr(),src.cols,src.rows,true).move_to(*this);
60
+ } else {
61
+ std::vector<cv::Mat> channels;
62
+ cv::split(src,channels);
63
+ CImg<ucharT>
64
+ tmp(src.cols,src.rows,1,3),
65
+ R = tmp.get_shared_channel(2),
66
+ G = tmp.get_shared_channel(1),
67
+ B = tmp.get_shared_channel(0);
68
+ std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(char));
69
+ std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(char));
70
+ std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(char));
71
+ tmp.move_to(*this);
72
+ }
73
+ break;
74
+ case CV_16U: // 16-bit unsigned int.
75
+ if (src.channels()==1) {
76
+ CImg<ushortT>((unsigned short*)src.ptr(),src.cols,src.rows,true).move_to(*this);
77
+ } else {
78
+ std::vector<cv::Mat> channels;
79
+ cv::split(src,channels);
80
+ CImg<ushortT>
81
+ tmp(src.cols,src.rows,1,3),
82
+ R = tmp.get_shared_channel(2),
83
+ G = tmp.get_shared_channel(1),
84
+ B = tmp.get_shared_channel(0);
85
+ std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(unsigned short));
86
+ std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(unsigned short));
87
+ std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(unsigned short));
88
+ tmp.move_to(*this);
89
+ }
90
+ break;
91
+ case CV_16S: // 16-bit signed int.
92
+ if (src.channels()==1) {
93
+ CImg<shortT>((short*)src.ptr(),src.cols,src.rows,true).move_to(*this);
94
+ } else {
95
+ std::vector<cv::Mat> channels;
96
+ cv::split(src,channels);
97
+ CImg<shortT>
98
+ tmp(src.cols,src.rows,1,3),
99
+ R = tmp.get_shared_channel(2),
100
+ G = tmp.get_shared_channel(1),
101
+ B = tmp.get_shared_channel(0);
102
+ std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(short));
103
+ std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(short));
104
+ std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(short));
105
+ tmp.move_to(*this);
106
+ }
107
+ break;
108
+ case CV_32S: // 32-bit signed int.
109
+ if (src.channels()==1) {
110
+ CImg<intT>((int*)src.ptr(),src.cols,src.rows,true).move_to(*this);
111
+ } else {
112
+ std::vector<cv::Mat> channels;
113
+ cv::split(src,channels);
114
+ CImg<intT>
115
+ tmp(src.cols,src.rows,1,3),
116
+ R = tmp.get_shared_channel(2),
117
+ G = tmp.get_shared_channel(1),
118
+ B = tmp.get_shared_channel(0);
119
+ std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(int));
120
+ std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(int));
121
+ std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(int));
122
+ tmp.move_to(*this);
123
+ }
124
+ break;
125
+ case CV_32F: // 32-bit float.
126
+ if (src.channels()==1) {
127
+ CImg<floatT>((float*)src.ptr(),src.cols,src.rows,true).move_to(*this);
128
+ } else {
129
+ std::vector<cv::Mat> channels;
130
+ cv::split(src,channels);
131
+ CImg<floatT>
132
+ tmp(src.cols,src.rows,1,3),
133
+ R = tmp.get_shared_channel(2),
134
+ G = tmp.get_shared_channel(1),
135
+ B = tmp.get_shared_channel(0);
136
+ std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(float));
137
+ std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(float));
138
+ std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(float));
139
+ tmp.move_to(*this);
140
+ }
141
+ break;
142
+ case CV_64F: // 64-bit double.
143
+ if (src.channels()==1) {
144
+ CImg<doubleT>((double*)src.ptr(),src.cols,src.rows,true).move_to(*this);
145
+ } else {
146
+ std::vector<cv::Mat> channels;
147
+ cv::split(src,channels);
148
+ CImg<doubleT>
149
+ tmp(src.cols,src.rows,1,3),
150
+ R = tmp.get_shared_channel(2),
151
+ G = tmp.get_shared_channel(1),
152
+ B = tmp.get_shared_channel(0);
153
+ std::memcpy(R.data(),channels[0].ptr(),src.cols*src.rows*sizeof(double));
154
+ std::memcpy(G.data(),channels[1].ptr(),src.cols*src.rows*sizeof(double));
155
+ std::memcpy(B.data(),channels[2].ptr(),src.cols*src.rows*sizeof(double));
156
+ tmp.move_to(*this);
157
+ }
158
+ break;
159
+ default:
160
+ throw CImgInstanceException(_cimg_instance
161
+ "assign(const cv::Mat&) : Mat depth is invalid.",
162
+ cimg_instance);
163
+ break;
164
+ }
165
+ } else {
166
+ cv::Size size = src.size();
167
+ switch (src.depth()) {
168
+ case CV_8U: // 8-bit unsigned int.
169
+ if (src.channels()==1) {
170
+ CImg<ucharT> tmp(src.cols,src.rows);
171
+ for (int i = 0; i<size.height; ++i) {
172
+ const unsigned char* row_i = src.ptr<unsigned char>(i);
173
+ unsigned char *row_o = tmp.data(0,i);
174
+ std::memcpy(row_o,row_i,size.width*sizeof(unsigned char));
175
+ }
176
+ tmp.move_to(*this);
177
+ } else {
178
+ CImg<ucharT> tmp(src.cols,src.rows,1,src.channels());
179
+ std::vector<cv::Mat> channels;
180
+ cv::split(src,channels);
181
+ for (int c = 0; c<src.channels(); ++c) {
182
+ CImg<ucharT> plane = tmp.get_shared_channel(src.channels()-1-c);
183
+ for (int i = 0; i<size.height; ++i) {
184
+ const unsigned char* row_i = channels[c].ptr<unsigned char>(i);
185
+ unsigned char *row_o = plane.data(0,i);
186
+ std::memcpy(row_o,row_i,size.width*sizeof(unsigned char));
187
+ }
188
+ }
189
+ tmp.move_to(*this);
190
+ }
191
+ break;
192
+ case CV_8S: // 8-bit int.
193
+ if (src.channels()==1) {
194
+ CImg<charT> tmp(src.cols,src.rows);
195
+ for (int i = 0; i<size.height; ++i) {
196
+ const char* row_i = src.ptr<char>(i);
197
+ char* row_o = tmp.data(0,i);
198
+ std::memcpy(row_o,row_i,size.width*sizeof(charT));
199
+ }
200
+ tmp.move_to(*this);
201
+ } else {
202
+ CImg<charT> tmp(src.cols,src.rows,1,src.channels());
203
+ std::vector<cv::Mat> channels;
204
+ cv::split(src,channels);
205
+ for (int c = 0; c<src.channels(); ++c) {
206
+ CImg<charT> plane = tmp.get_shared_channel(src.channels()-1-c);
207
+ for (int i = 0; i<size.height; ++i) {
208
+ const char* row_i = channels[c].ptr<char>(i);
209
+ char *row_o = plane.data(0,i);
210
+ std::memcpy(row_o,row_i,size.width*sizeof(char));
211
+ }
212
+ }
213
+ tmp.move_to(*this);
214
+ }
215
+ break;
216
+ case CV_16S: // 16-bit int.
217
+ if (src.channels()==1) {
218
+ CImg<shortT> tmp(src.cols,src.rows);
219
+ for (int i = 0; i<size.height; ++i) {
220
+ const short* row_i = src.ptr<short>(i);
221
+ short *row_o = tmp.data(0,i);
222
+ std::memcpy(row_o,row_i,size.width*sizeof(short));
223
+ }
224
+ tmp.move_to(*this);
225
+ } else {
226
+ CImg<shortT> tmp(src.cols,src.rows,1,src.channels());
227
+ std::vector<cv::Mat> channels;
228
+ cv::split(src,channels);
229
+ for (int c = 0; c<src.channels(); ++c) {
230
+ CImg<shortT> plane = tmp.get_shared_channel(src.channels()-1-c);
231
+ for (int i = 0; i<size.height; ++i) {
232
+ const short* row_i = channels[c].ptr<short>(i);
233
+ short *row_o = plane.data(0,i);
234
+ std::memcpy(row_o,row_i,size.width*sizeof(short));
235
+ }
236
+ }
237
+ tmp.move_to(*this);
238
+ }
239
+ break;
240
+ case CV_32F: // 32-bit float.float
241
+ if (src.channels()==1) {
242
+ CImg<floatT> tmp(src.cols,src.rows);
243
+ for (int i = 0; i<size.height; ++i) {
244
+ const float* row_i = src.ptr<float>(i);
245
+ float *row_o = tmp.data(0,i);
246
+ std::memcpy(row_o,row_i,size.width*sizeof(float));
247
+ }
248
+ tmp.move_to(*this);
249
+ } else {
250
+ CImg<floatT> tmp(src.cols,src.rows,1,src.channels());
251
+ std::vector<cv::Mat> channels;
252
+ cv::split(src,channels);
253
+ for (int c = 0; c<src.channels(); ++c) {
254
+ CImg<floatT> plane = tmp.get_shared_channel(src.channels()-1-c);
255
+ for (int i = 0; i<size.height; ++i) {
256
+ const float* row_i = channels[c].ptr<float>(i);
257
+ float *row_o = plane.data(0,i);
258
+ std::memcpy(row_o,row_i,size.width*sizeof(float));
259
+ }
260
+ }
261
+ tmp.move_to(*this);
262
+ }
263
+ break;
264
+ case CV_64F: // 64-bit double.
265
+ if (src.channels()==1) {
266
+ CImg<doubleT> tmp(src.cols,src.rows);
267
+ for (int i = 0; i<size.height; ++i) {
268
+ const double* row_i = src.ptr<double>(i);
269
+ double *row_o = tmp.data(0,i);
270
+ std::memcpy(row_o,row_i,size.width*sizeof(double));
271
+ }
272
+ tmp.move_to(*this);
273
+ } else {
274
+ CImg<doubleT> tmp(src.cols,src.rows,1,src.channels());
275
+ std::vector<cv::Mat> channels;
276
+ cv::split(src,channels);
277
+ for (int c = 0; c<src.channels(); ++c) {
278
+ CImg<doubleT> plane = tmp.get_shared_channel(src.channels()-1-c);
279
+ for (int i = 0; i<size.height; ++i) {
280
+ const double* row_i = channels[c].ptr<double>(i);
281
+ double *row_o = plane.data(0,i);
282
+ std::memcpy(row_o,row_i,size.width*sizeof(double));
283
+ }
284
+ }
285
+ tmp.move_to(*this);
286
+ }
287
+ break;
288
+ default:
289
+ throw CImgInstanceException(_cimg_instance
290
+ "assign(const cv::Mat&) : Mat depth is invalid.",
291
+ cimg_instance);
292
+ break;
293
+ }
294
+ }
295
+
296
+ // if (!std::strcmp(src->channelSeq,"BGR")) mirror('v');
297
+ // else if (!std::strcmp(src->channelSeq,"BGRA")) get_shared_channels(0,2).mirror('v');
298
+ return *this;
299
+ }
300
+
301
+ // Conversion CImg -> MAT
302
+ cv::Mat get_MAT(const unsigned int z=0) const {
303
+ if (is_empty())
304
+ throw CImgInstanceException(_cimg_instance
305
+ "get_MAT() : instance image is empty.",
306
+ cimg_instance);
307
+ if (z>=_depth)
308
+ throw CImgInstanceException(_cimg_instance
309
+ "get_MAT() : specified slice %u is out of image bounds.",
310
+ cimg_instance,z);
311
+ const CImg<T>
312
+ _slice = _depth>1?get_slice(z):CImg<T>(),
313
+ &slice = _depth>1?_slice:*this;
314
+ CImg<T> buf(slice,true);
315
+ int
316
+ cols = buf.width(),
317
+ rows = buf.height(),
318
+ nchannels = buf.spectrum(),
319
+ matType=-1;
320
+
321
+ if (!cimg::strcasecmp(buf.pixel_type(),"unsigned char")) matType = CV_8UC1;
322
+ if (!cimg::strcasecmp(buf.pixel_type(),"uint8")) matType = CV_8UC1;
323
+ if (!cimg::strcasecmp(buf.pixel_type(),"char")) matType = CV_8SC1;
324
+ if (!cimg::strcasecmp(buf.pixel_type(),"int8")) matType = CV_8SC1;
325
+ if (!cimg::strcasecmp(buf.pixel_type(),"unsigned short")) matType = CV_16UC1;
326
+ if (!cimg::strcasecmp(buf.pixel_type(),"uint16")) matType = CV_16UC1;
327
+ if (!cimg::strcasecmp(buf.pixel_type(),"short")) matType = CV_16SC1;
328
+ if (!cimg::strcasecmp(buf.pixel_type(),"int16")) matType = CV_16SC1;
329
+ if (!cimg::strcasecmp(buf.pixel_type(),"int")) matType = CV_32SC1;
330
+ if (!cimg::strcasecmp(buf.pixel_type(),"int32")) matType = CV_32SC1;
331
+ if (!cimg::strcasecmp(buf.pixel_type(),"float")) matType = CV_32FC1;
332
+ if (!cimg::strcasecmp(buf.pixel_type(),"float32")) matType = CV_32FC1;
333
+ if (!cimg::strcasecmp(buf.pixel_type(),"double")) matType = CV_64FC1;
334
+ if (!cimg::strcasecmp(buf.pixel_type(),"float64")) 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 */