图像块检测与标记技术详解
在图像处理领域,图像分割是将图像划分为具有共同属性区域的重要操作。常见的分割方法是先通过滤波增强共同属性,再进行阈值处理以检测具有增强属性的像素。不过,这些操作通常是逐个处理像素,为了分析图像,需要将相关像素组关联起来,以便从像素组中提取完整对象的数据。以下将详细介绍几种图像块检测与标记的方法。
1. 边界框
边界框是包含一组像素的最小矩形框,其与像素轴对齐。假设输入像素流已通过预处理操作进行阈值处理或分割,对于与对象 $i$ 相关联的像素集 $C_i$,其边界框的计算方式如下:
[
\begin{align
}
x_{min,i} &= \min { x_p | (x_p, y_p) \in C_i }\
x_{max,i} &= \max { x_p | (x_p, y_p) \in C_i }\
y_{min,i} &= \min { y_p | (x_p, y_p) \in C_i }\
y_{max,i} &= \max { y_p | (x_p, y_p) \in C_i }
\end{align
}
]
最初假设输入图像为二值图像,基本的流处理实现方式是在帧消隐期将
init
设置为 1,仅对检测到的像素进行时钟操作,从而有效忽略背景像素。当检测到第一个像素时,
init
寄存器会将该像素的地址加载到 $x_{min}$、$x_{max}$、$y_{min}$ 和 $y_{max}$ 寄存器中。由于图像按光栅顺序扫描,第一个检测到的像素将提供 $y_{min}$ 值,而每个检测到的像素的 $y$ 值会被时钟输入到 $y_{max}$ 寄存器中。在检测到第一个像素后,会将 $x$ 值与 $x_{min}$ 和 $x_{max}$ 进行比较,并在需要时调整相应的值。在帧结束时,这四个寄存器将指示图像中对象像素的范围。
这个基本实现可以很容易地扩展为每个时钟周期处理多个输入像素。如果同时处理的像素数是 2 的幂次方,则处理起来最为简单。此时,$x$ 地址仅包含地址的最高有效位,需要两个解码器来确定同时输入的最左侧和最右侧像素的最低有效位。这些解码器可以使用 FPGA 内的查找表轻松构建。如果同时处理多行,也可以采用类似的方法。
如果有多个输入类别,可以并行处理它们。由于每个输入像素只能有一个标签,因此可以重用更新逻辑,通过输入像素的标签对寄存器进行多路复用。不过,多路复用器会比实际的更新逻辑使用更多的资源,另一种选择是用 RAM 替换寄存器,并使用内置的 RAM 寻址进行多路复用。$x_{min}$ 和 $x_{max}$ 的 RAM 需要是双端口的,因为需要读取值进行比较。由于通常只有少量标签,使用结构 RAM 可以实现资源高效的实现。
从边界框可以很容易地推导出对象的中心位置、大小和纵横比:
[
\begin{align
}
\text{中心} &= (\frac{x_{max} + x_{min}}{2}, \frac{y_{max} + y_{min}}{2})\
\text{大小} &= (x_{max} - x_{min} + 1, y_{max} - y_{min} + 1)\
\text{纵横比} &= \frac{y_{max} - y_{min} + 1}{x_{max} - x_{min} + 1}
\end{align
}
]
然而,基本的边界框无法区分细长对象的方向。可以通过维护一个累加器
acc
来解决这个问题,每当 $x_{min}$ 被调整时,
acc
递增,每当 $x_{max}$ 被调整时,
acc
递减。在帧结束时,累加器的符号表示对象的方向,对于细长对象,可以估计角度为:
[
\text{角度} \approx \text{sign}(acc) * \arctan(\frac{y_{max} - y_{min}}{x_{max} - x_{min}})
]
使用边界框提取对象范围的主要限制是测量对噪声敏感,因此在使用边界框之前,必须应用适当的滤波来去除噪声。简单边界框的最大优点是处理成本低,如果能成功过滤噪声,它提供了一种提取一些基本对象参数的有效方法。
2. 游程编码
许多中级图像处理算法需要对图像进行多次遍历,在这种情况下,内存带宽通常是处理速度的瓶颈。对于一些图像处理操作,可以将像素游程作为一个单元进行处理,而不是处理单个像素,这样可以显著加速处理。
游程有多种编码方式,标准的图像压缩方法是将每个游程记录为 (类别, 长度) 对。如果后续处理考虑相邻行之间的连通性,也可以使用 (类别, 起始位置) 对记录转换的绝对位置,长度由相邻起始位置的差值隐含给出。对于二值图像,只需记录对象像素游程的起始和结束位置,而无需对背景进行编码,同时需要一个额外的符号来表示行的结束。
由于每行是独立编码的,可以通过构建多个处理器并行处理多行。游程编码可用于纹理特征化,特别是游程长度的分布可用于区分不同的纹理。在图像压缩方面,当图像只有几个不同的灰度值或颜色时,可直接应用于像素。对于一般图像,游程编码单独使用通常效果不佳,但在图像变换后,许多系数被截断为零,此时对零进行游程编码可以显著减少需要存储的系数数量。
3. 链码
链码是一种将图像区域的二维形状简化为一维边界编码的中级表示方法,在许多应用中可以显著减少数据量,从而实现高效的区域特征提取算法。
3.1 顺序实现
标准的链码软件算法是对图像进行光栅扫描,直到遇到未处理的边界,然后暂停扫描,跟踪对象边界并构建对象的链码。该算法从当前边界像素按顺时针顺序查看邻居,找到下一个边界像素并添加相应的链接到链码中,同时标记已跟踪的像素以防止再次检测。边界跟踪继续直到回到第一个像素,完成整个边界的跟踪,然后继续光栅扫描寻找另一个未标记的边界像素。
这种算法不适合流处理实现,因为它需要随机访问图像,处理时间也取决于图像的复杂性。不过,在某些应用中,链码实际上不需要保存,可以在扫描边界时直接计算面积、周长、重心和边界框等特征。扫描过程可以通过使用游程编码作为中间步骤来加速,在第一遍中对图像进行游程编码并确定游程邻接关系,第二遍再进行边界扫描。
3.2 单遍算法
更好的方法是在光栅扫描的一遍中完成整个过程,基本原理是维护一组链码片段,并在扫描每行时扩展每个链码片段的两端。当同时构建多个片段时,需要使用某种形式的链表,链表的存储空间通常比链码本身所需的存储空间大得多。
有多种软件方法使用这种基本技术,如 Cederberg 扫描 3×3 窗口生成链链接,Chakravarty 扫描 3×3 窗口并将构建的段添加到列表中,Shih 和 Wong 使用 3×3 窗口内像素的查找表扩展中裂纹码,Mandler 和 Oberlander 使用 2×2 窗口检测裂纹码中的角点,Zingaretti 等人对灰度图像进行类似的编码。
在流处理环境中,可以通过对像素之间的裂纹进行游程编码来实现,而无需先进行像素的游程编码。这种混合裂纹游程编码由水平游程的长度和一个指示游程结束处的裂纹是连接到上一行还是下一行的位组成。
构建裂纹游程链需要扫描 2×2 窗口,窗口内的像素模式为链接电路提供控制信号。除了形成输入窗口所需的行缓冲区外,还需要另外两个行缓冲区来记录每个片段末端的段和链接编号。在裂纹游程开始时,记录 $x$ 位置,如果链接来自上一行,则保持行缓冲区中的链接条目,否则分配一个新的链接条目并保存。在游程结束时,根据情况读取上一行的链接或创建新链接,并将游程长度数据写入链接表。如果创建了新段,需要分配新的起始指针并保存位置和链接条目;如果发生合并,需要检查链接的段是否属于同一或不同段,并进行相应处理。
如果需要,可以将裂纹游程码转换为传统的裂纹码或 Freeman 链码进行后续处理,也可以直接从边界码重建区域图像。
3.3 特征提取
由于边界包含区域形状的信息,可以从链码(或其他边界码)直接导出许多特征或参数。
-
周长 :简单地计算链码或裂纹码中的步数会因量化效应而高估周长长度。为了克服这个问题,需要通过测量两侧 $k$ 步点之间的距离并取平均值作为每个链接的步长来平滑边界:
[
\text{周长} = \frac{1}{k} \sum_{i} \sqrt{(y_{i + k} - y_i)^2 + (x_{i + k} - x_i)^2}
]
对于长直边界,增加 $k$ 可以将周长估计的误差降低到任意低的水平,但 $k$ 过大可能会低估周长。对于边界粗糙的对象,周长取决于测量的尺度,可以计算分形维数作为特征。 -
角点 :角点可以定义为极端曲率的区域,由于边界的量化效应,局部曲率可能很嘈杂,可以通过考虑相隔 $k$ 个链接的点来平滑。一个简单的角点度量是当前点前后 $k$ 个链接的点之间的角度差:
[
\Delta y_i = \tan^{-1}(\frac{y_{i + k} - y_i}{x_{i + k} - x_i}) - \tan^{-1}(\frac{y_i - y_{i - k}}{x_i - x_{i - k}})
]
当 $\Delta y_i$ 的峰值超过预定义角度时,定义为角点。 -
面积 :测量区域的面积可以通过对边界进行轮廓积分来实现,链码在边界的一侧,可能会低估区域面积和高估孔的面积,而裂纹码没有这个问题。用裂纹码表示的面积计算公式为:
[
\text{面积} = \sum_{j} \sum_{i} \Delta x_i \Delta y_j
]
面积通常比周长度量对数字化误差和噪声不太敏感,通过面积的正负可以区分外部和内部边界,从而计算孔的数量和欧拉数。 -
重心 :重心可以通过第一矩的轮廓积分确定:
[
\begin{align }
x_{COG} &= \frac{S_x}{\text{面积}}, \text{其中 } S_x = \frac{1}{2} \sum_{i} x_i^2 \Delta y_i\
y_{COG} &= \frac{S_y}{\text{面积}}, \text{其中 } S_y = \frac{1}{2} \sum_{i} x_i (y_{i - 1} + y_i) \Delta y_i
\end{align }
]
可以用类似的方法计算高阶矩。 -
凸包 :可以通过边界码确定凸包,对于边界上的点 $i$,如果满足 $ \Delta x_i \Delta y_{i - 1} \leq \Delta x_{i - 1} \Delta y_i $,则该点是凹的,可以将其与前一个点合并。重复此操作直到无法再消除点,剩余的点就是包含该区域的最小凸多边形的顶点。从凸包可以确定海湾的深度,用于分离相邻的凸对象,还可以确定最小面积包围矩形。
-
边界或形状匹配 :链码可用于边界或形状匹配,基本原理是提取边界的一系列形状特征,消除特征向量差异较大的候选匹配,对特征向量相似的进行更详细的比较。也可以将链码分解为多个段进行部分边界匹配。
-
傅里叶描述符 :对于封闭边界,可以使用傅里叶级数分析形状,通过低阶傅里叶级数系数表示形状,该方法对量化噪声相对不敏感,经过归一化后可用于旋转和尺度不变的匹配,还可以从几个系数重建平滑的边界。
4. 连通组件标记
与链码关注边界不同,连通组件标记是为连通组件内的像素分配唯一标签,以便隔离与区域相关的像素并提取该区域的特征。
4.1 随机访问算法
一种方法是基于边界扫描,对图像进行光栅扫描,遇到未标记的对象像素时分配新标签并扫描边界,然后将边界标签传播到对象内部像素。另一种方法是在光栅扫描中遇到未标记像素时进行泛洪填充操作,将其作为新区域的种子像素,填充所有与之相连的像素。这两种方法的主要限制是需要随机访问图像,要求完整的图像存储在帧缓冲区中。
4.2 多遍算法
为了避免随机访问处理,可以从先前标记的连通像素传播标签。在初始光栅扫描中遇到对象像素时,检查其左侧和上方的邻居,如果都是背景像素,则分配新标签,否则传播最小的非零(非背景)标签。对于 U 形对象,可能会为单个连通组件分配多个标签,需要进行第二遍反向光栅扫描,传播最小标签以替换较大的初始标签。对于 W 形对象和螺旋形,可能需要额外的正向和反向扫描,直到图像中不再有变化。
这种多遍算法的优点是电路简单且小,不需要中间存储(除了帧缓冲区),但处理的遍数取决于连通组件的复杂性,处理时间可能较长,图像必须存储在帧缓冲区中。
4.3 两遍算法
可以通过显式跟踪等效标签对,将标签传播减少到两遍。第一遍扫描图像,若邻居没有标签则分配新标签,若邻居只有一个标签则传播该标签,对于 U 形区域出现两个不同标签时,记录标签的等效性在等效表中。第一遍结束后,解析所有等效性并创建查找表,第二遍使用查找表为图像中的每个对象分配最终标签。
为了高效实现,需要一种有效的等效性解析方法,可以在每行部分解析合并,防止冗余标签传播。对于软件实现,第二遍可以通过游程编码加速,但在硬件中,除非图像已经进行了游程编码,否则收益不大。也可以采用并行架构加速标签传播,但许多方法需要大量处理器,在 FPGA 上实现资源消耗大。
4.4 单遍算法
如果只需要提取每个区域的特征数据,而不需要生成标记图像,可以在第一遍扫描中提取所需数据。根据要提取的特征,维护相应的数据表,当两个区域合并时,合并相关数据。例如,使用单个全局计数器确定区域数量,为每个标签维护单独的计数器测量区域面积,维护 $x$ 和 $y$ 坐标的总和确定重心等。
当可以进行单遍处理时,可以扩展架构,使用单端口内存实现数据表,在合并时更新数据。该方法的主要限制是数据表和合并表的大小取决于图像中的初始标签数量,最坏情况下与图像面积成正比。可以通过回收不再使用的标签来优化内存需求。
4.5 多输入标签
如果输入图像是标记图像,处理需要扩展。由于每个输入像素只能有一个标签,可以增强单个处理器的硬件来处理多个输入标签。主要变化是只在具有相同输入标签的区域内传播标签,将不同输入标签视为背景,需要在行缓冲区中缓存输入标签,可能需要两倍数量的标签,因此合并表和数据表需要加倍,但处理过程与单标签情况相同。
4.6 进一步优化
如果要标记或提取的区域是凸的,可以进行进一步简化。由于没有 U 形,相对简单的标签传播就足以在一遍中完全标记图像,不需要之前技术中的合并逻辑。对于 y 形区域,需要防止分配新标签,可以延迟行中像素的标记,直到遇到第一个背景像素,也可以对行缓冲区中的像素进行游程编码并输出流式标记图像。
总结
这些图像块检测与标记方法各有优缺点。边界框简单但对噪声敏感,适用于噪声可有效过滤的情况;链码能在单遍流式处理中完成区域定义,但需要复杂的内存管理;连通组件标记方法根据不同需求有多种实现方式,多遍算法简单但处理时间长,单遍算法适用于只提取特征数据的情况。通过合理选择和应用这些方法,可以在不同的图像处理场景中实现高效的图像分析和特征提取。
以下是几种方法的对比表格:
| 方法 | 优点 | 缺点 | 适用场景 |
| ---- | ---- | ---- | ---- |
| 边界框 | 处理成本低 | 对噪声敏感,无法区分细长对象方向 | 噪声可有效过滤,提取基本对象参数 |
| 链码 | 可单遍流式处理,减少数据量 | 内存管理复杂 | 区域较大且边界相对平滑,需要高效提取区域特征 |
| 连通组件标记 - 随机访问算法 | 处理速度可能较快,内存需求小 | 需要随机访问图像 | 对处理速度要求高,图像可存储在帧缓冲区 |
| 连通组件标记 - 多遍算法 | 电路简单,不需要中间存储 | 处理遍数不确定,处理时间长 | 对电路复杂度要求低,对处理时间要求不高 |
| 连通组件标记 - 两遍算法 | 减少处理遍数 | 等效性解析复杂 | 平衡处理遍数和等效性解析复杂度 |
| 连通组件标记 - 单遍算法 | 可直接提取特征数据 | 数据表和合并表大小取决于初始标签数量 | 只需要提取特征数据,对内存使用要求不高 |
下面是链码单遍算法的流程 mermaid 图:
graph LR
A[开始光栅扫描] --> B[检测到边缘]
B --> C{是否为新边缘}
C -- 是 --> D[开始新链码片段]
C -- 否 --> E[扩展现有链码片段]
D --> F[更新链表和段信息]
E --> F
F --> G{是否到达行尾}
G -- 否 --> B
G -- 是 --> H{是否完成图像扫描}
H -- 否 --> A
H -- 是 --> I[结束]
5. 距离变换
距离变换是为对象像素标记其到最近背景像素距离的操作。不同的距离度量会产生不同的距离变换,常见的距离度量有欧几里得距离、城市街区(曼哈顿)距离和棋盘距离。
- 欧几里得距离 :基于 $L_2$ 范数,计算公式为 $\vert \Delta x, \Delta y \vert_{L_2} = \sqrt{(\Delta x)^2 + (\Delta y)^2}$。但在图像中确定最近背景像素较为困难,因为图像是矩形采样网格。
- 城市街区距离 :基于 $L_1$ 范数,$\vert \Delta x, \Delta y \vert_{L_1} = \vert \Delta x \vert + \vert \Delta y \vert$,它计算水平和垂直像素步数,对角距离会被高估。
- 棋盘距离 :同样基于 $L_1$ 范数,$\vert \Delta x, \Delta y \vert_{L_1} = \max(\vert \Delta x \vert, \vert \Delta y \vert)$,类似于棋盘上国王的步数,对角距离会被低估。
这些非欧几里得度量具有各向异性,为了更好地近似欧几里得距离,同时保持计算简便,人们开发了多种其他度量。
计算距离变换的方法有以下几种:
5.1 形态学方法
通过一系列形态学滤波器对对象进行连续腐蚀。如果每次腐蚀去除一层像素,那么像素到边界的距离就是对象像素变为背景所需的腐蚀次数。使用 3×3 方形结构元素腐蚀可得到棋盘距离,使用十字形结构元素腐蚀可得到城市街区距离。交替使用方形和十字形元素可更接近欧几里得距离。但这种算法需要多次迭代,在 FPGA 上可将迭代实现为流水线,超出一定距离时需保存中间结果并反馈处理。
为了更好地近似欧几里得距离,可以并行应用一系列不同大小的圆形结构元素,相当于使用具有圆锥形结构元素的灰度形态学。通过将其分解为一系列较小的结构元素,可以降低计算复杂度,但对于任意大小的对象,仍需使用有限大小的结构元素进行迭代。
5.2 倒角距离
倒角距离变换通过局部传播计算距离,需要对图像进行两次光栅扫描。第一次正向扫描将距离从顶部和左侧边界传播到对象内部,计算公式为:
[
Q_1[x, y] =
\begin{cases}
0, & I[x, y] = 0 \
\min(Q_1[x, y - 1] + a, Q_1[x - 1, y] + a, Q_1[x - 1, y - 1] + b, Q_1[x + 1, y - 1] + b), & \text{otherwise}
\end{cases}
]
第二次反向扫描将距离从底部和右侧边界传播,计算公式为:
[
Q_2[x, y] = \min(Q_1[x, y], Q_2[x, y + 1] + a, Q_2[x + 1, y] + a, Q_2[x + 1, y + 1] + b, Q_2[x - 1, y + 1] + b)
]
不同的 $a$ 和 $b$ 值会产生不同的距离度量,例如 $a = b = 1$ 时为棋盘距离,$a = 1, b = \sqrt{2}$ 更接近欧几里得距离,为了保持整数运算,常用 $a = 3, b = 4$ 并除以 3,或 $a = 2, b = 3$ 并除以 2。
可以通过并行处理多行来加速倒角距离变换,需要足够的内存带宽同时读取多行数据,每个处理器需要偏移以处理上一行的可用数据。
5.3 可分离变换
如果需要真正的欧几里得距离变换,可以使用可分离算法。由于欧几里得距离的平方 $\vert \Delta x, \Delta y \vert_{L_2}^2 = (\Delta x)^2 + (\Delta y)^2$ 是可分离的,可以先对每行进行一维距离平方变换,再对结果的每列进行变换。
行处理需要两次扫描,正向扫描确定对象到左边缘的距离,反向扫描更新到右边缘的距离:
[
\begin{align
}
Q_1[x, y] &=
\begin{cases}
0, & I[x, y] = 0 \
Q_1[x - 1, y] + 1, & \text{otherwise}
\end{cases}\
Q_2[x, y] &= \min(Q_1[x, y], Q_1[x + 1, y] + 1)
\end{align
}
]
列处理需要找到每个点的最小距离,通过比较不同行的贡献来确定影响区域的边界。该算法易于并行化,可扩展到三维或更高维图像。
距离变换的应用包括:
-
特征提取
:计算对象内距离的统计信息,如均值和标准差,作为大小和形状的度量。距离变换中的脊对应于对象的中轴或骨架,局部最大值对应于最大内切圆的中心。
-
对象计数和分离
:如果对象在距离变换中只有一个局部最大值,可以用于计数对象,结合分水岭变换可分离相邻对象。
-
形态学滤波
:通过对距离变换后的图像进行阈值处理,可以实现快速的二值形态学滤波。
-
模板匹配
:比较距离变换后的图像进行模板或形状匹配,对形状差异更鲁棒。
5.4 测地距离变换
测地距离是区域内两点之间完全在区域内的最短路径距离。可以使用形态学方法,从种子像素开始进行一系列受限的膨胀操作,通过迭代次数确定距离。也可以使用倒角距离变换,但可能需要多次迭代直到距离不再变化。还可以基于 Dijkstra 最短路径算法的变体,使用 FIFO 队列进行广度优先搜索。
测地距离变换可用于机器人导航和路径规划,实现避障和确定最短或最低成本路径。
6. 分水岭变换
分水岭变换与连通组件标记密切相关,它将图像的像素值视为地形地图,根据地形分水岭对图像进行分割。
6.1 流算法
可以通过类似于连通组件分析的方式实现流算法。输入像素流初始标记为零,使用 3×3 窗口确定最小邻居的方向。如果没有像素小于中心像素,则为新的局部最小值(盆地)并分配标签;否则,将像素连接到最小邻居。如果两者都未标记,则分配新标签;如果一个已标记,则传播标签;如果两者都已标记,则记录合并信息。
对于标记图像,可能需要两遍扫描,第一遍进行初始标记和确定连通性,第二遍使用合并表提供最终一致的标记图像。如果可以在第一遍提取每个区域的数据,则可以用数据表代替帧缓冲区。
该算法的一个限制是不能均匀分割位于分水岭上的高原,通常整个高原会被分配到一个标签。可以通过对高原进行距离变换,将像素分配到最近的最小值来解决。
另一种改进的流算法分为四个处理阶段:第一阶段光栅扫描识别高原边界;第二阶段使用 FIFO 队列对高原进行距离变换;第三阶段再次光栅扫描定位局部最小值和未标记的高原;第四阶段使用 FIFO 队列传播每个区域的标签。
6.2 浸没算法
传统的浸没方法从盆地开始,依次增加整个图像的水位,将像素添加到相邻的连通区域。可以通过对像素进行排序来实现,使用直方图和累积直方图进行箱排序,将像素按值顺序排列。
浸没时,按像素值顺序从排序列表或队列中访问像素,将其添加到相邻的边界,如果没有更小的标记像素,则进行高原的测地距离变换,未标记的像素为新的盆地并分配新标签。
6.3 应用
- 图像分割 :在应用边缘检测算子后,边缘成为图像中的脊,对应于分水岭,可将图像沿区域边缘分割。但图像中的噪声会导致过分割,可通过平滑和设置阈值来解决。
- 分离相邻对象 :凸对象在距离变换后通常有一个峰值,反转距离变换将峰值变为盆地,分水岭变换可将每个像素分配到相应的盆地。但非凸对象可能有多个峰值,需要设置小阈值。
- 峰值检测 :可用于检测 Hough 变换后的峰值,反转图像将峰值变为盆地进行单独标记。
7. Hough 变换
Hough 变换是一种从图像中检测对象或特征的技术,最初用于检测直线,可扩展到任何可参数化的形状。基本思想是对图像进行边缘检测,每个边缘像素为与其兼容的参数集投票,在参数空间中积累多维直方图,检测峰值确定潜在对象。
7.1 直线 Hough 变换
直线通常用 $x \cos \theta + y \sin \theta = r$ 参数化,其中 $\theta$ 是直线的角度,$r$ 是直线到图像原点的最近距离。每个边缘点 $ (x, y) $ 在 $ (\theta, r) $ 参数空间中为正弦曲线上的点投票。
- 参数计算 :计算每个点投票的参数需要计算正弦和余弦值,可使用查找表、位串行分布式算术、对数数制或 CORDIC 旋转器等方法。也可以修改参数空间以简化计算。
- 投票积累 :每个检测到的像素在参数空间中为多个箱投票,需要多次内存访问。可以使用自适应 Hough 变换,先进行低分辨率扫描找到显著峰值,再进行高分辨率扫描细化参数。也可以根据边缘方向限制投票角度,减少计算和参数空间的混乱。
- 峰值查找和对象特征 :通过窗口扫描参数空间查找峰值,可结合相邻计数得到更高分辨率的峰值重心。还需要搜索检测到的直线的起点和终点。
7.2 圆 Hough 变换
检测圆需要参数化圆的中心和半径 $(x_c, y_c, r)$,每个检测到的点在三维参数空间中为圆锥表面上的参数投票。可以将三维 Hough 变换转换为三维卷积,也可以根据边缘方向减少计算维度,通过投影到二维空间确定圆心,再通过一维 Hough 变换确定半径。
7.3 广义 Hough 变换
可将上述技术推广到任意形状的对象,通过模板表示对象并参数化位置、尺度和方向,实现基于边缘的模板匹配。
以下是几种变换的对比表格:
| 变换方法 | 优点 | 缺点 | 适用场景 |
| ---- | ---- | ---- | ---- |
| 距离变换 | 可提取多种形状特征,用于对象计数和分离 | 计算复杂,不同度量有误差 | 形状分析、对象分割 |
| 分水岭变换 | 可有效分割图像,分离相邻对象 | 对噪声敏感,可能过分割 | 图像分割、对象分离 |
| Hough 变换 | 对遮挡和噪声不敏感,可检测多种形状 | 计算和内存需求大 | 对象检测、特征提取 |
下面是 Hough 变换检测直线的流程 mermaid 图:
graph LR
A[边缘检测] --> B[参数计算]
B --> C[投票积累]
C --> D[峰值查找]
D --> E[对象特征提取]
E --> F[对象验证和重建]
综上所述,这些图像块检测与标记的方法在图像处理中都有各自的优势和适用场景。在实际应用中,需要根据具体需求和图像特点选择合适的方法,以实现高效准确的图像分析和处理。通过合理组合和优化这些方法,可以进一步提高图像处理的性能和效果。
超级会员免费看
1663

被折叠的 条评论
为什么被折叠?



