lambda算子 1.b

本文深入探讨了Lambda演算中的自由与有界标识符概念,解释了标识符如何在不同的上下文中区分,以及如何通过Alpha转换和Beta简化进行计算。此外还介绍了如何避免变量冲突等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上上周就快写完这篇时,IE突然当掉,写的东西烟消云散。俺也元气大伤。这次吸取教训,不用CSDN的在线工具写了。这样的坏处是把文章拷贝到CSDN时,格式难免出错,还得手工调整一下。CSDN什么时候可以实现confluence的在线备份功能呢?还是继续八卦lambda:

自由 vs 有界标识符

标识符和变量其实是一个意思。我记得国内教材里很少用标识符这个说法。不过既然原作者用这个说法,我就跟着用了。上次说到Currying解决了如何处理多参数的问题。在讨论怎么使用lambda前,我们还要解决一个细微但重要的语法问题:封闭(closure),或者叫完全有界(complete bounding)。这里的有界和一阶谓词逻辑里的有界没有本质区别,对一阶谓词逻辑熟悉的老大们可以放心跳过。其实有界涉及的定义很直观,我们看一个例子先。假设我们有一个函数lambda x y. (lambda y. y + 2) + x + y +z,lambda y. y+2里的y和它后面的y是不是一样的呢?显然它们是不一样的。为了处理这种区别,我们引入了有界。当一个lambda表达式被计算时,它不能处理无界的标识符。当一个标识符出现在一个lambda表达式的参数里,并且被包含在这个lambda表达式里,我们就可以说这个标识符有界。如果一个标识符没有被包含在任何一个表达式里,我们就叫它为自由变量。比如说,上面那个lambda表达式里,x 出现在lambda x y .(....)里,所以它是有界的变量,它的包含环境(enclosing context,用“语境”或者“上下文”怎么听怎么别扭,好像俺是《读书》的御用作者似的。:-D)是整个lambda表达式。lambda y. y+2里的y也是有界的,但它的包含环境是lambda y. y+2。标识符z没有出现在包含它的表达式的参数列表里,所以是自由变量。再举几个例子:

  1. lambda x . plus x y: 这个表达式里,"y"和"plus"都是自由变量,因为它们不是任何包含它们的表达式的参数。x有界,因为它被包含在plus x y里,而plus x y的参数有x。
  2. lambda x y.y x: 这个表达式里,x和y都有界,因为它们是这个表达式的参数。
  3. lambda y . (lambda x . plus x y): 在内嵌的表达式lambda x. plus x y里,y和 plus 是自由变量而x是有界变量。在整个lambda表达式里,x和y都有界:x在内嵌表达式界内,而y在整个表达式界内。plus仍然自由。

我们用"free(x)"来代表表达式x里所有自由变量的集合。

一个lambda表达式完全合法仅当它的所有变量都有界。不过当我们考查某个复杂表达式里的子表达式且不考虑上下文时,那些子表达式可以有自由变量-其实确保正确处理那些子表达式里的自由变量非常重要。

 

Lambda 算子计算规则

其实真正的规则就俩:alpha和beta。Alpha规则又叫转换(conversion)规则,而beta规则又叫简化(reduction)规则。

Alpha转换

这个充满了《星际迷航》味道的规则其实就是重命名操作。它无非是说变量名不重要:给定任何一个lambda表达式,我们可以任意改变参数的名字,只要我们相应地改变这些对应这些参数的变量名字。

比如说,我们有如下表达式:
lambda x . if (= x 0) then 1 else x^2

我们通过alpha规则把X改成Y(写作alpha[x/y], 和逻辑里的变量替换一个写法),于是得到:
lambda y . if (= y 0) then 1 else y^2

Alpha操作完全不影响lambda表达式的意义。不过我们后面会发现,这个操作很重要,因为它让我们能够实现诸如递归的操作。

Beta简化

Beta简化就有意思了。我们只需要这一个规则,就可以让lamdba算子实现一台计算机能做的任何计算。透过纷繁的表象,我们会发现事情的本质往往出人意料地清晰而简单。删繁为简,恰是数学魅力所在。

Beta规则无非是说,应用一个函数(也就是lambda表达式。一个意思)等价于通过把函数体内有界的变量替换成应用里对应参数的实际值来替换原来的函数。听上去有些拗口(呵呵,其实原文更拗口),但当你看一个例子就知道它其实很简单:

假设我们要应用一个函数:"(lambda x . x + 1) 3"。Beta规则说,我们可以替换整个表达式,把函数体(也就是“x+1”)里的参数对应的x替换成实际的值3。所以最后的结果是“3+1”。

再来一个稍微复杂点的例子:
lambda y . (lambda x . x + y)) q

这个表达式有意思,因为应用了这个表达式后,我们可以得到另外一个表达式。也就是说,它是一个生成表达式的表达式(说到这里,玩儿动态语言的老大们可以笑了,玩儿C/C++/Java的老大们可以流口水了)。当我们对这个表达式应用Beta简化时,我们把所有对应参数y的变量替换成实际的值q。所以结果是"lambda x, x+q"。

再来一个例子:
"(lambda x y. x y) (lambda z . z * z) 3". 这个带两个参数的函数把第一个参数应用到第二个参数上。当我们计算它的值时,我们把第一个lambda表达式里的变量x换成lambda z. z * z, 再把变量y换成3,得到(lambda z. z * z) 3。对该结果应用Beta简化,我们得到3 * 3。

Beta的严格定义如下:

lambda x . B e = B[x := e] if free(e) /subset free(B[x := e]

这个定义末尾的条件,"if free(e) /subset free(B[x:=e])"道出了我们需要Alpha转换的原因:仅当beta化简不会引起有界变量和自由变量的冲突时,我们可以实施Beta化简。如果一个变量“z”是"e"里的自由变量,那我们得保证beta化简不会让"z"变成有界变量。如果B里的有界变量和”e"里的自由变量重名,我们必须先用Alpha转换,是的重名的变量不再重名。形式化定义不够直观,直观描述又不够简洁。还是来个例子漱漱口:

给定一个表达式,lambda z. lambda x. x+z. 假设我们要应用这个表达式:
(lambda z . (lambda x . x + z)) (x + 2)

在实际参数"(x + 2)"里,x是自由变量。但x不是表达式lambda x. x+z的自由变量。也就是说,free(e) /subset free(B[ x:=e])不成立。如果我们打破Beta简化的规则,直接开始Beta简化,便会得到: lambda x . x + x + 2

"x+2"里自由变量,x,现在变得有界了。如果我们把结果应用到3上:(lambda x. x+2+2) 3,我们得到3 + 3 + 2。

如果我们按正常程序办事呢?

应用 alpha[x/y]: lambda z . (lambda y . y+z)) (x + 2)
应用 beta: lambda y . y + x + 2) 3
再次应用beta: 3 + x + 2.

"3+x+2" 和 "3+3+2" 很不一样哈!

规则就这些了。我们还可以选择性地加一个所谓的Eta-化简,不过它不是必需的。我们就此跳过。我们讨论的这套系统已经是图灵完备的计算体系。那这套系统到底有什么用嗫?到底怎样才能让这套系统变得真正有用嗫?嗯,要说明这些问题,我们得先定义一些基本的函数,以便我们做算术,条件测试,递归,等等。这些会在以后的帖子里谈到。

我们也还没有谈到适合lambda算子的模型(Good Math Bad Math的作者在这里这里讨论了模型)。模型也是很重要的东西。逻辑学家用了好几年时间研究lambda算子,才搞出一个完备的模型。而且早先时候,尽管lambda算子看起来没错,为它制订模型的工作却失败了。这在当时极为引人关注。要知道,毕竟一个系统没有有效的模型就没有实际的意义。

<think>好的,用户让我介绍一下Harris角点检测算子。首先,我得回忆一下Harris算子的基本概念和原理。角点检测在计算机视觉中很重要,用于特征提取和匹配。Harris算子是经典方法之一,需要详细解释它的由来、数学原理以及应用步骤。 首先,Harris算子的提出是为了解决Moravec算子的局限性,比如方向敏感性和噪声敏感。我需要比较一下两者的区别,突出Harris的改进之处。然后,数学推导是关键部分。Harris使用了自相关函数,计算窗口在各个方向移动后的灰度变化,进而构造了结构张量矩阵M。这里可能需要详细推导自相关函数的展开,以及如何利用泰勒展开近似,最后得到M矩阵。 接下来,解释角点响应函数R的计算,以及如何通过R的值来判断角点、边缘和平坦区域。这里需要明确R的公式,以及k的取值对结果的影响。可能还需要提到R的计算中涉及的特征值分析,比如Harris如何通过迹和行列式来避免直接计算特征值,这样计算更高效。 然后,步骤部分要分点说明,从计算梯度、构造M矩阵、计算R、非极大值抑制到阈值处理。这部分要清晰,让用户了解实际应用的流程。应用场景方面,可以举例子,比如图像拼接、目标跟踪等,说明Harris算子的实用性。 最后,优缺点部分要客观,Harris的优点是对旋转和光照变化有一定鲁棒性,但缺点是对尺度变化敏感,可能有噪声干扰。可能还需要提到后续的改进方法,比如SIFT、SURF等,但用户没问的话,可以简要带过。 在写作过程中,要确保数学公式的正确性,行内公式用$...$,独立公式用$$...$$,并且符合LaTeX语法。比如结构张量矩阵M的表达式,角点响应函数R的公式,都要正确展示。同时,保持语言口语化,避免专业术语堆砌,但又要准确。 需要检查是否有遗漏的重要点,比如非极大值抑制的具体操作,或者阈值处理的方法。另外,是否需要提到OpenCV中的Harris实现?可能用户想知道实际应用,但可能超出问题范围,不过作为扩展可以提一下。 最后总结Harris算子的重要性,确保结构清晰,逐步引导用户理解从原理到应用的整个过程。避免使用Markdown格式,保持自然的中文叙述,分点明确,逻辑连贯。</think>Harris算子是一种经典的角点检测算法,由Chris Harris和Mike Stephens于1988年提出。它在计算机视觉中广泛用于图像特征点检测,尤其擅长识别图像中灰度变化显著的角点区域。以下是逐步解析: --- ### 1. 基本原理 **目标**:检测图像中灰度在多个方向发生剧烈变化的点(即角点)。 **核心思想**:通过局部窗口移动时的灰度变化程度来区分角点、边缘和平坦区域: - **平坦区域**:窗口移动时灰度变化小 - **边缘区域**:沿边缘方向移动时灰度变化小,垂直方向变化大 - **角点区域**:任意方向移动时灰度变化均显著 --- ### 2. 数学推导 #### 步骤1:定义自相关函数 对于图像窗口平移$(u,v)$,灰度变化$E(u,v)$可表示为: $$E(u,v) = \sum_{x,y} w(x,y) \left[ I(x+u,y+v) - I(x,y) \right]^2$$ 其中: - $w(x,y)$为窗口函数(如高斯函数) - $I(x,y)$为图像灰度值 #### 步骤2:泰勒展开近似 对$I(x+u,y+v)$进行一阶泰勒展开: $$I(x+u,y+v) \approx I(x,y) + u \cdot I_x + v \cdot I_y$$ 代入$E(u,v)$得: $$E(u,v) \approx \sum_{x,y} w(x,y) \left[ u \cdot I_x + v \cdot I_y \right]^2$$ #### 步骤3:构造结构张量矩阵 将表达式改写为矩阵形式: $$E(u,v) \approx \begin{bmatrix} u & v \end{bmatrix} M \begin{bmatrix} u \\ v \end{bmatrix}$$ 其中矩阵$M$为: $$M = \sum_{x,y} w(x,y) \begin{bmatrix} I_x^2 & I_x I_y \\ I_x I_y & I_y^2 \end{bmatrix}$$ --- ### 3. 角点响应函数 通过矩阵$M$的特征值$\lambda_1, \lambda_2$判断角点: - 若$\lambda_1 \approx \lambda_2 \gg 0$:角点 - 若$\lambda_1 \gg \lambda_2$或$\lambda_2 \gg \lambda_1$:边缘 - 若$\lambda_1 \approx \lambda_2 \approx 0$:平坦区域 **Harris响应函数**: $$R = \det(M) - k \cdot \text{trace}^2(M)$$ 其中: - $\det(M) = \lambda_1 \lambda_2$ - $\text{trace}(M) = \lambda_1 + \lambda_2$ - $k$为经验值(通常取0.04~0.06) --- ### 4. 实现步骤 1. **计算梯度**:使用Sobel算子求$I_x$和$I_y$ 2. **构造矩阵$M$**:对每个像素计算$I_x^2$, $I_y^2$, $I_x I_y$,并用高斯窗口加权 3. **计算响应值$R$**:按公式计算每个像素的$R$值 4. **非极大值抑制**:保留局部邻域内$R$最大的点 5. **阈值处理**:筛选$R > \text{threshold}$的点作为角点 --- ### 5. 特点与应用 #### 优点: - 对旋转具有不变性 - 对光照变化有一定鲁棒性 - 计算效率较高 #### 缺点: - 对尺度变化敏感 - 可能受噪声影响 #### 典型应用: - 图像配准 - 三维重建 - 目标跟踪 --- ### 示例代码(OpenCV) ```python import cv2 import numpy as np img = cv2.imread('image.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray = np.float32(gray) # Harris角点检测 dst = cv2.cornerHarris(gray, blockSize=2, ksize=3, k=0.04) dst = cv2.dilate(dst, None) img[dst > 0.01 * dst.max()] = [0,0,255] # 标记角点 ``` Harris算子为后续特征检测算法(如SIFT、ORB)奠定了基础,是理解图像特征提取的重要起点。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值