C语言 吉普高斯码解释



我试图理解 Gimp 中的高斯模糊是如何工作的。我下载了代码,我几乎可以理解一些事情......但我对其他事情感到困惑。

这是代码:

make_rle_curve (gdouble   sigma,
gint    **p_curve,
gint     *p_length,
gint    **p_sum,
gint     *p_total)
{
const gdouble  sigma2 = 2 * sigma * sigma;
const gdouble  l      = sqrt (-sigma2 * log (1.0 / 255.0));
gint           temp;
gint           i, n;
gint           length;
gint          *sum;
gint          *curve;
n = ceil (l) * 2;
if ((n % 2) == 0)
n += 1;
curve = g_new (gint, n);
length = n / 2;
curve += length; /* 'center' the curve[] */
curve[0] = 255;
for (i = 1; i <= length; i++)
{
temp = (gint) (exp (- (i * i) / sigma2) * 255);
curve[-i] = temp;
curve[i] = temp;
}
sum   = g_new (gint, 2 * length + 1);
sum[0] = 0;
for (i = 1; i <= length*2; i++)
{
sum[i] = curve[i-length-1] + sum[i-1];
}
sum += length; /* 'center' the sum[] */
*p_total  = sum[length] - sum[-length];
*p_curve  = curve;
*p_sum    = sum;
*p_length = length;

对我来说,曲线和总和是 2 个数组。 曲线从 -3 到 +3

总和从 0 到 6。 换句话说,我有

curve[-3] = ... 
curve[0] = 255
curve[3] = ...

curve = curve + length到底做了什么? 同样的事情,sum = sum + length做什么?

非常感谢您的帮助!

PS:我不是编码:(的天才

光滑的代码。 看来他们正在做指针算术。

我将从顶部开始,并使用curve进行解释。 我知道你只是在问曲线,但为了清楚起见,我也会解释其他东西。

gint *curve;

这将创建一个指向内存地址的指针,该内存地址足够大,可以容纳整数(gint 类型)。 目前它没有初始化,所以不是很有帮助

curve = g_new (gint, n);

现在,创建一个整数 (gint) 数组,并为曲线分配此新数组的起始地址。

length = n / 2;

在这里,他们正在计算过滤器的中点,即大小n。 过滤器的大小基于l,这是基于前面的 sigma 参数和对数变换数学。 在这里,length指的是一维内核的半径,而不是两倍长的数组长度。

curve += length; /* 'center' the curve[] */

你的问题:这是怎么回事?

这会更改变量curve,使其现在指向先前初始化的数组的中间,以便循环索引的后续操作可能更容易被程序员考虑,并且编写、调试等更清晰一些。

在这里,由于不使用[]运算符,因此对curve的引用是其在内存中的地址。 分配的内存保留在原位,不会四处移动(当然你可以把它从一个地方复制到另一个地方,但这不是我要说的)。 指针,curve,可以这么说。curve本身的地址被设置为变量,但是,它包含的地址可以调整和更改,以便它指向不同的东西,就像任何其他非常量变量一样,可以更改其值。

起初,curve指向曲线[0]的地址。 事实并非如此,但既然你说你是新手,假设 curve[0] 在内存地址 00 处。 所以curve的值,也是相等的地址00。 调用curve += length可以解释为curve = curve + length内部是将长度数据类型的大小(以字节为单位)添加到曲线的地址,然后用结果更新曲线的地址。 举个例子,假设 gint 需要 4 个字节,length是 5,curve仍然是 00。

因此,调用变为

  1. curve += length
  2. curve = curve + length
  3. curve = curve + sizeof(length)
  4. curve =地址曲线指向内存使用的字节数+
  5. 长度
  6. curve =地址 00+4 字节 * 8 位/字节
  7. curve = Address 32(地址 32 将以十六进制书写为 0x20)

同样,用g_new(gint, n)声明的内存仍然存在,它被声明的地方(它不会移动),但现在,由于指针已更改,它(指针)可用于使用负索引索引到该数组。 也就是说,curve[0]实际上是现在数组中间的值,而curve[-n]是数组的第一个元素。

在滤波器中,中点(curve[0])直接设置为最大值:

curve[0] = 255;

接下来的迭代从这里(+/- i)开始填充内核。

但是,您可以在下一个 for 循环中看到曲线值再次偏移以居中向上(即curve[i-length-1])。 现在有点令人困惑,因为看起来它们混合并匹配了这两种方法(有时使用指针算法使索引更清晰,有时不使用)。 但是,嘿,他们对其进行了编程,并且根据其余代码的外观,可能有充分的理由这样做。 谁知道呢,也许他们只是想为了多样性而把事情混为一谈。

更新

关于sum,首先设置数组中的值,然后将指针更改为指向此填充数组的中心。 但是,该程序可以遵循与之前在curve中看到的相同模式,并像这样编写:

sum += length; /* 'center' the sum[] */
sum[-length] = 0;
for (i = -length+1; i <= length; i++)
{
sum[i] = curve[i] + sum[i-1];
}

顺便说一句,调用*p_total = sum[length] - sum[-length];看起来可以简单地p_total = sum[length];,因为sum[-length]始终设置为 0。 也就是说,sum[0]=0后面跟sum += length表示调整后的sum[-length]与指针调整前的sum[0]相同。 这两个引用都指向数组中的第一个值,即 0。

sum指针放置在数组的中间与函数结束时curve设置为数组的中间一致。

然而,在"sum"的情况下,调整是在数组用值初始化后进行的,而在curve的情况下,首先进行调整,然后初始化值。 这可能只是程序员喜欢混合的东西,可能更容易想到与从 1 到 K 的索引集成(可以这么说)。 可能还有其他方法可以编写同样有效的代码,这就是这一切的美妙之处(或者有时可能是诅咒)。

相关内容

  • 没有找到相关文章

最新更新