tgImageProcessor.cpp
Go to the documentation of this file.
00001 
00002 #include <blort/TomGine/tgImageProcessor.h>
00003 #include <blort/TomGine/tgError.h>
00004 #include <stdexcept>
00005 
00006 using namespace TomGine;
00007 
00008 tgImageProcessor::tgImageProcessor(     const char *gauss_frag_file,
00009                                                                         const char *sobel_frag_file,
00010                                                                         const char *thinning_frag_file,
00011                                                                         const char *spreading_frag_file,
00012                                                                         unsigned img_width, unsigned img_height,
00013                                                                         int avg_resolution)
00014 {
00015         m_shadeGauss = new tgShader(NULL, gauss_frag_file, NULL);
00016         m_shadeSobel = new tgShader(NULL, sobel_frag_file, NULL);
00017         m_shadeThinning = new tgShader(NULL, thinning_frag_file, NULL);
00018         m_shadeSpreading = new tgShader(NULL, spreading_frag_file, NULL);
00019         
00020         init(img_width, img_height);
00021         initShader((float)img_width, (float)img_height);
00022         initFBO(avg_resolution);
00023         tgCheckError("[tgImageProcessor::tgImageProcessor()]");
00024 }
00025 
00026 tgImageProcessor::~tgImageProcessor(){
00027         if(glIsFramebuffer(fbo)) glDeleteFramebuffers(1, &fbo);
00028         if(glIsTexture(fbo_tex)) glDeleteTextures(1,&fbo_tex);
00029         if(glIsTexture(fbo_tex_depth)) glDeleteTextures(1,&fbo_tex_depth);
00030 
00031         if(m_shadeGauss) delete(m_shadeGauss);
00032         if(m_shadeSobel) delete(m_shadeSobel);
00033         if(m_shadeThinning) delete(m_shadeThinning);
00034         if(m_shadeSpreading) delete(m_shadeSpreading);
00035 }
00036 
00037 // Main initialisation function
00038 void tgImageProcessor::init(unsigned width, unsigned height){
00039     
00040         m_width = width;
00041         m_height = height;
00042 
00043         // Initialise camera
00044         m_cam_ortho.Set(        0.0f, 0.0f, 1.0f,
00045                                                 0.0f, 0.0f, 0.0f,
00046                                                 0.0f, 1.0f, 0.0f,
00047                                                 45.0f, m_width, m_height,
00048                                                 0.1f, 10.0f,
00049                                                 GL_ORTHO);
00050 }
00051 
00052 // Load and compile shaders and set parameters
00053 void tgImageProcessor::initShader(float w, float h){
00054         float sq2 = 1.0f/sqrt(2.0f);
00055         
00056         // offsets of neighbouring pixels in texture coordinates
00057         GLfloat offX[9] = { -1.0f/w, 0.0, 1.0f/w,
00058                                                 -1.0f/w, 0.0, 1.0f/w,
00059                                                 -1.0f/w, 0.0, 1.0f/w };
00060         GLfloat offY[9] = {  1.0f/h, 1.0f/h,  1.0f/h,
00061                                                  0.0,   0.0,    0.0,
00062                                                 -1.0f/h,-1.0f/h, -1.0f/h };
00063         
00064         // distance of neighbouring pixels
00065         GLfloat dist[9] = { sq2, 1.0f, sq2,
00066                                                 1.0f, 0.0f, 1.0f,
00067                                                 sq2, 1.0f, sq2 };
00068         GLfloat kernel[25] = {  2,  4,  5,  4, 2,
00069                                                         4,  9, 12,  9, 4,
00070                                                         5, 12, 15, 12, 5,
00071                                                         4,  9, 12,  9, 4,
00072                                                         2,  4,  5,  4, 2 };
00073         float hi = 10.0f/22; // = sqrt((3+10+3)^2 + (3+10+3)^2) = 22.6
00074         float lo = 3.0f/22; 
00075         GLfloat sobelX[9] = {   -lo,    0.0f,   lo,
00076                                                         -hi,    0.0f,   hi,
00077                                                         -lo,    0.0f,   lo };
00078         // dont modify structure of sobelY -> division in sobel.frag
00079         GLfloat sobelY[9] = {    lo,    hi,     lo,
00080                                                          0.0f,  0.0f,   0.0f,
00081                                                         -lo,   -hi,         -lo };
00082         
00083         // Gauss shader
00084         m_shadeGauss->bind();
00085         m_shadeGauss->setUniform( "kernel", 25, kernel );
00086         m_shadeGauss->setUniform( "width", w);
00087         m_shadeGauss->setUniform( "height", h);
00088         m_shadeGauss->unbind();
00089         
00090         // Sobel shader
00091         m_shadeSobel->bind();
00092         m_shadeSobel->setUniform( "frame", 0 );
00093         m_shadeSobel->setUniform( "mask", 1);
00094         m_shadeSobel->setUniform( "binary", false);
00095         m_shadeSobel->setUniform( "mOffsetX", mat3(offX), GL_FALSE );
00096         m_shadeSobel->setUniform( "mOffsetY", mat3(offY), GL_FALSE );
00097         m_shadeSobel->setUniform( "mSobelX", mat3(sobelX), GL_FALSE );
00098         m_shadeSobel->setUniform( "mSobelY", mat3(sobelY), GL_FALSE );
00099         m_shadeSobel->setUniform( "fThreshold", 0.1f );
00100         m_shadeSobel->unbind();
00101         
00102         // Thinning shader
00103         m_shadeThinning->bind();
00104         m_shadeThinning->setUniform( "frame", 0 );
00105         m_shadeThinning->setUniform( "mask", 1);
00106         m_shadeThinning->setUniform( "mOffsetX", mat3(offX), GL_FALSE );
00107         m_shadeThinning->setUniform( "mOffsetY", mat3(offY), GL_FALSE );
00108         m_shadeThinning->setUniform( "fThreshold", 0.1f );
00109         m_shadeThinning->unbind();
00110         
00111         // Spreading shader
00112         m_shadeSpreading->bind();
00113         m_shadeSpreading->setUniform( "mOffsetX", mat3(offX), GL_FALSE );
00114         m_shadeSpreading->setUniform( "mOffsetY", mat3(offY), GL_FALSE );
00115         m_shadeSpreading->setUniform( "mDistance", mat3(dist), GL_FALSE );
00116         m_shadeSpreading->setUniform( "fThreshold", 0.1f );
00117         m_shadeSpreading->setUniform( "fDistScale", 0.5f );
00118         m_shadeSpreading->unbind();
00119 }
00120 
00121 void tgImageProcessor::initFBO(int res)
00122 {
00123         if(res < 16)
00124                 printf("[tgImageProcessor::avgInit] Warning: resolution too low\n"); // doesn't make sense computing low number of sums on GPU
00125         
00126         bool res_valid = false;
00127         for(unsigned i=4; i<13; i++)
00128                 if(res == pow(2,i))
00129                         res_valid = true;
00130         
00131         if(!res_valid)
00132                 printf("[tgImageProcessor::avgInit] Warning: resolution must be power of 2 and in the range of 16 to 4048\n");
00133         
00134         fbo_res = res;
00135         
00136         glGenTextures(1, &fbo_tex_depth);
00137         glBindTexture(GL_TEXTURE_2D, fbo_tex_depth);
00138         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00139         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 
00140         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00141         glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // for attaching to fbo texture must be mipmap complete
00142 //      glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, fbo_res, fbo_res, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
00143         
00144         // tgTexture (=memory) for fbo
00145         glGenTextures(1, &fbo_tex);
00146         glBindTexture(GL_TEXTURE_2D, fbo_tex);
00147         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00148         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 
00149         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00150         glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // for attaching to fbo texture must be mipmap complete
00151         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, fbo_res, fbo_res, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
00152         
00153         
00154         // fbo = framebuffer object
00155         glGenFramebuffers(1,&fbo);
00156         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
00157         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo_tex, 0);
00158 //      glFramebuffertgTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, fbo_tex_depth, 0);
00159         
00160         m_cam_ortho_fbo.Set(    0.0f, 0.0f, 1.0f,
00161                                                         0.0f, 0.0f, 0.0f,
00162                                                         0.0f, 1.0f, 0.0f,
00163                                                         45.0f, fbo_res, fbo_res,
00164                                                         0.0f, 1.0f,
00165                                                         GL_ORTHO);
00166 
00167         glBindFramebuffer(GL_FRAMEBUFFER, 0);
00168         
00169         fbo_stage = ilog2(fbo_res);
00170         m_avg_init = true;
00171         
00172         if(     tgCheckFBError(GL_FRAMEBUFFER, "tgImageProcessor::avgInit()")!=GL_FRAMEBUFFER_COMPLETE ||
00173                 tgCheckError("tgImageProcessor::avgInit()")!=GL_NO_ERROR)
00174         {
00175                 std::string errmsg = std::string("[tgImageProcessor::initFBO()] Error generating frame buffer objects");
00176                 throw std::runtime_error(errmsg.c_str());
00177         }
00178 }
00179 
00180 void tgImageProcessor::drawQuad(float w, float h){    
00181         glBegin(GL_QUADS);
00182                 glTexCoord2f(0.0f,0.0f); glVertex3f( 0, 0, 0.0f);
00183                 glTexCoord2f(1.0f,0.0f); glVertex3f( w, 0, 0.0f);
00184                 glTexCoord2f(1.0f,1.0f); glVertex3f( w, h, 0.0f);
00185                 glTexCoord2f(0.0f,1.0f); glVertex3f( 0, h, 0.0f);
00186         glEnd();
00187 }
00188 
00189 // Display list for flipping image upside down
00190 void tgImageProcessor::drawQuadUpsideDown(float w, float h){    
00191         glBegin(GL_QUADS);
00192                 glTexCoord2f(0.0f,1.0f); glVertex3f( 0, 0, 0.0f);
00193                 glTexCoord2f(1.0f,1.0f); glVertex3f( w, 0, 0.0f);
00194                 glTexCoord2f(1.0f,0.0f); glVertex3f( w, h, 0.0f);
00195                 glTexCoord2f(0.0f,0.0f); glVertex3f( 0, h, 0.0f);
00196         glEnd();
00197 }
00198 
00199 // Set functions
00200 void tgImageProcessor::setCamOrtho(){ 
00201         m_cam_ortho.Activate();
00202 }
00203 
00204 // *** Image Processing functions ***
00205 void tgImageProcessor::flipUpsideDown(const tgTexture& source, tgTexture& result){
00206         int w = source.GetWidth();
00207         int h = source.GetHeight();
00208         m_cam_ortho.Activate();
00209         glEnable(GL_TEXTURE_2D);
00210                 source.Bind();
00211                 drawQuadUpsideDown(w, h);
00212                 result.CopyTexImage2D(w, h);
00213         glDisable(GL_TEXTURE_2D);
00214 }
00215 
00216 void tgImageProcessor::copy(const tgTexture& source, tgTexture& result){
00217         int w = source.GetWidth();
00218         int h = source.GetHeight();
00219         m_cam_ortho.Activate();
00220         glEnable(GL_TEXTURE_2D);
00221                 source.Bind();
00222                 drawQuad(w,h);
00223                 result.CopyTexImage2D(w, h);
00224         glDisable(GL_TEXTURE_2D);
00225 }
00226 
00227 void tgImageProcessor::gauss(const tgTexture& source, tgTexture& result){
00228         int w = source.GetWidth();
00229         int h = source.GetHeight();
00230         m_cam_ortho.Activate();
00231         m_shadeGauss->bind();
00232         glEnable(GL_TEXTURE_2D);
00233                 source.Bind();
00234                 drawQuad(w,h);
00235                 result.CopyTexImage2D(w, h);
00236         glDisable(GL_TEXTURE_2D);
00237         m_shadeGauss->unbind();
00238 }
00239 
00240 void tgImageProcessor::sobel(const tgTexture& source, tgTexture& result, float threshold, bool normalise, bool binary){
00241         int w = source.GetWidth();
00242         int h = source.GetHeight();
00243         m_cam_ortho.Activate();
00244         m_shadeSobel->bind();
00245         m_shadeSobel->setUniform( "fThreshold", threshold );
00246         m_shadeSobel->setUniform( "norm", normalise);
00247         m_shadeSobel->setUniform( "binary", binary);
00248     glEnable(GL_TEXTURE_2D);
00249                 source.Bind();
00250                 drawQuad(w,h);
00251                 result.CopyTexImage2D(w, h);
00252         glDisable(GL_TEXTURE_2D);
00253         m_shadeSobel->unbind();
00254 }
00255 
00256 void tgImageProcessor::sobel(const tgTexture& source, tgTexture& result, tgTexture& mask, float threshold, bool normalise, bool binary){
00257         int w = source.GetWidth();
00258         int h = source.GetHeight();
00259         m_cam_ortho.Activate();
00260         m_shadeSobel->bind();
00261         m_shadeSobel->setUniform( "fThreshold", threshold );
00262         m_shadeSobel->setUniform( "norm", normalise);
00263         m_shadeSobel->setUniform( "masked", true);
00264         m_shadeSobel->setUniform( "binary", binary);
00265         glEnable(GL_TEXTURE_2D);
00266                 source.Bind(0);
00267                 mask.Bind(1);
00268                 drawQuad(w,h);
00269                 result.CopyTexImage2D(w, h);
00270         glDisable(GL_TEXTURE_2D);
00271         m_shadeSobel->unbind();
00272         m_shadeSobel->setUniform( "masked", false);
00273 }
00274 
00275 void tgImageProcessor::thinning(const tgTexture& source, tgTexture& result){
00276         int w = source.GetWidth();
00277         int h = source.GetHeight();
00278         m_cam_ortho.Activate();
00279         m_shadeThinning->bind();
00280         glEnable(GL_TEXTURE_2D);
00281                 source.Bind();
00282                 drawQuad(w,h);
00283         result.CopyTexImage2D(w, h);
00284     glDisable(GL_TEXTURE_2D);
00285         m_shadeThinning->unbind();
00286 }
00287 
00288 void tgImageProcessor::thinning(const tgTexture& source, tgTexture& result, tgTexture& mask){
00289         int w = source.GetWidth();
00290         int h = source.GetHeight();
00291         m_cam_ortho.Activate();
00292         m_shadeThinning->bind();
00293         m_shadeThinning->setUniform( "masked", true);
00294         glEnable(GL_TEXTURE_2D);
00295                 source.Bind(0);
00296                 mask.Bind(1);
00297                 drawQuad(w,h);
00298         result.CopyTexImage2D(w, h);
00299     glDisable(GL_TEXTURE_2D);
00300         m_shadeThinning->setUniform( "masked", false);
00301         m_shadeThinning->unbind();
00302 }
00303 
00304 void tgImageProcessor::spreading(const tgTexture& source, tgTexture& result){
00305         int w = source.GetWidth();
00306         int h = source.GetHeight();
00307         m_cam_ortho.Activate();
00308         m_shadeSpreading->bind();
00309         glEnable(GL_TEXTURE_2D);
00310                 source.Bind();
00311                 drawQuad(w,h);
00312         result.CopyTexImage2D(w, h);
00313     glDisable(GL_TEXTURE_2D);
00314         m_shadeSpreading->unbind();
00315 }
00316 
00317 void tgImageProcessor::render(const tgTexture& tex){
00318         m_cam_ortho.Activate();
00319         glEnable(GL_TEXTURE_2D);
00320                 tex.Bind();
00321                 drawQuad(tex.GetWidth(), tex.GetHeight());
00322         glDisable(GL_TEXTURE_2D);
00323 }
00324 
00325 void tgImageProcessor::avgActivate(){
00326         if(m_avg_init){
00327                 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
00328                 tgCheckError("tgImageProcessor::avgActivate() A");
00329                 glClearColor(0,0,0,0);
00330                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00331                 tgCheckError("tgImageProcessor::avgActivate() B");
00332         }
00333 }
00334 
00335 void tgImageProcessor::avgGet(float *avg, int lvl){
00336         if(m_avg_init){
00337                 if(lvl==0){
00338                         // for some reason glGetTexImage doesen't get the value of the very last mipmap stage
00339 //                      float tmp[16];
00340 //                      glBindtgTexture(GL_TEXTURE_2D, fbo_tex);
00341 //                      glGenerateMipmap(GL_TEXTURE_2D);
00342 //                      glGetTexImage(GL_TEXTURE_2D, fbo_stage-1, GL_RGBA, GL_FLOAT, tmp);
00343 //                      avg[0] = 0;
00344 //                      for(unsigned i=0; i<4; i++)
00345 //                              avg[0] += 0.25 * tmp[i];
00346                         printf("[tgImageProcessor::avgGet] Warning: not implemented\n");
00347                 }else{
00348                         glBindTexture(GL_TEXTURE_2D, fbo_tex);
00349 //                      glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16,0, 0, fbo_res,fbo_res,0);
00350                         glGenerateMipmap(GL_TEXTURE_2D);
00351                         glGetTexImage(GL_TEXTURE_2D, fbo_stage-lvl, GL_RED, GL_FLOAT, avg);
00352                         tgCheckError("tgImageProcessor::avgGet()");
00353                 }
00354         }
00355 }
00356 
00357 void tgImageProcessor::avgDeactivate(){
00358         if(m_avg_init){
00359                 glBindFramebuffer(GL_FRAMEBUFFER, 0);
00360         }
00361 }
00362 
00363 
00364 
00365 


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