ImageProcessor.cpp
Go to the documentation of this file.
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 // Load and compile shaders and set parameters
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         // offsets of neighbouring pixels in texture coordinates
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; // = sqrt((3+10+3)^2 + (3+10+3)^2) = 22.6
00033         lo = 3.0f/22; 
00034         GLfloat sobelX[9] = {   -lo,    0.0f,   lo,
00035                                                         -hi,    0.0f,   hi,
00036                                                         -lo,    0.0f,   lo };
00037         // dont modify structure of sobelY -> division in sobel.frag
00038         GLfloat sobelY[9] = {    lo,    hi,     lo,
00039                                                          0.0f,  0.0f,   0.0f,
00040                                                         -lo,   -hi,         -lo };
00041         
00042         // Gauss shader
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         // Sobel shader
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         // Thinning shader
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         // Spreading shader
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 // Display list for normal images (non-rectificating TexCoords)
00091 bool ImageProcessor::dlImage(){
00092 //     float x = float(m_width)*0.5f;
00093 //     float y = float(m_height)*0.5f;
00094 //     glBegin(GL_QUADS);
00095 //              glColor3f(1.0f,1.0f,1.0f);
00096 //         glTexCoord2f(0,0); glVertex3f(-x,-y, 0.0f);
00097 //         glTexCoord2f(1,0); glVertex3f( x,-y, 0.0f);
00098 //         glTexCoord2f(1,1); glVertex3f( x, y, 0.0f);
00099 //         glTexCoord2f(0,1); glVertex3f(-x, y, 0.0f);
00100 //     glEnd();
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 // Display list for flipping image upside down
00129 bool ImageProcessor::dlFlipUpsideDown(){
00130 //     float x = float(m_width>>1);
00131 //     float y = float(m_height>>1);
00132 //     
00133 //     glBegin(GL_QUADS);
00134 //              glTexCoord2f(0.0f,1.0f); glVertex3f(-x,-y, 0.0f);
00135 //         glTexCoord2f(1.0f,1.0f); glVertex3f( x,-y, 0.0f);
00136 //         glTexCoord2f(1.0f,0.0f); glVertex3f( x, y, 0.0f);
00137 //         glTexCoord2f(0.0f,0.0f); glVertex3f(-x, y, 0.0f);
00138 //     glEnd();
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 // Display list for rectificating image (rectificating TexCoords)
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     // Lens rectificated texture coordinates
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 // Gets rectificated texture coordinates ix, iy for pixel at position i,j
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     switch (m_lensMode) {
00201     case NONE:
00202         xnew = x;
00203         ynew = y;
00204         break;
00205     case BARREL:
00206         a = -0.005f;
00207         b = 0.0f;
00208         c = 0.0f;
00209         d = 1.0f;
00210         rnew = (a*r*r*r + b*r*r + c*r + d) * r;
00211         thetanew = theta;
00212         xnew = rnew * cos(thetanew);
00213         ynew = rnew * sin(thetanew);
00214         break;
00215     }
00216     *ix = (xnew + 1)*0.5f;
00217     *iy = (ynew + 1)*0.5f;
00218     
00219     return true;
00220 }
00221 
00222 ImageProcessor::ImageProcessor(){
00223         m_shadeSobel = 0;
00224         m_shadeThinning = 0;
00225         m_shadeSpreading = 0;
00226         m_sum_init = false;
00227 }
00228 
00229 ImageProcessor::~ImageProcessor(){
00230         glDeleteLists(m_dlRect, 1);
00231         glDeleteLists(m_dlImage, 1);
00232         glDeleteLists(m_dlUpsideDown, 1);
00233         if(m_sum_init){
00234                 glDeleteFramebuffers(1, &fbo);
00235                 glDeleteTextures(1,&fbo_tex);
00236                 glDeleteTextures(1,&fbo_tex_depth);
00237         }
00238 }
00239 
00240 // Set functions
00241 void ImageProcessor::setCamOrtho(){ 
00242         m_cam_ortho.Activate();
00243 }
00244 
00245 // *** Image Processing functions ***
00246 void ImageProcessor::flipUpsideDown(Texture* source, Texture* result){
00247         m_cam_ortho.Activate();
00248         glEnable(GL_TEXTURE_2D);
00249                 source->bind();
00250                 glCallList(m_dlUpsideDown);
00251                 result->copyTexImage2D(source->getWidth(), source->getHeight());
00252         glDisable(GL_TEXTURE_2D);
00253 }
00254 
00255 void ImageProcessor::copy(Texture* source, Texture* result){
00256         m_cam_ortho.Activate();
00257         glEnable(GL_TEXTURE_2D);
00258                 source->bind();
00259                 glCallList(m_dlImage);
00260         result->copyTexImage2D(source->getWidth(), source->getHeight());
00261     glDisable(GL_TEXTURE_2D);
00262 }
00263 
00264 void ImageProcessor::rectification(Texture* source, Texture* result){
00265         m_cam_ortho.Activate();
00266         glEnable(GL_TEXTURE_2D);
00267                 source->bind();
00268                 glCallList(m_dlRect);
00269         result->copyTexImage2D(source->getWidth(), source->getHeight());
00270     glDisable(GL_TEXTURE_2D);
00271 }
00272 
00273 void ImageProcessor::gauss(Texture* source, Texture* result){
00274         m_cam_ortho.Activate();
00275         m_shadeGauss->bind();
00276     glEnable(GL_TEXTURE_2D);
00277                 source->bind();
00278                 glCallList(m_dlImage);
00279         result->copyTexImage2D(source->getWidth(), source->getHeight());
00280     glDisable(GL_TEXTURE_2D);
00281     m_shadeGauss->unbind();
00282 }
00283 
00284 void ImageProcessor::sobel(Texture* source, Texture* result, float threshold, bool normalise, bool binary){
00285         m_cam_ortho.Activate();
00286         m_shadeSobel->bind();
00287         m_shadeSobel->setUniform( "fThreshold", threshold );
00288         m_shadeSobel->setUniform( "norm", normalise);
00289         m_shadeSobel->setUniform( "binary", binary);
00290     glEnable(GL_TEXTURE_2D);
00291                 source->bind();
00292                 glCallList(m_dlImage);
00293         result->copyTexImage2D(source->getWidth(), source->getHeight());
00294     glDisable(GL_TEXTURE_2D);
00295   m_shadeSobel->unbind();
00296 }
00297 
00298 void ImageProcessor::sobel(Texture* source, Texture* result, Texture* mask, float threshold, bool normalise, bool binary){
00299         m_cam_ortho.Activate();
00300         m_shadeSobel->bind();
00301         m_shadeSobel->setUniform( "fThreshold", threshold );
00302         m_shadeSobel->setUniform( "norm", normalise);
00303         m_shadeSobel->setUniform( "masked", true);
00304         m_shadeSobel->setUniform( "binary", binary);
00305     glEnable(GL_TEXTURE_2D);
00306                 source->bind(0);
00307                 mask->bind(1);
00308                 glCallList(m_dlImage);
00309         result->copyTexImage2D(source->getWidth(), source->getHeight());
00310     glDisable(GL_TEXTURE_2D);
00311   m_shadeSobel->unbind();
00312   m_shadeSobel->setUniform( "masked", false);
00313 }
00314 
00315 void ImageProcessor::thinning(Texture* source, Texture* result){
00316         m_cam_ortho.Activate();
00317         glEnable(GL_TEXTURE_2D);
00318                 source->bind();
00319                 m_shadeThinning->bind();
00320                         glCallList(m_dlImage);
00321                 m_shadeThinning->unbind();
00322                 result->copyTexImage2D(source->getWidth(), source->getHeight());
00323     glDisable(GL_TEXTURE_2D);
00324 }
00325 
00326 void ImageProcessor::thinning(Texture* source, Texture* result, Texture* mask){
00327         m_cam_ortho.Activate();
00328         m_shadeThinning->bind();
00329         m_shadeThinning->setUniform( "masked", true);
00330         glEnable(GL_TEXTURE_2D);
00331                 source->bind(0);
00332                 mask->bind(1);
00333                 glCallList(m_dlImage);
00334                 result->copyTexImage2D(source->getWidth(), source->getHeight());
00335     glDisable(GL_TEXTURE_2D);
00336         m_shadeThinning->setUniform( "masked", false);
00337         m_shadeThinning->unbind();
00338 }
00339 
00340 void ImageProcessor::spreading(Texture* source, Texture* result){
00341         m_cam_ortho.Activate();
00342         glEnable(GL_TEXTURE_2D);
00343                 source->bind();
00344                 m_shadeSpreading->bind();
00345                 glCallList(m_dlImage);
00346                 m_shadeSpreading->unbind();
00347                 result->copyTexImage2D(source->getWidth(), source->getHeight());
00348     glDisable(GL_TEXTURE_2D);;
00349 }
00350 
00351 void ImageProcessor::render(Texture* tex){
00352         m_cam_ortho.Activate();
00353         glEnable(GL_TEXTURE_2D);
00354                 tex->bind();
00355                 glCallList(m_dlImage);
00356         glDisable(GL_TEXTURE_2D);
00357 }
00358 
00359 void ImageProcessor::render(Texture* tex, int x, int y, unsigned w, unsigned h){
00360         m_cam_ortho.Activate();
00361         glEnable(GL_TEXTURE_2D);
00362                 tex->bind();
00363                 dlImage((float)x, (float)y, (float)w, (float)h);
00364         glDisable(GL_TEXTURE_2D);
00365 }
00366 
00367 GLenum ImageProcessor::avgInit(int res)
00368 {
00369         if(res < 16)
00370                 ROS_DEBUG("[ImageProcessor::avgInit] Warning: resolution too low\n"); // doesn't make sense computing low number of sums on GPU
00371         
00372         bool res_valid = false;
00373         for(unsigned i=4; i<13; i++)
00374                 if(res == pow(2,i))
00375                         res_valid = true;
00376         
00377         if(!res_valid)
00378                 ROS_DEBUG("[ImageProcessor::avgInit] Warning: resolution must be power of 2 and in the range of 16 to 4048\n");
00379         
00380         fbo_res = res;
00381         
00382         
00383         glGenTextures(1, &fbo_tex_depth);
00384         glBindTexture(GL_TEXTURE_2D, fbo_tex_depth);
00385         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00386         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 
00387         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00388         glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // for attaching to fbo texture must be mipmap complete
00389 //      glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, fbo_res, fbo_res, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
00390         
00391         // Texture (=memory) for fbo
00392         glGenTextures(1, &fbo_tex);
00393         glBindTexture(GL_TEXTURE_2D, fbo_tex);
00394         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00395         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 
00396         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00397         glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // for attaching to fbo texture must be mipmap complete
00398         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, fbo_res, fbo_res, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
00399         
00400         
00401         // fbo = framebuffer object
00402         glGenFramebuffers(1,&fbo);
00403         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
00404         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo_tex, 0);
00405 //      glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, fbo_tex_depth, 0);
00406         
00407         m_cam_ortho_fbo.Set(    0.0f, 0.0f, 1.0f,
00408                                                         0.0f, 0.0f, 0.0f,
00409                                                         0.0f, 1.0f, 0.0f,
00410                                                         45.0f, fbo_res, fbo_res,
00411                                                         0.0f, 1.0f,
00412                                                         GL_ORTHO);
00413 
00414         glBindFramebuffer(GL_FRAMEBUFFER, 0);
00415         
00416         fbo_stage = ilog2(fbo_res);
00417         m_sum_init = true;
00418         
00419         tgCheckFBError(GL_FRAMEBUFFER, "ImageProcessor::avgInit()");
00420         return tgCheckError("ImageProcessor::avgInit()");
00421 }
00422 
00423 void ImageProcessor::avgActivate(){
00424         if(m_sum_init){
00425                 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
00426                 tgCheckError("ImageProcessor::avgActivate() A");
00427                 glClearColor(0,0,0,0);
00428                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00429                 tgCheckError("ImageProcessor::avgActivate() B");
00430         }
00431 }
00432 
00433 void ImageProcessor::avgGet(float *avg, int lvl){
00434         if(m_sum_init){
00435                 if(lvl==0){
00436                         // for some reason glGetTexImage doesen't get the value of the very last mipmap stage
00437 //                      float tmp[16];
00438 //                      glBindTexture(GL_TEXTURE_2D, fbo_tex);
00439 //                      glGenerateMipmap(GL_TEXTURE_2D);
00440 //                      glGetTexImage(GL_TEXTURE_2D, fbo_stage-1, GL_RGBA, GL_FLOAT, tmp);
00441 //                      avg[0] = 0;
00442 //                      for(unsigned i=0; i<4; i++)
00443 //                              avg[0] += 0.25 * tmp[i];
00444                         ROS_DEBUG("[ImageProcessor::avgGet] Warning: not implemented\n");
00445                 }else{
00446                         glBindTexture(GL_TEXTURE_2D, fbo_tex);
00447 //                      glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16,0, 0, fbo_res,fbo_res,0);
00448                         glGenerateMipmap(GL_TEXTURE_2D);
00449                         glGetTexImage(GL_TEXTURE_2D, fbo_stage-lvl, GL_RED, GL_FLOAT, avg);
00450                         tgCheckError("ImageProcessor::avgGet()");
00451                 }
00452         }
00453 }
00454 
00455 void ImageProcessor::avgDeactivate(){
00456         if(m_sum_init){
00457                 glBindFramebuffer(GL_FRAMEBUFFER, 0);
00458         }
00459 }
00460 
00461 // Main initialisation function
00462 bool ImageProcessor::init(unsigned w, unsigned h){
00463     
00464         m_width = w;
00465         m_height = h;
00466         
00467         // Initialise camera
00468         m_cam_ortho.Set(        0.0f, 0.0f, 1.0f,
00469                                                 0.0f, 0.0f, 0.0f,
00470                                                 0.0f, 1.0f, 0.0f,
00471                                                 45.0f, w, h,
00472                                                 0.1f, 10.0f,
00473                                                 GL_ORTHO);
00474         
00475         // Initialize shaders
00476         if(!initShader())
00477                 return false;
00478     
00479     
00480         // Setup display lists
00481         m_dlRect = glGenLists(1);
00482         m_lensMode = BARREL;
00483         glNewList(m_dlRect, GL_COMPILE);
00484         dlRectification();
00485         glEndList();
00486         
00487         m_dlImage = glGenLists(1);
00488         glNewList(m_dlImage, GL_COMPILE);
00489         dlImage();
00490         glEndList();
00491         
00492         m_dlUpsideDown = glGenLists(1);
00493         glNewList(m_dlUpsideDown, GL_COMPILE);
00494                 dlFlipUpsideDown();
00495         glEndList();
00496         
00497         return true;
00498 }
00499 
00500 


blort
Author(s): Michael Zillich, Thomas Mörwald, Johann Prankl, Andreas Richtsfeld, Bence Magyar (ROS version)
autogenerated on Thu Jan 2 2014 11:38:25