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     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 // Set functions
00243 void ImageProcessor::setCamOrtho(){ 
00244         m_cam_ortho.Activate();
00245 }
00246 
00247 // *** Image Processing functions ***
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"); // doesn't make sense computing low number of sums on GPU
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); // for attaching to fbo texture must be mipmap complete
00391 //      glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, fbo_res, fbo_res, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
00392         
00393         // Texture (=memory) for fbo
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); // for attaching to fbo texture must be mipmap complete
00400         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, fbo_res, fbo_res, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
00401         
00402         
00403         // fbo = framebuffer object
00404         glGenFramebuffers(1,&fbo);
00405         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
00406         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo_tex, 0);
00407 //      glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, fbo_tex_depth, 0);
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                         // for some reason glGetTexImage doesen't get the value of the very last mipmap stage
00439 //                      float tmp[16];
00440 //                      glBindTexture(GL_TEXTURE_2D, fbo_tex);
00441 //                      glGenerateMipmap(GL_TEXTURE_2D);
00442 //                      glGetTexImage(GL_TEXTURE_2D, fbo_stage-1, GL_RGBA, GL_FLOAT, tmp);
00443 //                      avg[0] = 0;
00444 //                      for(unsigned i=0; i<4; i++)
00445 //                              avg[0] += 0.25 * tmp[i];
00446                         ROS_DEBUG("[ImageProcessor::avgGet] Warning: not implemented\n");
00447                 }else{
00448                         glBindTexture(GL_TEXTURE_2D, fbo_tex);
00449 //                      glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16,0, 0, fbo_res,fbo_res,0);
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 // Main initialisation function
00464 bool ImageProcessor::init(unsigned w, unsigned h){
00465     
00466         m_width = w;
00467         m_height = h;
00468         
00469         // Initialise camera
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         // Initialize shaders
00478         if(!initShader())
00479                 return false;
00480     
00481     
00482         // Setup display lists
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 


blort
Author(s): Thomas Mörwald , Michael Zillich , Andreas Richtsfeld , Johann Prankl , Markus Vincze , Bence Magyar
autogenerated on Wed Aug 26 2015 15:24:12