从GIMP的Retinex算法里发现了一种高斯模糊的快速实现方法

出自:http://bbs.csdn.net/topics/390340232


这段时间在研究Retinex 技术(Retinex技术的难点其实还是个高斯模糊) ,看例程代码时翻到了GIMP的源代码,结果却找到了一种简单而又快速的高斯模糊的实现方式。

     这种高斯模糊的实现同GIMP内嵌的高斯模糊算法也有所不同,并且速度上还有一定的优势,具体的代码可以参考GIMP下的contrast-retinex.c里面的代码。

     GIMP自带的高斯模糊的代码在 blur-gauss里。

     不过使用Retinex里的高斯模糊的代码会有一个小问题,就是多次模糊会发现图像像素整体向右下角或某个方向偏移,这个问题的解决很简单,有朋友遇到的时候在来问问,这里先卖个关子。

      具体的算法论文可以再百度搜索 : Recursive Implementation of the gaussian filter.

      贴一段核心代码:

C/C++ code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/*
  * Calculate the coefficients for the recursive filter algorithm
  * Fast Computation of gaussian blurring.
  */
static  void
compute_coefs3 (gauss3_coefs *c, gfloat sigma)
{
   /*
    * Papers:  "Recursive Implementation of the gaussian filter.",
    *          Ian T. Young , Lucas J. Van Vliet, Signal Processing 44, Elsevier 1995.
    * formula: 11b       computation of q
    *          8c        computation of b0..b1
    *          10        alpha is normalization constant B
    */
   gfloat q, q2, q3;
 
   q = 0;
 
   if  (sigma >= 2.5)
     {
       q = 0.98711 * sigma - 0.96330;
     }
   else  if  ((sigma >= 0.5) && (sigma < 2.5))
     {
       q = 3.97156 - 4.14554 * (gfloat)  sqrt  (( double ) 1 - 0.26891 * sigma);
     }
   else
     {
       q = 0.1147705018520355224609375;
     }
 
   q2 = q * q;
   q3 = q * q2;
   c->b[0] = (1.57825+(2.44413*q)+(1.4281 *q2)+(0.422205*q3));
   c->b[1] = (        (2.44413*q)+(2.85619*q2)+(1.26661 *q3));
   c->b[2] = (                   -((1.4281*q2)+(1.26661 *q3)));
   c->b[3] = (                                 (0.422205*q3));
   c->B = 1.0-((c->b[1]+c->b[2]+c->b[3])/c->b[0]);
   c->sigma = sigma;
   c->N = 3;
 
}
 
View Code 
static  void
gausssmooth (gfloat *in, gfloat *out, gint size, gint rowstride, gauss3_coefs *c)
{
   /*
    * Papers:  "Recursive Implementation of the gaussian filter.",
    *          Ian T. Young , Lucas J. Van Vliet, Signal Processing 44, Elsevier 1995.
    * formula: 9a        forward filter
    *          9b        backward filter
    *          fig7      algorithm
    */
   gint i,n, bufsize;
   gfloat *w1,*w2;
 
   /* forward pass */
   bufsize = size+3;
   size -= 1;
   w1 = (gfloat *) g_try_malloc (bufsize *  sizeof  (gfloat));
   w2 = (gfloat *) g_try_malloc (bufsize *  sizeof  (gfloat));
   w1[0] = in[0];
   w1[1] = in[0];
   w1[2] = in[0];
   for  ( i = 0 , n=3; i <= size ; i++, n++)
     {
       w1[n] = (gfloat)(c->B*in[i*rowstride] +
                        ((c->b[1]*w1[n-1] +
                          c->b[2]*w1[n-2] +
                          c->b[3]*w1[n-3] ) / c->b[0]));
     }
 
   /* backward pass */
   w2[size+1]= w1[size+3];
   w2[size+2]= w1[size+3];
   w2[size+3]= w1[size+3];
   for  (i = size, n = i; i >= 0; i--, n--)
     {
       w2[n]= out[i * rowstride] = (gfloat)(c->B*w1[n] +
                                            ((c->b[1]*w2[n+1] +
                                              c->b[2]*w2[n+2] +
                                              c->b[3]*w2[n+3] ) / c->b[0]));
     }
 
   g_free (w1);
   g_free (w2);
}


    有兴趣的朋友可以去看这两个源代码,C的算法代码转换为C#基本上很容易。g_try_malloc 之类的函数可以用Marshal.AllocHGlobal实现。

      这段代码的优化还有很大的空间, 并且高斯模糊算法很容易并行化。 

      我用单线程处理 在i3的CPU上处理一副4000*3000的数码彩色照片的耗时基本在725ms(任意模糊半径理论耗时都是一样的,耗时仅为算法本身的,不包括图像数据读取和显示),说明这个算法很实用。

你可能感兴趣的:(从GIMP的Retinex算法里发现了一种高斯模糊的快速实现方法)