New repo for repo.or.cz
[The-Artvertiser.git] / garfeild / lightcalib / lightmap.cpp
bloba6e774f13deacef2ab8c0a54d61f3ea6c3a55273
1 /*
2 Copyright 2005, 2006 Computer Vision Lab,
3 Ecole Polytechnique Federale de Lausanne (EPFL), Switzerland.
4 Modified by Damian Stewart <damian@frey.co.nz> 2009-2010;
5 modifications Copyright 2009, 2010 Damian Stewart <damian@frey.co.nz>.
7 Distributed under the terms of the GNU General Public License v3.
9 This file is part of The Artvertiser.
11 The Artvertiser is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 The Artvertiser is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public License
22 along with The Artvertiser. If not, see <http://www.gnu.org/licenses/>.
26 #include <stdio.h>
27 #include <iostream>
28 #include <fstream>
30 //also includes opengl if available
31 #include "lightmap.h"
32 #include <highgui.h>
35 #ifndef M_PI
36 #define M_PI 3.1415926535897932384626433832795
37 #endif
39 using namespace std;
41 LightMap::LightMap()
43 ARB=true;
44 initialized=false;
45 lightParams=0;
46 normals=0;
47 nbCam=0;
50 LightMap::LightMap(const LightMap &a)
52 ARB=a.ARB;
53 initialized=false;
54 if (a.map.getIm())
55 map.setImage(cvCloneImage(a.map.getIm()));
56 reflc.copy(a.reflc);
57 lightParams=0;
58 normals=0;
59 nbCam=0;
62 LightMap::~LightMap()
64 IplImage *im = map.getIm();
65 if(im) cvReleaseImage(&im);
66 if (lightParams) cvReleaseMat(&lightParams);
67 if (normals) delete normals;
70 void LightMap::clear()
72 IplImage* im = map.getIm();
73 if ( im ) cvReleaseImage( &im );
74 map.setImage(0);
76 if (normals) delete normals;
77 normals = 0;
79 if (lightParams)
80 cvReleaseMat(&lightParams);
81 lightParams=0;
85 bool LightMap::init(int nbCam, IplImage *model, float corners[4][2], int nx, int ny)
87 IplImage *im = map.getIm();
88 if(im) cvReleaseImage(&im);
89 map.setImage(cvCreateImage(cvSize(128,64), IPL_DEPTH_32F, model->nChannels));
90 cvSet(map.getIm(), cvScalarAll(.1));
91 if (model->nChannels == 3) {
92 im = map.getIm();
93 im->channelSeq[0]='B';
94 im->channelSeq[1]='G';
95 im->channelSeq[2]='R';
98 if (!model) return false;
100 reflc.genGrid(corners, nx, ny);
101 reflc.averageImage(model,0);
104 FILE *IRef= fopen("IRef.txt","w");
105 if (IRef) {
106 for (int i=0; i<reflc.nbTri; i++)
107 fprintf(IRef, "%.6f ", reflc.avg[i]);
108 fprintf(IRef, "\n");
109 fclose(IRef);
113 setCamNum(nbCam);
114 return reflc.avg != 0;
117 void LightMap::normal2uv(const float n[3], float uv[2]) {
118 float l = 1/sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
119 float n0 = n[0]*l;
120 float n1 = n[1]*l;
121 float n2 = n[2]*l;
122 uv[0] = n0*.25f +.25f + (n2>0 ? 0:.5f);
123 uv[1] = .5f+n1*.5f;
126 void LightMap::uv2normal(const float uv[2], float n[3]) {
127 n[0] = (uv[0]-(uv[0]>.5f ? .5f : 0)-.25f)*4;
128 n[1] = 2*uv[1]-1;
129 float len = n[0]*n[0] + n[1]*n[1];
130 if (len>=1) {
131 float f = 1/sqrt(len);
132 n[0]*=f;
133 n[1]*=f;
134 n[2]=(uv[0]>.5f ? -0.0f : 0.0f);
136 else n[2] = sqrt(1-len)*(uv[0]>.5f ? -1 : 1);
138 float l = 1/sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
139 n[0]*=l;
140 n[1]*=l;
141 n[2]*=l;
144 CvScalar LightMap::readMap(const float normal[3])
146 if (!isReady()) return cvScalarAll(1);
147 float uv[2];
148 normal2uv(normal, uv);
150 IplImage *im = map.getIm();
151 assert(im!=0);
152 int iu = cvRound(uv[0]*(double)im->width);
153 int iv = cvRound(uv[1]*(double)im->height);
154 if (iu<0) iu=0;
155 if (iv<0) iv=0;
156 if (iu>=im->width) iu = im->width-1;
157 if (iv>=im->height) iv = im->height-1;
158 return cvGet2D(im, iv, iu );
161 bool LightMap::addNormal(float normal[3], LightCollector &lc, int cam)
163 if (lightParams)
164 return addNormalLightMap(normal,lc,cam);
165 else
166 return addNormalCalib(normal,lc,cam);
169 const float *LightMap::getGain(int cam)
171 static const float ones[3] = {1, 1, 1};
172 if (!isReady()) return ones;
173 return &CV_MAT_ELEM(*lightParams, float, 2*cam, 0);
176 const float *LightMap::getBias(int cam)
178 static const float zeroes[3] = {0, 0, 0};
179 if (!isReady()) return zeroes;
180 return &CV_MAT_ELEM(*lightParams, float, 2*cam+1, 0);
183 bool LightMap::addNormalLightMap(float normal[3], LightCollector &lc, int cam)
185 if (lightParams==0) return false;
186 assert(map.getIm()!=0);
187 assert(cam < nbCam);
189 float l = 1/sqrt(normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2]);
190 normal[0]*=l;
191 normal[1]*=l;
192 normal[2]*=l;
194 float val[3];
195 if (lc.cmpWithRef(reflc, val, getGain(cam), getBias(cam)))
196 return updateLightMap(normal, val);
197 return false;
200 bool LightMap::updateLightMap(float normal[3], float *val)
202 if (val[0]<0) return false;
204 const int nc = map.getIm()->nChannels;
206 for (int y=0; y<map.getIm()->height; y++) {
207 float *line = (float *)(map.getIm()->imageData + y*map.getIm()->widthStep);
209 for (int x=0; x<map.getIm()->width; x++) {
210 float n[3];
211 float uv[2] = { float(x)/float(map.getIm()->width), float(y)/float(map.getIm()->height) };
212 uv2normal(uv, n);
213 float dot = n[0]*normal[0] + n[1]*normal[1] + n[2]*normal[2];
214 #if 0
215 if (dot>0) {
216 dot = acos(dot)*2/M_PI;
217 float s = .2;
218 float f = (1/sqrt(2*M_PI))*exp(-(1-dot)/(2*s*s));
219 line[x] = (1.0f-f)*line[x] + f*val;
221 #else
222 float min_dot=0;
223 if (dot>min_dot) {
224 //dot = pow(dot, 16)/2;
225 float angle = (float)(acos(dot)*2/M_PI);
226 //dot = (dot-min_dot)/(1-min_dot);
227 float s = .2f;
228 //float f = (1/sqrt(2*M_PI))*exp(-(1-dot)/(2*s*s));
229 //float f = (1/sqrt(2*M_PI))*exp(-(angle)/(2*s*s));
230 float f = exp(-(angle)/(2*s*s));
231 for (int c=0; c<nc; c++)
232 line[x*nc +c] = (1.0f-f)*line[x*nc + c] + f*val[c];
234 #endif
237 map.update();
238 return true;
241 #ifdef HAVE_GLEW
242 static void printShaderInfoLog(GLuint obj, const char *str, bool ARB)
244 GLint infologLength = 0;
245 GLint charsWritten = 0;
246 char *infoLog;
248 if (ARB) glGetObjectParameterivARB(obj, GL_INFO_LOG_LENGTH,&infologLength);
249 else glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infologLength);
251 if (infologLength > 0)
253 infoLog = (char *)malloc(infologLength);
254 if (ARB) glGetInfoLogARB(obj, infologLength, &charsWritten, infoLog);
255 else glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
256 if (strlen(infoLog)>0) {
257 if (str) printf("%s\n", str);
258 printf("%s\n",infoLog);
260 free(infoLog);
263 #endif
265 #ifdef HAVE_GLEW
266 static std::string readFile(const char * const file)
268 std::string ret = "";
269 FILE * fp = fopen(file, "rb");
270 if (!fp) return "";
271 fseek(fp, 0, SEEK_END);
272 int size = (int)ftell(fp);
273 fseek(fp, 0, SEEK_SET);
274 char * buf = new char[size + 1];
275 fread(buf, size, 1, fp);
276 fclose(fp);
277 buf[size] = 0;
278 ret = buf;
279 delete [] buf;
280 return ret;
283 static bool checkErrors(const char *file, int line, bool exitOnFailure=false)
285 GLenum error;
286 bool r=true;
287 while ((error = glGetError()) != GL_NO_ERROR) {
288 fprintf(stderr, "%s:%d: %s\n",
289 file, line,
290 (char *) gluErrorString(error));
291 if (exitOnFailure)
292 exit(-1);
293 r=false;
295 return r;
297 #endif
299 bool LightMap::initGL()
301 #ifdef HAVE_GLEW
302 if (initialized) return true;
303 glewInit();
304 initialized = true;
306 ARB = GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader;
307 if (!ARB && !glewIsSupported("GL_VERSION_2_0"))
309 printf("No GLSL support\n");
310 return false;
312 std::string ret;
313 const char * shaderProg;
315 bool ok=true;
316 ret = readFile("myvert.glsl");
317 shaderProg = ret.c_str();
319 if (ARB) g_vertShader = glCreateShaderObjectARB(GL_VERTEX_SHADER);
320 else g_vertShader = glCreateShader(GL_VERTEX_SHADER);
321 ok = ok && checkErrors(__FILE__,__LINE__);
323 if (ARB) glShaderSourceARB(g_vertShader, 1, &shaderProg, 0);
324 else glShaderSource(g_vertShader, 1, &shaderProg, 0);
325 printShaderInfoLog(g_vertShader, "Vertex shader myvert.glsl", ARB);
326 ok = ok && checkErrors(__FILE__,__LINE__);
328 if (ARB) glCompileShaderARB(g_vertShader);
329 else glCompileShader(g_vertShader);
331 printShaderInfoLog(g_vertShader, "Vertex shader myvert.glsl", ARB);
332 ok = ok && checkErrors(__FILE__,__LINE__);
334 ret = readFile("myfrag.glsl");
335 shaderProg = ret.c_str();
336 if (ARB) g_fragShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER);
337 else g_fragShader = glCreateShader(GL_FRAGMENT_SHADER);
339 if (ARB) glShaderSourceARB(g_fragShader, 1, &shaderProg, 0);
340 else glShaderSource(g_fragShader, 1, &shaderProg, 0);
342 if (ARB) glCompileShaderARB(g_fragShader);
343 else glCompileShader(g_fragShader);
345 printShaderInfoLog(g_fragShader, "Fragment shader myfrag.glsl", ARB);
346 ok = ok && checkErrors(__FILE__,__LINE__);
347 //if (!ok) return false;
349 if (ARB) g_shaderProgram = glCreateProgramObjectARB();
350 else g_shaderProgram = glCreateProgram();
352 if (ARB) glAttachObjectARB(g_shaderProgram, g_vertShader);
353 else glAttachShader(g_shaderProgram, g_vertShader);
355 if (ARB) glAttachObjectARB(g_shaderProgram, g_fragShader);
356 else glAttachShader(g_shaderProgram, g_fragShader);
358 if (ARB) glLinkProgramARB(g_shaderProgram);
359 else glLinkProgram(g_shaderProgram);
360 ok = ok && checkErrors(__FILE__,__LINE__);
362 if (ARB) glValidateProgramARB(g_shaderProgram);
363 else glValidateProgram(g_shaderProgram);
364 ok = ok && checkErrors(__FILE__,__LINE__);
365 printShaderInfoLog(g_shaderProgram, "glValidateProgram(g_shaderProgram)", ARB);
366 if (ok) {
367 cout << "GLSL shaders sucessfully initialized using "
368 << (ARB ? "ARB extensions" : "OpenGL 2.0") << ".\n";
369 } else
370 cout << "Failed to initialize GLSL shaders.\n";
371 return ok;
372 #else
373 return false;
374 #endif
377 void LightMap::enableShader(int cam, CvMat *obj2world)
379 #ifdef HAVE_GLEW
380 assert(cam < nbCam);
381 if (!initialized) {
382 if (!initGL()) return;
384 if (ARB) glUseProgramObjectARB(g_shaderProgram);
385 else glUseProgram(g_shaderProgram);
386 if (!checkErrors(__FILE__,__LINE__)) {
387 printShaderInfoLog(g_shaderProgram, "glUseProgram(g_shaderProgram)", ARB);
388 return;
391 GLuint shaderTexture, worldToObjectNormal, gain, bias;
392 if (ARB) {
393 shaderTexture = glGetUniformLocationARB(g_shaderProgram, "main_texture");
394 worldToObjectNormal = glGetUniformLocationARB(g_shaderProgram, "worldToObjectNormal");
395 gain = glGetUniformLocationARB(g_shaderProgram, "gain");
396 bias = glGetUniformLocationARB(g_shaderProgram, "bias");
397 } else {
398 shaderTexture = glGetUniformLocation(g_shaderProgram, "main_texture");
399 worldToObjectNormal = glGetUniformLocation(g_shaderProgram, "worldToObjectNormal");
400 gain = glGetUniformLocation(g_shaderProgram, "gain");
401 bias = glGetUniformLocation(g_shaderProgram, "bias");
403 checkErrors(__FILE__,__LINE__);
405 glActiveTexture(GL_TEXTURE0 + 0);
406 glBindTexture(GL_TEXTURE_2D, shaderTexture);
407 checkErrors(__FILE__,__LINE__);
409 if (ARB) glUniform1iARB(shaderTexture, 0);
410 else glUniform1i(shaderTexture, 0);
411 checkErrors(__FILE__,__LINE__);
413 // The sign change is required because we do not like OpenGL's Z axis direction.
414 // Thus, we flip all normals.
415 float mat[9];
416 for (int i=0; i<3; ++i)
417 for (int j=0; j<3; ++j)
418 mat[j*3 +i] = -(float)cvGet2D(obj2world, i, j).val[0];
420 float g[3],b[3];
421 for (int i=0;i<lightParams->cols; i++) {
422 if (lightParams) {
423 g[i] = 1/cvGet2D(lightParams, cam*2, i).val[0];
424 b[i] = g[i]*cvGet2D(lightParams, cam*2+1, i).val[0];
425 } else {
426 g[i] = 1;
427 b[i] = 0;
430 if (ARB) {
431 glUniform1iARB(shaderTexture, 0);
432 glUniformMatrix3fvARB(worldToObjectNormal, 1, GL_FALSE, mat);
433 glUniform4fARB(gain, g[2], g[1], g[0], 1);
434 glUniform4fARB(bias, b[2], b[1], b[0], 0);
435 } else {
436 glUniform1i(shaderTexture, 0);
437 glUniformMatrix3fv(worldToObjectNormal, 1, GL_FALSE, mat);
438 glUniform4f(gain, g[2], g[1], g[0], 1);
439 glUniform4f(bias, b[2], b[1], b[0], 0);
441 checkErrors(__FILE__,__LINE__);
442 map.loadTexture();
443 checkErrors(__FILE__,__LINE__);
444 #endif
447 void LightMap::disableShader()
449 #ifdef HAVE_GLEW
450 if (ARB) glUseProgramObjectARB(0);
451 else glUseProgram(0);
452 map.disableTexture();
453 #endif
456 void LightMap::setCamNum(int n)
458 obs.clear();
459 obs.reserve(300000);
461 if (normals) delete normals;
462 normals = new CvGrowMat(256,3, CV_32FC1);
463 normals->resize(0,3);
464 nbCam=n;
466 if (lightParams)
467 cvReleaseMat(&lightParams);
468 lightParams=0;
471 static void normalize(float normal[3])
473 float l = 1/sqrt(normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2]);
474 normal[0]*=l;
475 normal[1]*=l;
476 normal[2]*=l;
479 bool LightMap::addNormalCalib(float normal[3], LightCollector &lc, int cam)
481 assert(nbCam>0);
482 if (lc.avg==0 || reflc.avg==0) return false;
484 bool hasObs=false;
486 assert(lc.nbTri == reflc.nbTri);
488 int normIdx = normals->rows + nbCam*2;
489 bool newT=true;
490 float maxdot= .999;
492 normalize(normal);
494 // is the normal already in the database ?
495 for (int i=0; i<normals->rows; i++) {
496 float *n2 = (float *)CV_MAT_ELEM_PTR(*normals, i, 0);
497 float ndot = n2[0]*normal[0] +
498 n2[1]*normal[1] +
499 n2[2]*normal[2];
500 if (ndot > maxdot) {
501 newT=false;
502 maxdot = ndot;
503 normIdx = i + nbCam*2;
507 // if (newT) {
508 // obsMat->resize(obsMat->rows, obsMat->cols+1);
509 // }
511 for (int i=0; i<lc.nbTri; ++i) {
512 float *rv = reflc.avg+i*reflc.avgChannels;
513 float *v = lc.avg+i*lc.avgChannels;
514 bool ok=true;
515 for (int c=0; c<reflc.avgChannels; c++)
516 if (!(v[c]>5 && rv[c] >5 && v[c]<250 && rv[c] <250))
517 ok=false;
518 if (ok) {
519 hasObs = true;
521 Observation o;
522 o.camCol = cam*2;
523 o.normalCol = normIdx;
525 for (int c=0; c<reflc.avgChannels; c++) {
526 o.camVal[c] = - v[c]/255.0f;
527 o.normalVal[c] = rv[c]/255.0f;
529 obs.push_back(o);
533 if (newT&&hasObs){
534 // add the normal vector
535 normals->resize(normals->rows+1, normals->cols);
536 float *n = (float *)CV_MAT_ELEM_PTR(*normals, normals->rows-1,0);
537 n[0] = normal[0];
538 n[1] = normal[1];
539 n[2] = normal[2];
541 return true;
544 static bool saveMat(const CvMat *m, const char *fn)
546 ofstream f(fn);
548 if (!f.good()) return false;
550 for (int j=0; j<m->rows; j++) {
551 for (int i=0; i<m->cols; i++) {
552 double v = cvGet2D(m, j, i).val[0];
553 f << v;
554 if (i+1 < m->cols) f<<'\t';
556 f << endl;
558 f.close();
559 return true;
562 static CvGrowMat *loadMat(const char *fn)
564 ifstream f(fn);
566 if (!f.good()) return 0;
568 CvGrowMat *m = new CvGrowMat(128,3, CV_32FC1);
569 m->resize(1,1);
571 int nrow=0;
572 do {
573 char line[4096];
574 f.getline(line, 4095);
575 line[4095]=0;
576 if (!f.good()) break;
578 ++nrow;
580 int ncols=1;
581 int len = strlen(line);
582 char *last=line;
583 for (int i=0;i<len+1;i++) {
584 if (line[i]==' ' || line[i]=='\t' || line[i]==0) {
585 line[i] = 0;
586 float val;
587 if (sscanf(last, "%f", &val)==1) {
588 m->resize(nrow,max(ncols, m->cols));
589 cvSet2D(m, nrow-1, ncols-1, cvScalarAll(val));
590 ncols++;
592 last = line+i+1;
595 } while (f.good());
597 return m;
600 double LightMap::getObsMat(int i, int j, int c)
602 if (j == obs[i].camCol) return (double)obs[i].camVal[c];
603 if (j == (obs[i].camCol+1)) return 1;
604 if (j == obs[i].normalCol) return (double)obs[i].normalVal[c];
605 return 0;
608 double LightMap::getObsElem(const vector<Observation>::iterator &it, int i, int c)
610 if (it->camCol == i) return it->camVal[c];
611 if (it->camCol+1 == i) return 1;
612 if (it->normalCol == i) return it->normalVal[c];
613 return 0;
616 void LightMap::computeAtA(CvMat *AtA, int channel)
618 for (vector<Observation>::iterator it = obs.begin();
619 it!=obs.end(); ++it)
621 int idx[3] = {it->camCol, it->camCol+1, it->normalCol};
622 for (unsigned i=0; i<3; i++) {
623 for (unsigned j=0; j<3; j++) {
624 int i_ = idx[i];
625 int j_ = idx[j];
626 if (i_ <= j_) {
627 double v = getObsElem(it,i_, channel)*getObsElem(it,j_, channel);
628 if (v!=0) {
629 double d = v+cvGetReal2D(AtA, i_, j_);
630 cvSetReal2D(AtA, i_, j_, d);
631 cvSetReal2D(AtA, j_, i_, d);
638 for (int y=1;y<AtA->height; y++)
639 for (int x=0;x<y; x++) {
640 CV_MAT_ELEM(*AtA, float, y, x) = CV_MAT_ELEM(*AtA, float, x, y);
645 bool LightMap::save(const char *lightParamsFN, const char *normalsFN)
647 return saveMat(lightParams,lightParamsFN) &&
648 saveMat(normals, normalsFN);
651 bool LightMap::computeLightParams()
653 int obsMatCols=normals->rows+2*nbCam;
654 int sizes[] = {obs.size(), obsMatCols};
656 if (lightParams) cvReleaseMat(&lightParams);
657 lightParams = cvCreateMat(obsMatCols, reflc.avgChannels, CV_32FC1);
658 sizes[0] = sizes[1] = obsMatCols;
660 // create temporary matrices
661 CvMat *AtA = cvCreateMat(obsMatCols,obsMatCols, CV_32FC1);
662 CvMat *w = cvCreateMat(obsMatCols, 1, CV_32FC1);
663 CvMat *V = cvCreateMat(obsMatCols, obsMatCols, CV_32FC1);
665 for (int c=0; c<reflc.avgChannels; c++) {
666 cvSetZero(AtA);
667 computeAtA(AtA, c);
669 /* char atafn[64];
670 sprintf(atafn,"ata%d.mat",c);
671 saveMat(AtA, atafn);
674 cvSVD(AtA, w, 0, V, CV_SVD_MODIFY_A);
676 CvMat sub, lpc;
677 cvGetCol(V, &sub, V->cols-1);
678 cvGetCol(lightParams, &lpc, c);
679 cvScale(&sub, &lpc, 1.0/cvGet2D(&sub,0,0).val[0]);
682 std::cout << "Eigen values:";
683 for (int i=0; i<w->rows; ++i) {
684 float v = (float)cvGet2D(w, i, 0).val[0];
685 std::cout << " " << v;
687 std::cout << std::endl;
690 cvReleaseMat(&V);
691 cvReleaseMat(&AtA);
693 // construct light map
694 cvSet(map.getIm(), cvScalarAll(.1));
695 cvReleaseMat(&w);
698 std::cout << "Camera Values:\n";
699 for (int c=0; c<nbCam; ++c) {
700 float g = (float)cvGet2D(lightParams, c*2, 0).val[0];
701 float b = (float)cvGet2D(lightParams, c*2+1, 0).val[0];
702 std::cout <<" cam " << c << ": "<< g <<", " << b << std::endl;
705 buildMapFromSamples();
706 return true;
709 void LightMap::buildMapFromSamples()
711 for (int i=0; i<normals->rows; ++i) {
712 updateLightMap((float *)CV_MAT_ELEM_PTR(*normals, i, 0),
713 &CV_MAT_ELEM(*lightParams, float, i+2*nbCam, 0));
717 bool LightMap::load(const char *lightParamsFN, const char *normalsFN)
719 CvGrowMat *lp= loadMat(lightParamsFN);
720 if (!lp) return false;
721 lightParams = cvCreateMat(lp->rows, lp->cols, CV_32FC1);
722 cvCopy(lp, lightParams);
723 printf("Loaded lightParams: %dx%d.\n", lp->rows, lp->cols);
724 delete lp;
725 normals = loadMat(normalsFN);
726 int nlights = lightParams->rows - 2*nbCam;
727 if (!normals || ((normals->rows) < nlights)) {
728 if (normals) {
729 printf("Not enough normals. Expecting %d cameras. Found %d normals and %d parameters.\n",
730 nbCam, normals->rows, lightParams->rows);
732 cvReleaseMat(&lightParams);
733 return false;
735 if (normals->rows > nlights)
736 normals->resize(nlights,3);
739 std::cout << "Camera Values:\n";
740 for (int c=0; c<nbCam; ++c) {
741 float g = (float)cvGet2D(lightParams, c*2, 0).val[0];
742 float b = (float)cvGet2D(lightParams, c*2+1, 0).val[0];
743 std::cout <<" cam " << c << ": "<< g <<", " << b << std::endl;
747 buildMapFromSamples();
749 return true;
752 bool LightMap::saveImage(const char *filename)
754 IplImage *image = map.getIm();
755 if (image==0) return false;
756 IplImage *im = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U,image->nChannels);
757 //double min=0, max=2;
758 //cvMinMaxLoc(image, &min, &max);
759 cvConvertScale(image, im, 128, 0);
760 int r = cvSaveImage(filename, im);
761 cvReleaseImage(&im);
762 return r!=0;