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[Image] " );

  
/*  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 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值