11 #define M_PI 3.1415926535897932384626433832795
30 map.setImage(cvCloneImage(a.
map.
getIm()));
39 IplImage *im = map.getIm();
40 if(im) cvReleaseImage(&im);
41 if (lightParams) cvReleaseMat(&lightParams);
42 if (normals)
delete normals;
45 bool LightMap::init(
int nbCam, IplImage *model,
float corners[4][2],
int nx,
int ny)
47 IplImage *im = map.getIm();
48 if(im) cvReleaseImage(&im);
49 map.setImage(cvCreateImage(cvSize(128,64), IPL_DEPTH_32F, model->nChannels));
50 cvSet(map.getIm(), cvScalarAll(.1));
51 if (model->nChannels == 3) {
53 im->channelSeq[0]=
'B';
54 im->channelSeq[1]=
'G';
55 im->channelSeq[2]=
'R';
58 if (!model)
return false;
60 reflc.genGrid(corners, nx, ny);
61 reflc.averageImage(model,0);
74 return reflc.avg != 0;
77 void LightMap::normal2uv(
const float n[3],
float uv[2]) {
78 float l = 1/sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
82 uv[0] = n0*.25f +.25f + (n2>0 ? 0:.5f);
86 void LightMap::uv2normal(
const float uv[2],
float n[3]) {
87 n[0] = (uv[0]-(uv[0]>.5f ? .5f : 0)-.25f)*4;
89 float len = n[0]*n[0] + n[1]*n[1];
91 float f = 1/sqrt(len);
94 n[2]=(uv[0]>.5f ? -0.0f : 0.0f);
96 else n[2] = sqrt(1-len)*(uv[0]>.5f ? -1 : 1);
98 float l = 1/sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
106 if (!isReady())
return cvScalarAll(1);
108 normal2uv(normal, uv);
110 IplImage *im = map.getIm();
112 int iu = cvRound(uv[0]*(
double)im->width);
113 int iv = cvRound(uv[1]*(
double)im->height);
116 if (iu>=im->width) iu = im->width-1;
117 if (iv>=im->height) iv = im->height-1;
118 return cvGet2D(im, iv, iu );
124 return addNormalLightMap(normal,lc,cam);
126 return addNormalCalib(normal,lc,cam);
131 static const float ones[3] = {1, 1, 1};
132 if (!isReady())
return ones;
133 return &CV_MAT_ELEM(*lightParams,
float, 2*cam, 0);
138 static const float zeroes[3] = {0, 0, 0};
139 if (!isReady())
return zeroes;
140 return &CV_MAT_ELEM(*lightParams,
float, 2*cam+1, 0);
145 if (lightParams==0)
return false;
146 assert(map.getIm()!=0);
149 float l = 1/sqrt(normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2]);
155 if (lc.
cmpWithRef(reflc, val, getGain(cam), getBias(cam)))
156 return updateLightMap(normal, val);
160 bool LightMap::updateLightMap(
float normal[3],
float *val)
162 if (val[0]<0)
return false;
164 const int nc = map.getIm()->nChannels;
166 for (
int y=0; y<map.getIm()->height; y++) {
167 float *line = (
float *)(map.getIm()->imageData + y*map.getIm()->widthStep);
169 for (
int x=0; x<map.getIm()->width; x++) {
171 float uv[2] = { float(x)/float(map.getIm()->width),
float(y)/float(map.getIm()->height) };
173 float dot = n[0]*normal[0] + n[1]*normal[1] + n[2]*normal[2];
176 dot = acos(dot)*2/
M_PI;
178 float f = (1/sqrt(2*
M_PI))*exp(-(1-dot)/(2*s*s));
179 line[x] = (1.0f-f)*line[x] + f*val;
185 float angle = (float)(acos(dot)*2/
M_PI);
190 float f = exp(-(angle)/(2*s*s));
191 for (
int c=0; c<nc; c++)
192 line[x*nc +c] = (1.0f-f)*line[x*nc + c] + f*val[c];
202 static void printShaderInfoLog(GLuint obj,
const char *str,
bool ARB)
204 GLint infologLength = 0;
205 GLint charsWritten = 0;
208 if (ARB) glGetObjectParameterivARB(obj, GL_INFO_LOG_LENGTH,&infologLength);
209 else glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infologLength);
211 if (infologLength > 0)
213 infoLog = (
char *)malloc(infologLength);
214 if (ARB) glGetInfoLogARB(obj, infologLength, &charsWritten, infoLog);
215 else glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
216 if (strlen(infoLog)>0) {
217 if (str) printf(
"%s\n", str);
218 printf(
"%s\n",infoLog);
226 static std::string readFile(
const char *
const file)
228 std::string ret =
"";
229 FILE * fp = fopen(file,
"rb");
231 fseek(fp, 0, SEEK_END);
232 int size = (int)ftell(fp);
233 fseek(fp, 0, SEEK_SET);
234 char * buf =
new char[size + 1];
235 fread(buf, size, 1, fp);
243 static bool checkErrors(
const char *file,
int line,
bool exitOnFailure=
false)
247 while ((error = glGetError()) != GL_NO_ERROR) {
248 fprintf(stderr,
"%s:%d: %s\n",
250 (
char *) gluErrorString(error));
262 if (initialized)
return true;
266 ARB = GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader;
267 if (!ARB && !glewIsSupported(
"GL_VERSION_2_0"))
269 printf(
"No GLSL support\n");
273 const char * shaderProg;
276 ret = readFile(
"myvert.glsl");
277 shaderProg = ret.c_str();
279 if (ARB) g_vertShader = glCreateShaderObjectARB(GL_VERTEX_SHADER);
280 else g_vertShader = glCreateShader(GL_VERTEX_SHADER);
281 ok = ok && checkErrors(__FILE__,__LINE__);
283 if (ARB) glShaderSourceARB(g_vertShader, 1, &shaderProg, 0);
284 else glShaderSource(g_vertShader, 1, &shaderProg, 0);
285 printShaderInfoLog(g_vertShader,
"Vertex shader myvert.glsl", ARB);
286 ok = ok && checkErrors(__FILE__,__LINE__);
288 if (ARB) glCompileShaderARB(g_vertShader);
289 else glCompileShader(g_vertShader);
291 printShaderInfoLog(g_vertShader,
"Vertex shader myvert.glsl", ARB);
292 ok = ok && checkErrors(__FILE__,__LINE__);
294 ret = readFile(
"myfrag.glsl");
295 shaderProg = ret.c_str();
296 if (ARB) g_fragShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER);
297 else g_fragShader = glCreateShader(GL_FRAGMENT_SHADER);
299 if (ARB) glShaderSourceARB(g_fragShader, 1, &shaderProg, 0);
300 else glShaderSource(g_fragShader, 1, &shaderProg, 0);
302 if (ARB) glCompileShaderARB(g_fragShader);
303 else glCompileShader(g_fragShader);
305 printShaderInfoLog(g_fragShader,
"Fragment shader myfrag.glsl", ARB);
306 ok = ok && checkErrors(__FILE__,__LINE__);
309 if (ARB) g_shaderProgram = glCreateProgramObjectARB();
310 else g_shaderProgram = glCreateProgram();
312 if (ARB) glAttachObjectARB(g_shaderProgram, g_vertShader);
313 else glAttachShader(g_shaderProgram, g_vertShader);
315 if (ARB) glAttachObjectARB(g_shaderProgram, g_fragShader);
316 else glAttachShader(g_shaderProgram, g_fragShader);
318 if (ARB) glLinkProgramARB(g_shaderProgram);
319 else glLinkProgram(g_shaderProgram);
320 ok = ok && checkErrors(__FILE__,__LINE__);
322 if (ARB) glValidateProgramARB(g_shaderProgram);
323 else glValidateProgram(g_shaderProgram);
324 ok = ok && checkErrors(__FILE__,__LINE__);
325 printShaderInfoLog(g_shaderProgram,
"glValidateProgram(g_shaderProgram)", ARB);
327 cout <<
"GLSL shaders sucessfully initialized using "
328 << (ARB ?
"ARB extensions" :
"OpenGL 2.0") <<
".\n";
330 cout <<
"Failed to initialize GLSL shaders.\n";
342 if (!initGL())
return;
344 if (ARB) glUseProgramObjectARB(g_shaderProgram);
345 else glUseProgram(g_shaderProgram);
346 if (!checkErrors(__FILE__,__LINE__)) {
347 printShaderInfoLog(g_shaderProgram,
"glUseProgram(g_shaderProgram)", ARB);
351 GLuint shaderTexture, worldToObjectNormal, gain, bias;
353 shaderTexture = glGetUniformLocationARB(g_shaderProgram,
"main_texture");
354 worldToObjectNormal = glGetUniformLocationARB(g_shaderProgram,
"worldToObjectNormal");
355 gain = glGetUniformLocationARB(g_shaderProgram,
"gain");
356 bias = glGetUniformLocationARB(g_shaderProgram,
"bias");
358 shaderTexture = glGetUniformLocation(g_shaderProgram,
"main_texture");
359 worldToObjectNormal = glGetUniformLocation(g_shaderProgram,
"worldToObjectNormal");
360 gain = glGetUniformLocation(g_shaderProgram,
"gain");
361 bias = glGetUniformLocation(g_shaderProgram,
"bias");
363 checkErrors(__FILE__,__LINE__);
365 glActiveTexture(GL_TEXTURE0 + 0);
366 glBindTexture(GL_TEXTURE_2D, shaderTexture);
367 checkErrors(__FILE__,__LINE__);
369 if (ARB) glUniform1iARB(shaderTexture, 0);
370 else glUniform1i(shaderTexture, 0);
371 checkErrors(__FILE__,__LINE__);
376 for (
int i=0; i<3; ++i)
377 for (
int j=0; j<3; ++j)
378 mat[j*3 +i] = -(
float)cvGet2D(obj2world, i, j).val[0];
381 for (
int i=0;i<lightParams->cols; i++) {
383 g[i] = 1/cvGet2D(lightParams, cam*2, i).val[0];
384 b[i] = g[i]*cvGet2D(lightParams, cam*2+1, i).val[0];
391 glUniform1iARB(shaderTexture, 0);
392 glUniformMatrix3fvARB(worldToObjectNormal, 1, GL_FALSE, mat);
393 glUniform4fARB(gain, g[2], g[1], g[0], 1);
394 glUniform4fARB(bias, b[2], b[1], b[0], 0);
396 glUniform1i(shaderTexture, 0);
397 glUniformMatrix3fv(worldToObjectNormal, 1, GL_FALSE, mat);
398 glUniform4f(gain, g[2], g[1], g[0], 1);
399 glUniform4f(bias, b[2], b[1], b[0], 0);
401 checkErrors(__FILE__,__LINE__);
403 checkErrors(__FILE__,__LINE__);
410 if (ARB) glUseProgramObjectARB(0);
411 else glUseProgram(0);
412 map.disableTexture();
421 if (normals)
delete normals;
422 normals =
new CvGrowMat(256,3, CV_32FC1);
423 normals->resize(0,3);
427 cvReleaseMat(&lightParams);
433 float l = 1/sqrt(normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2]);
442 if (lc.
avg==0 || reflc.avg==0)
return false;
446 assert(lc.
nbTri == reflc.nbTri);
448 int normIdx = normals->rows + nbCam*2;
455 for (
int i=0; i<normals->rows; i++) {
456 float *n2 = (
float *)CV_MAT_ELEM_PTR(*normals, i, 0);
457 float ndot = n2[0]*normal[0] +
463 normIdx = i + nbCam*2;
471 for (
int i=0; i<lc.
nbTri; ++i) {
472 float *rv = reflc.avg+i*reflc.avgChannels;
475 for (
int c=0; c<reflc.avgChannels; c++)
476 if (!(v[c]>5 && rv[c] >5 && v[c]<250 && rv[c] <250))
483 o.normalCol = normIdx;
485 for (
int c=0; c<reflc.avgChannels; c++) {
486 o.camVal[c] = - v[c]/255.0f;
487 o.normalVal[c] = rv[c]/255.0f;
495 normals->resize(normals->rows+1, normals->cols);
496 float *n = (
float *)CV_MAT_ELEM_PTR(*normals, normals->rows-1,0);
504 static bool saveMat(
const CvMat *m,
const char *fn)
508 if (!f.good())
return false;
510 for (
int j=0; j<m->rows; j++) {
511 for (
int i=0; i<m->cols; i++) {
512 double v = cvGet2D(m, j, i).val[0];
514 if (i+1 < m->cols) f<<
'\t';
526 if (!f.good())
return 0;
534 f.getline(line, 4095);
536 if (!f.good())
break;
541 int len = strlen(line);
543 for (
int i=0;i<len+1;i++) {
544 if (line[i]==
' ' || line[i]==
'\t' || line[i]==0) {
547 if (sscanf(last,
"%f", &val)==1) {
548 m->
resize(nrow,max(ncols, m->cols));
549 cvSet2D(m, nrow-1, ncols-1, cvScalarAll(val));
560 double LightMap::getObsMat(
int i,
int j,
int c)
562 if (j == obs[i].camCol)
return (
double)obs[i].camVal[c];
563 if (j == (obs[i].camCol+1))
return 1;
564 if (j == obs[i].normalCol)
return (
double)obs[i].normalVal[c];
568 double LightMap::getObsElem(
const vector<Observation>::iterator &it,
int i,
int c)
570 if (it->camCol == i)
return it->camVal[c];
571 if (it->camCol+1 == i)
return 1;
572 if (it->normalCol == i)
return it->normalVal[c];
576 void LightMap::computeAtA(CvMat *AtA,
int channel)
578 for (vector<Observation>::iterator it = obs.begin();
581 int idx[3] = {it->camCol, it->camCol+1, it->normalCol};
582 for (
unsigned i=0; i<3; i++) {
583 for (
unsigned j=0; j<3; j++) {
587 double v = getObsElem(it,i_, channel)*getObsElem(it,j_, channel);
589 double d = v+cvGetReal2D(AtA, i_, j_);
590 cvSetReal2D(AtA, i_, j_, d);
591 cvSetReal2D(AtA, j_, i_, d);
607 return saveMat(lightParams,lightParamsFN) &&
613 int obsMatCols=normals->rows+2*nbCam;
614 int sizes[] = {obs.size(), obsMatCols};
616 if (lightParams) cvReleaseMat(&lightParams);
617 lightParams = cvCreateMat(obsMatCols, reflc.avgChannels, CV_32FC1);
618 sizes[0] = sizes[1] = obsMatCols;
621 CvMat *AtA = cvCreateMat(obsMatCols,obsMatCols, CV_32FC1);
622 CvMat *w = cvCreateMat(obsMatCols, 1, CV_32FC1);
623 CvMat *V = cvCreateMat(obsMatCols, obsMatCols, CV_32FC1);
625 for (
int c=0; c<reflc.avgChannels; c++) {
634 cvSVD(AtA, w, 0, V, CV_SVD_MODIFY_A);
637 cvGetCol(V, &sub, V->cols-1);
638 cvGetCol(lightParams, &lpc, c);
639 cvScale(&sub, &lpc, 1.0/cvGet2D(&sub,0,0).val[0]);
654 cvSet(map.getIm(), cvScalarAll(.1));
665 buildMapFromSamples();
669 void LightMap::buildMapFromSamples()
671 for (
int i=0; i<normals->rows; ++i) {
672 updateLightMap((
float *)CV_MAT_ELEM_PTR(*normals, i, 0),
673 &CV_MAT_ELEM(*lightParams,
float, i+2*nbCam, 0));
680 if (!lp)
return false;
681 lightParams = cvCreateMat(lp->rows, lp->cols, CV_32FC1);
682 cvCopy(lp, lightParams);
683 printf(
"Loaded lightParams: %dx%d.\n", lp->rows, lp->cols);
686 int nlights = lightParams->rows - 2*nbCam;
687 if (!normals || ((normals->rows) < nlights)) {
689 printf(
"Not enough normals. Expecting %d cameras. Found %d normals and %d parameters.\n",
690 nbCam, normals->rows, lightParams->rows);
692 cvReleaseMat(&lightParams);
695 if (normals->rows > nlights)
696 normals->resize(nlights,3);
707 buildMapFromSamples();
714 IplImage *image = map.getIm();
715 if (image==0)
return false;
716 IplImage *im = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U,image->nChannels);
719 cvConvertScale(image, im, 128, 0);
720 int r = cvSaveImage(filename, im);