How to write GIMP plugin with OpenCV

How to write GIMP plugin with OpenCV

<solotim>

This is a guide of making OpenCV and Gimp worked togther. It's not complex as you might thought. Taking 5 minutes, you will understand how to make your first OpenCV-oriented Gimp plugin.

Gimp is powerful enough, why OpenCV comes into? (Don't care about this paragraph, it's a crap :))
Yes, Gimp is excellent, but it will take a while for me to explain why I involved OpenCV in.  I knew OpenCV before I knew Gimp. I wrote my program in OpenCV several months ago. When all core functions have been finished, I felt that UI is also critical for the program. However it is quite time-consuming to implement a full featured UI which can handle image load, save, display, mouse capture etc. Finally I searched google and come to realize that create a GIMP plugin is a good idea. That's the exact reason that I used OpenCV in Gimp plugin.

By querying the mailling list of GIMP I figured out that Gimp's plugin is nothing but "normal" programs which is conformed with GIMP's plugin interface. It means you can use any library you like in plugin coding, including OpenCV. As I already got my OpenCV based program born, what I need to do is just write some middle code to adapter my code to Gimp.

You can find the classic GIMP plugin tutorial in here: How to write a GIMP plug-in

I am not going to repeat the content of that tutorial, instead, let's have a look of how the adapter function works.

void  process_it (GimpDrawable  * drawable, GimpPreview   * preview)
{
    gint         i, j, k, channels;
    gint         x1, y1, x2, y2;
    gint         width, height;
    GimpPixelRgn rgn_in, rgn_out;
    guchar      
* rect;
    CvMat        mat;
    
    
if  ( !  preview)
        gimp_progress_init (
" Dust Cleaner " );

  
/*  Gets upper left and lower right coordinates,
   * and layers number in the image 
*/
  
if  (preview)
    {
      gimp_preview_get_position (preview, 
& x1,  & y1);
      gimp_preview_get_size (preview, 
& width,  & height);
      x2 
=  x1  +  width;
      y2 
=  y1  +  height;
    }
  
else
    {
    gimp_drawable_mask_bounds (drawable
-> drawable_id,
                            
& x1,  & y1,
                            
& x2,  & y2);
      width 
=  x2  -  x1;
      height 
=  y2  -  y1;
    }   

    channels 
=  gimp_drawable_bpp (drawable -> drawable_id);

    
/*  Region for reading  */
    gimp_pixel_rgn_init (
& rgn_in,
                    drawable,
                    x1, y1,
                    x2 
-  x1, y2  -  y1,
                    FALSE, FALSE);
    
/*  Region for writting  */
    gimp_pixel_rgn_init (
& rgn_out,
                    drawable,
                    x1, y1,
                    x2 
-  x1, y2  -  y1,
                    preview 
==  NULL, TRUE);

    
/*  Initialise enough memory for rect */
    rect 
=  g_new (guchar, channels  *  width  *  height);  //<----this is the raw data represents the image.
    
/*  Put raw data from rgn_in to rect  */
    gimp_pixel_rgn_get_rect (
& rgn_in,
                                            rect,
                                            x1, y1,
                                            width,
                                            height);

    
    
/*  Create OpenCV matrix object from raw data  */
    mat 
=  cvMat( height, width, CV_8UC3, rect );            //<---- this is the exact code of creating object of OpenCV
    findDust(
& mat);                                                                //<----this is the core function to handle the image processing

    
/*  Set modified raw data back to writable region  */
    gimp_pixel_rgn_set_rect (
& rgn_out,
                                            rect,
                                            x1, y1,
                                            width,
                                            height);        
    
/*  Free memory  */
    g_free (rect);                                                                     //<----don't forget release the raw data
  
/*   Update the modified region  */
  
if  (preview)
    {
      gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview),
                                         
& rgn_out);
    }
  
else
    {
      gimp_drawable_flush (drawable);
      gimp_drawable_merge_shadow (drawable
-> drawable_id, TRUE);
      gimp_drawable_update (drawable
-> drawable_id,
                                                     x1, y1,
                                                     width, height);
    }
    
return ;
}

As you can see from the above code, there are three steps to  get  things done:
  1. Create a  raw  data represents the image object in Gimp.
  2. Create a CvMat object by the raw data.
  3. Give the CvMat object a whirl with your local function. Remember, when you modify any pixel of that CvMat object you are actually modifying the raw data wrapped by the CvMat header.
That's all. It's fortunate that both Gimp and OpenCV used the same sequence of RGB color, so it's simplified the conversion between them, not like Matlab.
Good luck~

Thank David Hodson and Sven .

Frank Tao

你可能感兴趣的:(How to write GIMP plugin with OpenCV)