00001 #include <ros/console.h>
00002
00003 #include <blort/Tracker/ImageProcessor.h>
00004 #include <blort/TomGine/tgError.h>
00005
00006 using namespace Tracking;
00007
00008
00009
00010 bool ImageProcessor::initShader(){
00011 int id;
00012 float w = (float)m_width;
00013 float h = (float)m_height;
00014 float hi,lo;
00015 float sq2 = 1.0f/sqrt(2.0f);
00016
00017
00018 GLfloat offX[9] = { -1.0f/w, 0.0, 1.0f/w,
00019 -1.0f/w, 0.0, 1.0f/w,
00020 -1.0f/w, 0.0, 1.0f/w };
00021 GLfloat offY[9] = { 1.0f/h, 1.0f/h, 1.0f/h,
00022 0.0, 0.0, 0.0,
00023 -1.0f/h,-1.0f/h, -1.0f/h };
00024 GLfloat dist[9] = { sq2, 1.0f, sq2,
00025 1.0f, 0.0f, 1.0f,
00026 sq2, 1.0f, sq2 };
00027 GLfloat kernel[25] = { 2, 4, 5, 4, 2,
00028 4, 9, 12, 9, 4,
00029 5, 12, 15, 12, 5,
00030 4, 9, 12, 9, 4,
00031 2, 4, 5, 4, 2 };
00032 hi = 10.0f/22;
00033 lo = 3.0f/22;
00034 GLfloat sobelX[9] = { -lo, 0.0f, lo,
00035 -hi, 0.0f, hi,
00036 -lo, 0.0f, lo };
00037
00038 GLfloat sobelY[9] = { lo, hi, lo,
00039 0.0f, 0.0f, 0.0f,
00040 -lo, -hi, -lo };
00041
00042
00043 id = g_Resources->AddShader("gauss", NULL, "gauss.frag");
00044 m_shadeGauss = g_Resources->GetShader(id);
00045 m_shadeGauss->bind();
00046 m_shadeGauss->setUniform( "kernel", 25, kernel );
00047 m_shadeGauss->setUniform( "width", w);
00048 m_shadeGauss->setUniform( "height", h);
00049 m_shadeGauss->unbind();
00050
00051
00052 id = g_Resources->AddShader("sobel", NULL, "sobel.frag");
00053 m_shadeSobel = g_Resources->GetShader(id);
00054 m_shadeSobel->bind();
00055 m_shadeSobel->setUniform( "frame", 0 );
00056 m_shadeSobel->setUniform( "mask", 1);
00057 m_shadeSobel->setUniform( "binary", false);
00058 m_shadeSobel->setUniform( "mOffsetX", mat3(offX), GL_FALSE );
00059 m_shadeSobel->setUniform( "mOffsetY", mat3(offY), GL_FALSE );
00060 m_shadeSobel->setUniform( "mSobelX", mat3(sobelX), GL_FALSE );
00061 m_shadeSobel->setUniform( "mSobelY", mat3(sobelY), GL_FALSE );
00062 m_shadeSobel->setUniform( "fThreshold", 0.01f );
00063 m_shadeSobel->unbind();
00064
00065
00066 id = g_Resources->AddShader("thinning", NULL, "thinning.frag");
00067 m_shadeThinning = g_Resources->GetShader(id);
00068 m_shadeThinning->bind();
00069 m_shadeThinning->setUniform( "frame", 0 );
00070 m_shadeThinning->setUniform( "mask", 1);
00071 m_shadeThinning->setUniform( "mOffsetX", mat3(offX), GL_FALSE );
00072 m_shadeThinning->setUniform( "mOffsetY", mat3(offY), GL_FALSE );
00073 m_shadeThinning->setUniform( "fThreshold", 0.0f );
00074 m_shadeThinning->unbind();
00075
00076
00077 id = g_Resources->AddShader("spreading", NULL, "spreading.frag");
00078 m_shadeSpreading = g_Resources->GetShader(id);
00079 m_shadeSpreading->bind();
00080 m_shadeSpreading->setUniform( "mOffsetX", mat3(offX), GL_FALSE );
00081 m_shadeSpreading->setUniform( "mOffsetY", mat3(offY), GL_FALSE );
00082 m_shadeSpreading->setUniform( "mDistance", mat3(dist), GL_FALSE );
00083 m_shadeSpreading->setUniform( "fThreshold", 0.01f );
00084 m_shadeSpreading->setUniform( "fDistScale", 0.5f );
00085 m_shadeSpreading->unbind();
00086
00087 return true;
00088 }
00089
00090
00091 bool ImageProcessor::dlImage(){
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 float x = float(m_width);
00103 float y = float(m_height);
00104 glBegin(GL_QUADS);
00105 glColor3f(1.0f,1.0f,1.0f);
00106 glTexCoord2f(0,0); glVertex3f( 0, 0, 0.0f);
00107 glTexCoord2f(1,0); glVertex3f( x, 0, 0.0f);
00108 glTexCoord2f(1,1); glVertex3f( x, y, 0.0f);
00109 glTexCoord2f(0,1); glVertex3f( 0, y, 0.0f);
00110 glEnd();
00111
00112 return true;
00113 }
00114
00115 bool ImageProcessor::dlImage(float x, float y, float w, float h){
00116
00117 glBegin(GL_QUADS);
00118 glColor3f(1.0f,1.0f,1.0f);
00119 glTexCoord2f(0.0f,0.0f); glVertex3f(x, y, 0.0f);
00120 glTexCoord2f(1.0f,0.0f); glVertex3f(x+w, y, 0.0f);
00121 glTexCoord2f(1.0f,1.0f); glVertex3f(x+w, y+h, 0.0f);
00122 glTexCoord2f(0.0f,1.0f); glVertex3f(x, y+h, 0.0f);
00123 glEnd();
00124
00125 return true;
00126 }
00127
00128
00129 bool ImageProcessor::dlFlipUpsideDown(){
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 float x = float(m_width);
00141 float y = float(m_height);
00142
00143 glBegin(GL_QUADS);
00144 glTexCoord2f(0.0f,1.0f); glVertex3f( 0, 0, 0.0f);
00145 glTexCoord2f(1.0f,1.0f); glVertex3f( x, 0, 0.0f);
00146 glTexCoord2f(1.0f,0.0f); glVertex3f( x, y, 0.0f);
00147 glTexCoord2f(0.0f,0.0f); glVertex3f( 0, y, 0.0f);
00148 glEnd();
00149
00150 return true;
00151 }
00152
00153
00154 bool ImageProcessor::dlRectification(){
00155 unsigned i,j,n=10;
00156 float x,y;
00157 unsigned w2 = m_width >> 1;
00158 unsigned h2 = m_height >> 1;
00159
00160
00161 glBegin(GL_QUADS);
00162 for (i=0;i<w2;i+=n) {
00163 for (j=0;j<h2;j+=n) {
00164 float fi = float(i);
00165 float fj = float(j);
00166 transform(fi,fj,&x,&y);
00167 glTexCoord2f(x,y);
00168 glVertex3f(fi-w2,fj-h2,0.0f);
00169
00170 transform(fi+n,fj,&x,&y);
00171 glTexCoord2f(x,y);
00172 glVertex3f((fi+n)-w2,fj-h2,0.0f);
00173
00174 transform(fi+n,fj+n,&x,&y);
00175 glTexCoord2f(x,y);
00176 glVertex3f((fi+n)-w2,(fj+n)-h2,0.0f);
00177
00178 transform(fi,fj+n,&x,&y);
00179 glTexCoord2f(x,y);
00180 glVertex3f(fi-w2,(fj+n)-h2,0.0f);
00181 }
00182 }
00183 glEnd();
00184 return true;
00185 }
00186
00187
00188 bool ImageProcessor::transform(float i, float j, float *ix, float *iy){
00189 float a,b,c,d;
00190 float x,y,xnew,ynew;
00191 float r,theta,rnew,thetanew;
00192 int w = m_width;
00193 int h = m_height;
00194
00195 x = i / (w*0.5f) - 1;
00196 y = j / (h*0.5f) - 1;
00197 r = sqrt(x*x+y*y);
00198 theta = atan2(y,x);
00199
00200 xnew = x;
00201 ynew = y;
00202 switch (m_lensMode) {
00203 case NONE:
00204 xnew = x;
00205 ynew = y;
00206 break;
00207 case BARREL:
00208 a = -0.005f;
00209 b = 0.0f;
00210 c = 0.0f;
00211 d = 1.0f;
00212 rnew = (a*r*r*r + b*r*r + c*r + d) * r;
00213 thetanew = theta;
00214 xnew = rnew * cos(thetanew);
00215 ynew = rnew * sin(thetanew);
00216 break;
00217 }
00218 *ix = (xnew + 1)*0.5f;
00219 *iy = (ynew + 1)*0.5f;
00220
00221 return true;
00222 }
00223
00224 ImageProcessor::ImageProcessor(){
00225 m_shadeSobel = 0;
00226 m_shadeThinning = 0;
00227 m_shadeSpreading = 0;
00228 m_sum_init = false;
00229 }
00230
00231 ImageProcessor::~ImageProcessor(){
00232 glDeleteLists(m_dlRect, 1);
00233 glDeleteLists(m_dlImage, 1);
00234 glDeleteLists(m_dlUpsideDown, 1);
00235 if(m_sum_init){
00236 glDeleteFramebuffers(1, &fbo);
00237 glDeleteTextures(1,&fbo_tex);
00238 glDeleteTextures(1,&fbo_tex_depth);
00239 }
00240 }
00241
00242
00243 void ImageProcessor::setCamOrtho(){
00244 m_cam_ortho.Activate();
00245 }
00246
00247
00248 void ImageProcessor::flipUpsideDown(Texture* source, Texture* result){
00249 m_cam_ortho.Activate();
00250 glEnable(GL_TEXTURE_2D);
00251 source->bind();
00252 glCallList(m_dlUpsideDown);
00253 result->copyTexImage2D(source->getWidth(), source->getHeight());
00254 glDisable(GL_TEXTURE_2D);
00255 }
00256
00257 void ImageProcessor::copy(Texture* source, Texture* result){
00258 m_cam_ortho.Activate();
00259 glEnable(GL_TEXTURE_2D);
00260 source->bind();
00261 glCallList(m_dlImage);
00262 result->copyTexImage2D(source->getWidth(), source->getHeight());
00263 glDisable(GL_TEXTURE_2D);
00264 }
00265
00266 void ImageProcessor::rectification(Texture* source, Texture* result){
00267 m_cam_ortho.Activate();
00268 glEnable(GL_TEXTURE_2D);
00269 source->bind();
00270 glCallList(m_dlRect);
00271 result->copyTexImage2D(source->getWidth(), source->getHeight());
00272 glDisable(GL_TEXTURE_2D);
00273 }
00274
00275 void ImageProcessor::gauss(Texture* source, Texture* result){
00276 m_cam_ortho.Activate();
00277 m_shadeGauss->bind();
00278 glEnable(GL_TEXTURE_2D);
00279 source->bind();
00280 glCallList(m_dlImage);
00281 result->copyTexImage2D(source->getWidth(), source->getHeight());
00282 glDisable(GL_TEXTURE_2D);
00283 m_shadeGauss->unbind();
00284 }
00285
00286 void ImageProcessor::sobel(Texture* source, Texture* result, float threshold, bool normalise, bool binary){
00287 m_cam_ortho.Activate();
00288 m_shadeSobel->bind();
00289 m_shadeSobel->setUniform( "fThreshold", threshold );
00290 m_shadeSobel->setUniform( "norm", normalise);
00291 m_shadeSobel->setUniform( "binary", binary);
00292 glEnable(GL_TEXTURE_2D);
00293 source->bind();
00294 glCallList(m_dlImage);
00295 result->copyTexImage2D(source->getWidth(), source->getHeight());
00296 glDisable(GL_TEXTURE_2D);
00297 m_shadeSobel->unbind();
00298 }
00299
00300 void ImageProcessor::sobel(Texture* source, Texture* result, Texture* mask, float threshold, bool normalise, bool binary){
00301 m_cam_ortho.Activate();
00302 m_shadeSobel->bind();
00303 m_shadeSobel->setUniform( "fThreshold", threshold );
00304 m_shadeSobel->setUniform( "norm", normalise);
00305 m_shadeSobel->setUniform( "masked", true);
00306 m_shadeSobel->setUniform( "binary", binary);
00307 glEnable(GL_TEXTURE_2D);
00308 source->bind(0);
00309 mask->bind(1);
00310 glCallList(m_dlImage);
00311 result->copyTexImage2D(source->getWidth(), source->getHeight());
00312 glDisable(GL_TEXTURE_2D);
00313 m_shadeSobel->unbind();
00314 m_shadeSobel->setUniform( "masked", false);
00315 }
00316
00317 void ImageProcessor::thinning(Texture* source, Texture* result){
00318 m_cam_ortho.Activate();
00319 glEnable(GL_TEXTURE_2D);
00320 source->bind();
00321 m_shadeThinning->bind();
00322 glCallList(m_dlImage);
00323 m_shadeThinning->unbind();
00324 result->copyTexImage2D(source->getWidth(), source->getHeight());
00325 glDisable(GL_TEXTURE_2D);
00326 }
00327
00328 void ImageProcessor::thinning(Texture* source, Texture* result, Texture* mask){
00329 m_cam_ortho.Activate();
00330 m_shadeThinning->bind();
00331 m_shadeThinning->setUniform( "masked", true);
00332 glEnable(GL_TEXTURE_2D);
00333 source->bind(0);
00334 mask->bind(1);
00335 glCallList(m_dlImage);
00336 result->copyTexImage2D(source->getWidth(), source->getHeight());
00337 glDisable(GL_TEXTURE_2D);
00338 m_shadeThinning->setUniform( "masked", false);
00339 m_shadeThinning->unbind();
00340 }
00341
00342 void ImageProcessor::spreading(Texture* source, Texture* result){
00343 m_cam_ortho.Activate();
00344 glEnable(GL_TEXTURE_2D);
00345 source->bind();
00346 m_shadeSpreading->bind();
00347 glCallList(m_dlImage);
00348 m_shadeSpreading->unbind();
00349 result->copyTexImage2D(source->getWidth(), source->getHeight());
00350 glDisable(GL_TEXTURE_2D);;
00351 }
00352
00353 void ImageProcessor::render(Texture* tex){
00354 m_cam_ortho.Activate();
00355 glEnable(GL_TEXTURE_2D);
00356 tex->bind();
00357 glCallList(m_dlImage);
00358 glDisable(GL_TEXTURE_2D);
00359 }
00360
00361 void ImageProcessor::render(Texture* tex, int x, int y, unsigned w, unsigned h){
00362 m_cam_ortho.Activate();
00363 glEnable(GL_TEXTURE_2D);
00364 tex->bind();
00365 dlImage((float)x, (float)y, (float)w, (float)h);
00366 glDisable(GL_TEXTURE_2D);
00367 }
00368
00369 GLenum ImageProcessor::avgInit(int res)
00370 {
00371 if(res < 16)
00372 ROS_DEBUG("[ImageProcessor::avgInit] Warning: resolution too low\n");
00373
00374 bool res_valid = false;
00375 for(unsigned i=4; i<13; i++)
00376 if(res == pow(2,i))
00377 res_valid = true;
00378
00379 if(!res_valid)
00380 ROS_DEBUG("[ImageProcessor::avgInit] Warning: resolution must be power of 2 and in the range of 16 to 4048\n");
00381
00382 fbo_res = res;
00383
00384
00385 glGenTextures(1, &fbo_tex_depth);
00386 glBindTexture(GL_TEXTURE_2D, fbo_tex_depth);
00387 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00388 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00389 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00390 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
00391
00392
00393
00394 glGenTextures(1, &fbo_tex);
00395 glBindTexture(GL_TEXTURE_2D, fbo_tex);
00396 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00397 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00398 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00399 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
00400 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, fbo_res, fbo_res, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
00401
00402
00403
00404 glGenFramebuffers(1,&fbo);
00405 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
00406 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo_tex, 0);
00407
00408
00409 m_cam_ortho_fbo.Set( 0.0f, 0.0f, 1.0f,
00410 0.0f, 0.0f, 0.0f,
00411 0.0f, 1.0f, 0.0f,
00412 45.0f, fbo_res, fbo_res,
00413 0.0f, 1.0f,
00414 GL_ORTHO);
00415
00416 glBindFramebuffer(GL_FRAMEBUFFER, 0);
00417
00418 fbo_stage = ilog2(fbo_res);
00419 m_sum_init = true;
00420
00421 tgCheckFBError(GL_FRAMEBUFFER, "ImageProcessor::avgInit()");
00422 return tgCheckError("ImageProcessor::avgInit()");
00423 }
00424
00425 void ImageProcessor::avgActivate(){
00426 if(m_sum_init){
00427 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
00428 tgCheckError("ImageProcessor::avgActivate() A");
00429 glClearColor(0,0,0,0);
00430 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00431 tgCheckError("ImageProcessor::avgActivate() B");
00432 }
00433 }
00434
00435 void ImageProcessor::avgGet(float *avg, int lvl){
00436 if(m_sum_init){
00437 if(lvl==0){
00438
00439
00440
00441
00442
00443
00444
00445
00446 ROS_DEBUG("[ImageProcessor::avgGet] Warning: not implemented\n");
00447 }else{
00448 glBindTexture(GL_TEXTURE_2D, fbo_tex);
00449
00450 glGenerateMipmap(GL_TEXTURE_2D);
00451 glGetTexImage(GL_TEXTURE_2D, fbo_stage-lvl, GL_RED, GL_FLOAT, avg);
00452 tgCheckError("ImageProcessor::avgGet()");
00453 }
00454 }
00455 }
00456
00457 void ImageProcessor::avgDeactivate(){
00458 if(m_sum_init){
00459 glBindFramebuffer(GL_FRAMEBUFFER, 0);
00460 }
00461 }
00462
00463
00464 bool ImageProcessor::init(unsigned w, unsigned h){
00465
00466 m_width = w;
00467 m_height = h;
00468
00469
00470 m_cam_ortho.Set( 0.0f, 0.0f, 1.0f,
00471 0.0f, 0.0f, 0.0f,
00472 0.0f, 1.0f, 0.0f,
00473 45.0f, w, h,
00474 0.1f, 10.0f,
00475 GL_ORTHO);
00476
00477
00478 if(!initShader())
00479 return false;
00480
00481
00482
00483 m_dlRect = glGenLists(1);
00484 m_lensMode = BARREL;
00485 glNewList(m_dlRect, GL_COMPILE);
00486 dlRectification();
00487 glEndList();
00488
00489 m_dlImage = glGenLists(1);
00490 glNewList(m_dlImage, GL_COMPILE);
00491 dlImage();
00492 glEndList();
00493
00494 m_dlUpsideDown = glGenLists(1);
00495 glNewList(m_dlUpsideDown, GL_COMPILE);
00496 dlFlipUpsideDown();
00497 glEndList();
00498
00499 return true;
00500 }
00501
00502