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.
- package/CImg.h +70659 -0
- package/Licence_CeCILL-C_V1-en.txt +508 -0
- package/Licence_CeCILL_V2-en.txt +504 -0
- package/README.md +44 -0
- package/README.txt +180 -0
- package/package.json +15 -0
- package/plugins/add_fileformat.h +79 -0
- package/plugins/bayer.h +212 -0
- package/plugins/chlpca.h +323 -0
- package/plugins/cvMat.h +350 -0
- package/plugins/draw_gradient.h +269 -0
- package/plugins/inpaint.h +508 -0
- package/plugins/ipl.h +309 -0
- package/plugins/ipl_alt.h +122 -0
- package/plugins/jpeg_buffer.h +377 -0
- package/plugins/loop_macros.h +24166 -0
- package/plugins/matlab.h +287 -0
- package/plugins/nlmeans.h +242 -0
- package/plugins/skeleton.h +587 -0
- package/plugins/tiff_stream.h +196 -0
- package/plugins/tinymatwriter.h +109 -0
- package/plugins/vrml.h +894 -0
- package/plugins/vtk.h +103 -0
package/plugins/chlpca.h
ADDED
|
@@ -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 */
|
package/plugins/cvMat.h
ADDED
|
@@ -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 */
|