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

posted on 2007-04-30 20:13 肥虫 阅读(2689) 评论(0)  编辑  收藏 所属分类: Image Processing


只有注册用户登录后才能发表评论。


网站导航:
 

导航

<2007年4月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

统计

常用链接

留言簿(2)

随笔分类

随笔档案

相册

搜索

最新评论

阅读排行榜

评论排行榜