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 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
00241 void ImageProcessor::setCamOrtho(){
00242 m_cam_ortho.Activate();
00243 }
00244
00245
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");
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);
00389
00390
00391
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);
00398 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, fbo_res, fbo_res, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
00399
00400
00401
00402 glGenFramebuffers(1,&fbo);
00403 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
00404 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo_tex, 0);
00405
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
00437
00438
00439
00440
00441
00442
00443
00444 ROS_DEBUG("[ImageProcessor::avgGet] Warning: not implemented\n");
00445 }else{
00446 glBindTexture(GL_TEXTURE_2D, fbo_tex);
00447
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
00462 bool ImageProcessor::init(unsigned w, unsigned h){
00463
00464 m_width = w;
00465 m_height = h;
00466
00467
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
00476 if(!initShader())
00477 return false;
00478
00479
00480
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