00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <iostream>
00041 #include <highgui.h>
00042 #include "pyrimage.h"
00043
00044 using namespace std;
00045
00046 PyrImage::PyrImage(IplImage *im, int nblev, bool build_it) : nbLev(nblev)
00047 {
00048 images = new IplImage *[nblev];
00049
00050 images[0] = im;
00051
00052 for (int i=1; i<nbLev; ++i) {
00053 images[i] = cvCreateImage(cvSize(images[i-1]->width/2, images[i-1]->height/2),
00054 im->depth, im->nChannels);
00055 }
00056
00057 if (build_it)
00058 build();
00059 }
00060
00061 PyrImage::~PyrImage() {
00062 for (int i=0; i<nbLev; ++i)
00063 cvReleaseImage(&images[i]);
00064 delete [] images;
00065 }
00066
00067 void PyrImage::build()
00068 {
00069 for (int i=1; i<nbLev; ++i)
00070 cvPyrDown(images[i-1], images[i]);
00071 }
00072
00073 PyrImage *PyrImage::load(int level, const char *filename, int color, bool fatal) {
00074
00075 IplImage *im = cvLoadImage(filename, color);
00076
00077 if (im == 0) {
00078 cerr << filename << ": unable to load image.\n";
00079 if (fatal)
00080 exit(-1);
00081 return 0;
00082 }
00083
00084 PyrImage *r= new PyrImage(im, level);
00085 r->build();
00086 return r;
00087 }
00088
00089 int PyrImage::convCoord(int x, int from, int to, unsigned max)
00090 {
00091 if (max == 2)
00092 return (convCoord(x, from, to, 0) + convCoord(x, from, to, 1)) >> 1;
00093 if (to==from)
00094 return x;
00095 if (to<from) {
00096 if (max == 1) {
00097 int r=x;
00098 for (int i=from; i<to; ++i) {
00099 r = r*2 + 1;
00100 }
00101 return r;
00102 }
00103 return x << ( from - to );
00104 }
00105 return x >> ( to - from );
00106 }
00107
00108 float PyrImage::convCoordf(float x, int from, int to)
00109 {
00110 if (to == from)
00111 return x;
00112
00113 if (to<from)
00114 return x * float(1 << (from-to));
00115
00116 return x / float(1 << (to-from));
00117 }
00118
00119 void PyrImage::setPixel(unsigned x, unsigned y, CvScalar &val)
00120 {
00121 if (( x >= (unsigned)images[0]->width ) || ( y >= (unsigned)images[0]->height ))
00122 return;
00123
00124 for (int i=0; i<nbLev; ++i) {
00125 cvSet2D(images[i],
00126 convCoord((int)y, 0, i),
00127 convCoord((int)x, 0, i),
00128 val);
00129 }
00130 }
00131
00132 void PyrImage::set(CvScalar val)
00133 {
00134 for (int i=0; i<nbLev; ++i)
00135 cvSet(images[i], val);
00136 }
00137
00138 PyrImage *PyrImage::clone() const
00139 {
00140 PyrImage *p = new PyrImage(cvCloneImage(images[0]), nbLev);
00141 for (int i=1; i<nbLev; ++i)
00142 cvCopy(images[i], p->images[i]);
00143 return p;
00144 }
00145
00146 void PyrImage::setImageROI(CvRect rect)
00147 {
00148 CvRect r;
00149 for (int i=0; i<nbLev; ++i) {
00150 r.x = convCoord(rect.x, 0, i);
00151 r.y = convCoord(rect.y, 0, i);
00152 r.width = convCoord(rect.width, 0, i);
00153 r.height = convCoord(rect.height, 0, i);
00154 cvSetImageROI(images[i], r);
00155 }
00156 }
00157
00158 void PyrImage::swap(PyrImage &a) {
00159 assert(nbLev == a.nbLev);
00160 for (int i=0; i<nbLev; i++) {
00161 IplImage *tmp = a[i];
00162 a.images[i] = images[i];
00163 images[i] = tmp;
00164 }
00165 }
00166
00167 void PyrImage::resetImageROI()
00168 {
00169 for (int i=0; i<nbLev; ++i) {
00170 cvResetImageROI(images[i]);
00171 }
00172 }
00173
00174
00175 static inline void bicub_interp3f (
00176 float u,
00177 float v,
00178 float C1[4][4],
00179 float C2[4][4],
00180 float C3[4][4],
00181 double cgret[3])
00182 {
00183 float t8;
00184 float t25; float t26; float t10; float t14; float t24;
00185 float t4; float t37; float t1; float t39; float t18;
00186 float t5; float t22; float t2; float t3; float t63;
00187 float t23; float t51;
00188 t1 = v * v;
00189 t2 = t1 * v;
00190 t3 = 0.5e0f * t2;
00191 t4 = 0.5e0f * v;
00192 t5 = -t3 + t1 - t4;
00193 t8 = 0.15e1f * t2;
00194 t10 = t8 - 0.25e1f * t1 + 0.1e1f;
00195 t14 = -t8 + 0.2e1f * t1 + t4;
00196 t18 = t3 - 0.5e0f * t1;
00197 t22 = u * u;
00198 t23 = t22 * u;
00199 t24 = 0.5e0f * t23;
00200 t25 = 0.5e0f * u;
00201 t26 = -t24 + t22 - t25;
00202 t37 = 0.15e1f * t23;
00203 t39 = t37 - 0.25e1f * t22 + 0.1e1f;
00204 t51 = -t37 + 0.2e1f * t22 + t25;
00205 t63 = t24 - 0.5e0f * t22;
00206 cgret[0] = (t5 * C1[0][0] + t10 * C1[1][0] + t14 * C1[2][0] + t18 * C1[3][0]) * t26
00207 + (t5 * C1[0][1] + t10 * C1[1][1] + t14 * C1[2][1] + t18 * C1[3][1]) * t39
00208 + (t5 * C1[0][2] + t10 * C1[1][2] + t14 * C1[2][2] + t18 * C1[3][2]) * t51
00209 + (t5 * C1[0][3] + t10 * C1[1][3] + t14 * C1[2][3] + t18 * C1[3][3]) * t63;
00210 cgret[1] = (t5 * C2[0][0] + t10 * C2[1][0] + t14 * C2[2][0] + t18 * C2[3][0]) * t26
00211 + (t5 * C2[0][1] + t10 * C2[1][1] + t14 * C2[2][1] + t18 * C2[3][1]) * t39
00212 + (t5 * C2[0][2] + t10 * C2[1][2] + t14 * C2[2][2] + t18 * C2[3][2]) * t51
00213 + (t5 * C2[0][3] + t10 * C2[1][3] + t14 * C2[2][3] + t18 * C2[3][3]) * t63;
00214 cgret[2] = (t5 * C3[0][0] + t10 * C3[1][0] + t14 * C3[2][0] + t18 * C3[3][0]) * t26
00215 + (t5 * C3[0][1] + t10 * C3[1][1] + t14 * C3[2][1] + t18 * C3[3][1]) * t39
00216 + (t5 * C3[0][2] + t10 * C3[1][2] + t14 * C3[2][2] + t18 * C3[3][2]) * t51
00217 + (t5 * C3[0][3] + t10 * C3[1][3] + t14 * C3[2][3] + t18 * C3[3][3]) * t63;
00218 }
00219
00220 static void bicub_interp3f_grad (
00221 float u,
00222 float v,
00223 float C1[4][4],
00224 float C2[4][4],
00225 float C3[4][4],
00226 double color[3],
00227 float *grad)
00228 {
00229 float t14; float t44; float t15; float t23; float t92;
00230 float t67; float t35; float t11; float t149; float t8;
00231 float t46; float t48; float t147; float t25; float t189;
00232 float t62; float t197; float t195; float t119; float t201;
00233 float t199; float t211; float t209; float t18; float t143;
00234 float t145; float t213; float t50; float t151; float t100;
00235 float t131; float t1; float t141; float t215; float t139;
00236 float t27; float t203; float t69; float t137; float t221;
00237 float t2; float t135; float t19; float t219; float t36;
00238 float t223; float t225; float t155; float t52; float t227;
00239 float t3; float t133; float t129; float t40; float t29;
00240 float t10; float t90; float t71; float t4; float t42;
00241 float t121; float t5; float t127; float t54; float t205;
00242 float t21; float t58; float t31; float t65; float t74;
00243 float t125; float t6; float t38; float t153; float t56;
00244 float t33; float t117; float t77; float t217; float t123;
00245 float t80; float t191; float t207; float t81; float t108;
00246 float t83; float t82; float t22; float t193; float t60;
00247 t1 = v * v;
00248 t2 = t1 * v;
00249 t3 = 0.5e0f * t2;
00250 t4 = 0.5e0f * v;
00251 t5 = -t3 + t1 - t4;
00252 t6 = C1[0][0];
00253 t8 = 0.15e1f * t2;
00254 t10 = t8 - 0.25e1f * t1 + 0.1e1f;
00255 t11 = C1[1][0];
00256 t14 = -t8 + 0.2e1f * t1 + t4;
00257 t15 = C1[2][0];
00258 t18 = t3 - 0.5e0f * t1;
00259 t19 = C1[3][0];
00260 t21 = t5 * t6 + t10 * t11 + t14 * t15 + t18 * t19;
00261 t22 = u * u;
00262 t23 = 0.15e1f * t22;
00263 t25 = -t23 + 0.2e1f * u - 0.5e0f;
00264 t27 = C1[0][1];
00265 t29 = C1[1][1];
00266 t31 = C1[2][1];
00267 t33 = C1[3][1];
00268 t35 = t5 * t27 + t10 * t29 + t14 * t31 + t18 * t33;
00269 t36 = 0.45e1f * t22;
00270 t38 = t36 - 0.50e1f * u;
00271 t40 = C1[0][2];
00272 t42 = C1[1][2];
00273 t44 = C1[2][2];
00274 t46 = C1[3][2];
00275 t48 = t5 * t40 + t10 * t42 + t14 * t44 + t18 * t46;
00276 t50 = -t36 + 0.4e1f * u + 0.5e0f;
00277 t52 = C1[0][3];
00278 t54 = C1[1][3];
00279 t56 = C1[2][3];
00280 t58 = C1[3][3];
00281 t60 = t5 * t52 + t10 * t54 + t14 * t56 + t18 * t58;
00282 t62 = t23 - 0.10e1f * u;
00283 t65 = 0.15e1f * t1;
00284 t67 = -t65 + 0.2e1f * v - 0.5e0f;
00285 t69 = 0.45e1f * t1;
00286 t71 = t69 - 0.50e1f * v;
00287 t74 = -t69 + 0.4e1f * v + 0.5e0f;
00288 t77 = t65 - 0.10e1f * v;
00289 t80 = t22 * u;
00290 t81 = 0.5e0f * t80;
00291 t82 = 0.5e0f * u;
00292 t83 = -t81 + t22 - t82;
00293 t90 = 0.15e1f * t80;
00294 t92 = t90 - 0.25e1f * t22 + 0.1e1f;
00295 t100 = -t90 + 0.2e1f * t22 + t82;
00296 t108 = t81 - 0.5e0f * t22;
00297 t117 = C2[0][0];
00298 t119 = C2[1][0];
00299 t121 = C2[2][0];
00300 t123 = C2[3][0];
00301 t125 = t5 * t117 + t10 * t119 + t14 * t121 + t18 * t123;
00302 t127 = C2[0][1];
00303 t129 = C2[1][1];
00304 t131 = C2[2][1];
00305 t133 = C2[3][1];
00306 t135 = t5 * t127 + t10 * t129 + t14 * t131 + t18 * t133;
00307 t137 = C2[0][2];
00308 t139 = C2[1][2];
00309 t141 = C2[2][2];
00310 t143 = C2[3][2];
00311 t145 = t5 * t137 + t10 * t139 + t14 * t141 + t18 * t143;
00312 t147 = C2[0][3];
00313 t149 = C2[1][3];
00314 t151 = C2[2][3];
00315 t153 = C2[3][3];
00316 t155 = t5 * t147 + t10 * t149 + t14 * t151 + t18 * t153;
00317 t189 = C3[0][0];
00318 t191 = C3[1][0];
00319 t193 = C3[2][0];
00320 t195 = C3[3][0];
00321 t197 = t5 * t189 + t10 * t191 + t14 * t193 + t18 * t195;
00322 t199 = C3[0][1];
00323 t201 = C3[1][1];
00324 t203 = C3[2][1];
00325 t205 = C3[3][1];
00326 t207 = t5 * t199 + t10 * t201 + t14 * t203 + t18 * t205;
00327 t209 = C3[0][2];
00328 t211 = C3[1][2];
00329 t213 = C3[2][2];
00330 t215 = C3[3][2];
00331 t217 = t5 * t209 + t10 * t211 + t14 * t213 + t18 * t215;
00332 t219 = C3[0][3];
00333 t221 = C3[1][3];
00334 t223 = C3[2][3];
00335 t225 = C3[3][3];
00336 t227 = t5 * t219 + t10 * t221 + t14 * t223 + t18 * t225;
00337
00338 grad[0] = t21 * t25 + t35 * t38 + t48 * t50 + t60 * t62;
00339 grad[1] = (t67 * t6 + t71 * t11 + t74 * t15 + t77 * t19) * t83 + (t67 * t27 + t71 * t29 + t74 * t31 + t77 * t33) * t92 + (t67 * t40 + t71 * t42 + t74 * t44 + t77 * t46) * t100 + (t67 * t52 + t71 * t54 + t74 * t56 + t77 * t58) * t108;
00340
00341 grad[1*2] = t125 * t25 + t135 * t38 + t145 * t50 + t155 * t62;
00342 grad[1*2+1] = (t67 * t117 + t71 * t119 + t74 * t121 + t77 * t123) * t83 + (t67 * t127 + t71 * t129 + t74 * t131 + t77 * t133) * t92 + (t67 * t137 + t71 * t139 + t74 * t141 + t77 * t143) * t100 + (t67 * t147 + t71 * t149 + t74 * t151 + t77 * t153) * t108;
00343
00344 grad[2*2+0] = t197 * t25 + t207 * t38 + t217 * t50 + t227 * t62;
00345 grad[2*2+1] = (t67 * t189 + t71 * t191 + t74 * t193 + t77 * t195) * t83 + (t67 * t199 + t71 * t201 + t74 * t203 + t77 * t205) * t92 + (t67 * t209 + t71 * t211 + t74 * t213 + t77 * t215) * t100 + (t67 * t219 + t71 * t221 + t74 * t223 + t77 * t225) * t108;
00346 color[0] = t21 * t83 + t35 * t92 + t48 * t100 + t60 * t108;
00347 color[1] = t125 * t83 + t135 * t92 + t145 * t100 + t155 * t108;
00348 color[2] = t197 * t83 + t207 * t92 + t217 * t100 + t227 * t108;
00349 }
00350
00351 static CvScalar cvBicubicSample(IplImage *im, float x, float y, float *grad=0) {
00352 float ixf = (float)floorf(x);
00353 float iyf = (float)floorf(y);
00354 int ix = (int) ixf;
00355 int iy = (int) iyf;
00356
00357 CvScalar rgb;
00358 if((ix < 0) || (ix > im->width) || (iy<0) || (iy>im->height))
00359 return cvScalarAll(0);
00360
00361 float u = x-ixf;
00362 float v = y-iyf;
00363 float C[3][4][4];
00364
00365 if((ix <= 0) || (ix >= im->width-2) || (iy<=0) || (iy>=im->height-2)) {
00366 for (int y=0;y<4;y++) {
00367 int sy = MIN(im->height-1,MAX(0, iy-1+y));
00368 for (int x=0;x<4;x++) {
00369 int sx = 3*(MIN(im->width-1,MAX(0, ix-1+x)));
00370 for (int c=0;c<3;c++)
00371 C[c][y][x] = CV_IMAGE_ELEM(im, unsigned char, sy,sx+c);
00372 }
00373 }
00374 } else {
00375 unsigned char *src = &CV_IMAGE_ELEM(im, unsigned char, (iy-1),(ix-1)*3);
00376 for (int y=0;y<4;y++) {
00377 unsigned char *s=src;
00378 for (int x=0;x<4;x++) {
00379 for (int c=0;c<3;c++)
00380 C[c][y][x] = *s++;
00381 }
00382 src += im->widthStep;
00383 }
00384 }
00385
00386 if (grad)
00387 bicub_interp3f_grad(u,v,C[0],C[1],C[2],rgb.val, grad);
00388 else
00389 bicub_interp3f(u,v,C[0],C[1],C[2],rgb.val);
00390 return rgb;
00391 }
00392
00393 CvScalar PyrImage::bicubicSample(float _u, float _v, int l, float *grad) const {
00394 float div = 1.0f/(float)(1<<l);
00395 float x = _u*div;
00396 float y = _v*div;
00397 CvScalar s= cvBicubicSample(images[l], x,y,grad);
00398 if (grad) {
00399 for (int i=0;i<6;i++) grad[i]*=div;
00400 }
00401 return s;
00402 }
00403
00404
00405 CvScalar PyrImage::randomSample(float u, float v, float sigma2, float *grad) const
00406 {
00407 int l=-1;
00408
00409 float sigma_l2;
00410 float sigma_l_p2;
00411
00412 do {
00413 l++;
00414 sigma_l2 = ((1<<(2*l))-1)/3.0f;
00415 sigma_l_p2 = ((1<<(2*l+2))-1)/3.0f;
00416
00417 if (l==nbLev-2) break;
00418 } while (!((sigma_l2 <= sigma2) && (sigma_l_p2 >= sigma2)));
00419
00420 float sdiv = 1.0f/(sigma_l_p2-sigma_l2);
00421 float rs = (sigma2 - sigma_l2)*sdiv;
00422
00423 if (rs<0) rs=0;
00424 if (rs>1) rs=1;
00425
00426 float grad1[3][2];
00427 float grad2[3][2];
00428 float *g1=0;
00429 float *g2=0;
00430 if (grad) {
00431 g1=&grad1[0][0];
00432 g2=&grad2[0][0];
00433 }
00434 CvScalar r;
00435 CvScalar a = bicubicSample(u,v,l,g1);
00436 CvScalar b = bicubicSample(u,v,l+1,g2);
00437 float mrs = 1-rs;
00438 for (int i=0;i<3;i++) {
00439 float d = (float)(b.val[i]-a.val[i]);
00440 float v = (float)(a.val[i]+rs*d);
00441 if (grad) {
00442 grad[i*3 + 0] = mrs*g1[i*2] +rs*g2[i*2];
00443 grad[i*3 + 1] = mrs*g1[i*2+1] + rs*g2[i*2+1];
00444 grad[i*3 + 2] = d*sdiv;
00445 }
00446 v = MAX(v,0);
00447 r.val[i] = MIN(v,255);
00448 }
00449 return r;
00450 }
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484