Archive for October, 2012

Convert a bunch of images into a video, batch job

Friday, October 26th, 2012

I was sure I posted this some time before, but just in case, here it is again. My programs can easily dump jpgs, pngs, or tga image files at every frame. Sometimes it suffices to convert these to an animated GIF using imagemagick. But if there are many images and they’re all hi-res then really you need a proper video codec to get a reasonably small file. I use this ffmpeg command:

ffmpeg -f image2 -r 30 -i myimages-%04d.tga -r 30 -vcodec libx264 -pix_fmt yuv420p -q:vscale 0 output.mp4

or using GLOB for a lexicographical, alphabetical file list:

ffmpeg -f image2 -r 30 -pattern_type glob -i 'my-images-*.png' -r 30 -vcodec libx264 -pix_fmt yuv420p -q:vscale 0 output.mp4

Update : The -pix_fmt yuv420p` is important for getting the output video to play in quicktime.

Setting number of OpenMP threads in MATLAB mex function, corrupts max number of threads

Thursday, October 25th, 2012

I wanted to use OpenMP in a MATALB mex function, and I noticed some strange behavior when trying to set the number of threads. Consider this small program:


#include "mex.h"                                          
#include <omp.h>                                          
#define min(X,Y) (X<Y ? X : Y)                            

void mexFunction(int nlhs, mxArray *plhs[],               
    int nrhs, const mxArray *prhs[])
{
  using namespace std;                                    

  // Set up openmp
  int nProcessors=omp_get_max_threads();                  
  mexPrintf("Number of processors: %d\n",nProcessors);    
  // Set to 2 threads
  omp_set_num_threads(min(nProcessors,2));                
  mexPrintf("Using %d out of %d threads\n",min(nProcessors,2),nProcessors);

#pragma omp parallel for
  for(int i = 0;i<1000;i++)                               
  {
    if(i==0)
    {
      mexPrintf("Num threads: %d\n",omp_get_num_threads());      
    }
  }
  
}

If I compile this with:


mex omp_bug.cpp

making sure to have -fopenmp in the compiler flags in mexopts.sh. Then when I run the program the first time I see:


Number of processors: 8
Using 4 out of 8 threads
Num threads: 4

Which appears to be working correctly. But then I run it again and see:


Number of processors: 4
Using 2 out of 4 threads
Num threads: 2

And again:


Number of processors: 2
Using 2 out of 2 threads
Num threads: 2

and it continues. So it seems that setting the number of threads actually also sets the number of max threads across executions. The interesting thing is that if I recompile with the mex function it resets this number of max threads, so it will run correctly once more. In my case, I just no longer try to set the number of threads and just let OpenMP use all of them.

Eigen access quaternion coefficients data elements

Wednesday, October 24th, 2012

For some reason, using eigen’s Quaternion class I could not figure out how to access the underlying data: the x,y,z,w coefficients of the xi + yi + zi + w quaternion representation. I tried using


Eigen::Quaterniond q;
function_needing_double_pointer(q.data());

but the data() method doesn’t exist so you get:


error: 'Eigen::Quaterniond' has no member named 'data'

I also tried just referencing to the first coefficient (which confusingly is x despite the constructor using w,x,y,):


function_needing_double_pointer(q.data());

seems works if you first assign to a pointer, but otherwise you get:


error: lvalue required as unary '&' operand

This seems like the “correct” solution:


function_needing_double_pointer(q.coeffs().data());

GL_POSITION retrieved with glGetLightfv wrong

Sunday, October 21st, 2012

I recently got snagged on a bug in my code. I was setting the position of a light at every frame in OpenGL with:


const float lp[4] = {0,0,1,1};
glLightfv(GL_LIGHT0,GL_POSITION,lp);

This produced the correct result the first frame but then subsequent frames came out wrong. To debug this I added:


float cp[4];
glGetLightfv(GL_LIGHT0,GL_POSITION,lp);
// print lp
// print cp

Which would print:


lp: [0 0 1 1]
cp: [0 0 1 1]
lp: [0 0 1 1]
cp: [0 0 -29 1]

Finally I discovered it was because I was setting the light position before setting up my model view matrix. I suppose the first time through it had an identity matrix there as default, but then it was corrupted by the time of the second draw.

Note: At first, to make matters worse, I was using lp[3] instead of lp[4].

Transfusive Image Manipulation project page

Thursday, October 18th, 2012

transfusive image manipulation transfers edits on one image to other images of the same object
My colleagues, Kaan YĆ¼cer, Alexander Hornung, Olga Sorkine, and I have just submitted the camera ready version of paper “Transfusive Image Manipulation” to be presented at ACM SIGGRAPH Asia 2012. We’ve put up a Transfusive image manipulation project page where you can find the preprint version of the article, videos and implementation details and hopefully more to com.

Abstract

We present a method for consistent automatic transfer of edits applied to one image to many other images of the same object or scene. By introducing novel, content-adaptive weight functions we enhance the non-rigid alignment framework of Lucas-Kanade to robustly handle changes of view point, illumination and non rigid deformations of the subjects. Our weight functions are content-aware and possess high-order smoothness, enabling to define high-quality image warping with a low number of parameters using spatially-varying weighted combinations of affine deformations. Optimizing the warp parameters leads to subpixel-accurate alignment while maintaining computation efficiency. Our method allows users to perform precise, localized edits such as simultaneous painting on multiple images in real-time, relieving them from tedious and repetitive manual reapplication to each individual image.

Accompanying video

Perl warnings logging into blue host server from Switzerland

Wednesday, October 17th, 2012

I got the following warnings logging into my Bluehost web server from Zurich:


perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
	LANGUAGE = (unset),
	LC_ALL = (unset),
	LC_CTYPE = "UTF-8",
	LANG = "en_US.utf-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
	LANGUAGE = (unset),
	LC_ALL = (unset),
	LC_CTYPE = "UTF-8",
	LANG = "en_US.utf-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
	LANGUAGE = (unset),
	LC_ALL = (unset),
	LC_CTYPE = "UTF-8",
	LANG = "en_US.utf-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").

To disable them I just commented out the following line to look like:


SendEnv LANG LC_*

in the /private/etc/ssh_config file on my client-side mac.
source

-Weffc++ and Eigen library

Sunday, October 14th, 2012

I recently tried to make use of the -Weffc++ gcc compiler flag in my project. Unfortunately Eigen is not developed with these warnings in mind. So when I tried to use it I got a gazillion warnings from including Eigen headers. My solution was to move all Eigen includes to a single header (EigenConvenience.h), which looks something like this:


#ifdef __GNUC__
// This is how it should be done
#  if __GNUC__ >= 4
#    if __GNUC_MINOR__ >= 6
#      pragma GCC diagnostic push
#      pragma GCC diagnostic ignored "-Weffc++"
#    endif
#  endif
// This is a hack
#  pragma GCC system_header
#endif

// Include all eigen headers here, e.g.
#include <Eigen/Dense>

#ifdef __GNUC__
#  if __GNUC__ >= 4
#    if __GNUC_MINOR__ >= 6
#      pragma GCC diagnostic pop
#    endif
#  endif
#endif

Sign a PDF form with an image

Saturday, October 13th, 2012

I tried to sign a PDF form that was sent to me using Acrobat Pro but all the sign fields were greyed out. TO get around this I first opened the document in Preview.app, clicked Print > PDF > Open PDF in Preveiw. This opens up a copy of the document, but the forms have been converted to a plain document. Then I could open it up in Acrobat and dump in my signature image using Tools > Comment & Markup > Stamps > Paste Clipboard Image as Stamp Tool.

GL_COMPILE_AND_EXECUTE is slow (but apparently everybody knew that)

Thursday, October 11th, 2012

Although it doesn’t seem to be deprecated the glNewList() option GL_COMPILE_AND_EXECUTE is not properly supported by nVidia GPUs. On my linux machine, we installed a fancy pants nVidia card. So I was surprised to find out that my code ran slower there than on my dinky mac. After a long debugging session I found that it was all GL_COMPILE_AND_EXECUTE‘s fault. I was displaying a mesh each frame using code that looked like:


  if(!display_list_compiled)
  {
    dl_id = glGenLists(1);
    glNewList(dl_id,GL_COMPILE_AND_EXECUTE);
    ... //draw mesh
    glEndList();
    display_list_compiled = true;
  }else
  {
    glCallList(dl_id);
  }

I expected that this would be slow for the first time. But in fact it was significantly slower (factor of 100) for every frame! Even though it was using the display list. I guess that passing GL_COMPILE_AND_EXECUTE creates a very badly organized display list and then you’re punished every time you use it.

The solution is of course trivial:


  if(!display_list_compiled)
  {
    dl_id = glGenLists(1);
    glNewList(dl_id,GL_COMPILE;
    ... //draw mesh
    glEndList();
    display_list_compiled = true;
  }
  glCallList(dl_id);

but $#%^&*! what a waste of time.

Compiling and running Off Screen Mesa (OSMesa) demo (osdemo.c) on mac os x

Tuesday, October 9th, 2012

I installed mesa on my mac using macports:

sudo port install mesa

But was sad to find out that the off screen renderer (the whole reason I got it), didn’t work out of the box. The problem seems to be that the things aren’t meshing well with the GLU implementation. I tried to compile the mesa demo file

osdemo.c with:

gcc -o osdemo osdemo.c -I/opt/local/include/ -L/opt/local/lib/ -lOSMesa -lglu

which compiled but produced a funny result:

mesa wrong output with bad glu implementation

This picture looked ok at first, but then I realized that there should be a green cone and a blue sphere also in the image. These objects were rendered using glu*() commands in osdemo.c, but some how have had no effect, despite compiling correctly. I also tried linking against the native GLU implementation in the mac os x OpenGL framework and the GLU implementation in my /usr/X11/lib directory. Both compiled but produced runtime errors:

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x000000000000000c
0x00007fff8c8b2a7d in gluQuadricDrawStyle ()
(gdb) bt
#0  0x00007fff8c8b2a7d in gluQuadricDrawStyle ()
#1  0x00000001000011a6 in Cone ()
#2  0x000000010000172d in render_image ()
#3  0x0000000100000e26 in main ()

I finally fixed the problem by reinstalling GLU by itself via mesa’s repo:

./autogen.sh
./configure --enable-osmesa --prefix=/usr/local/
make
sudo make install

Now I can compile osdemo again (careful to note that I’ve places -L/usr/local/lib/ before -L/opt/local/lib/):

gcc -o osdemo osdemo.c -I/opt/local/include/ -L/usr/local/lib/ -L/opt/local/lib/ -lOSMesa -lglu

And when I run it I get the correct picture: correct osdemo output with correct glu implementation

Note: A new version of mesa was just released yesterday and may fix this issue. I don’t know yet, because the mesa source does not compile out of the box for mac os x and the macports version has not yet been updated.

Update: Seems this problem still hasn’t been fixed in the macports version of mesa-glu. I recently ran into this again where gluPerspective and gluLookAt were producing bogus results.