用于图像标注和图像处理的自定义控件






4.50/5 (8投票s)
2004年5月19日
5分钟阅读

145275

3241
图像处理后图像标注控件的演变。
引言
这是我对之前关于标注的文章的一次重大更新。我宁愿保留原稿,而在这里更专注于代码的演变。
之前的版本有什么问题?
起初,我为“边界点”实现了一个标注类,即可以通过设置定义某个区域边界的点(无论是通过编程还是交互方式)来修改的标注。然后,内部和边界区域会自动使用 GDI+ 生成,这些可以用于命中测试、计算图像属性等。
然而,大多数图像处理算法不使用边界点,而是使用构成由这些边界点定义的区域内部的点。从一组边界点到区域的转换很简单,但反过来则**不**是。因此,我特意为这类“基于区域”的标注编写了另一个类。在这个类中,用户可以设置和操作内部区域本身,而不是边界点。点式和基于区域的标注都继承自一个抽象标注类,该类实现了通用的属性和方法。还有一个用于不定义内部区域的标注的类。通常,当事情变得如此复杂时,设计就存在问题,因此很快就出现了几个问题。最重要的是,绘制基于区域轮廓的边界点非常棘手且速度很慢,并且在缩放时无法正常工作。
为什么 GDI+ 区域对图像处理真的很糟糕
在基于区域的标注中,用户可以设置区域,类会在屏幕上绘制它。这涉及到确定边界区域,例如通过称为形态侵蚀的过程,或者简单地检查区域中点的“连通性”。因此,我开始编写一些用于处理 GDI+ 区域的例程。然而,很快就发现,虽然区域可能是存储不规则形状区域的有效方法,但它们对图像处理来说**效率极低**!事实上,GDI+ 区域中最常用的方法是 `IsVisible`,而且它**非常**慢(我猜想由于区域的编码,位置信息不能直接获得)。此外,在图像处理中,我们会不断地向区域添加和删除非常小的、像素大小的矩形,这再次证明非常慢。带有许多小矩形的复杂区域的缩放速度再次证明非常慢。最糟糕的是,GDI+ 中存在一些令人讨厌的怪癖,例如:你需要一个 `Graphics` 对象来确定边界框,但不需要它来确定一个点是否在区域内……(有人能向我解释一下这个逻辑吗?)。由于标注独立于图像,并且只有在需要时才获得 `Graphics` 对象来在表面上重绘自身,这带来了麻烦。
解决这个问题的方案是使用通常称为“蒙版”图像。这些是位图(这里是字面意思上的 1 位图像),其中包含关于像素是否在区域内或不在区域内的信息。显然,在这里确定一个像素是否在区域内很简单(并且使用不安全 C# 代码速度很快)。将我的图像处理例程重写为使用蒙版而不是区域,带来了巨大的速度提升(10 倍或更多!)。然后,我只需要编写能够将蒙版转换为区域和反之亦然的例程,并设置基于区域标注中的区域以在屏幕上显示它。
蒙版图像
然而,这并没有解决确定基于区域的标注类中区域的边界点的问题,现在大部分处理时间都花在了执行这些操作的例程上。此外,出于未知原因,在确定非常复杂的区域的边界点时,我一直在 `drawing.dll` 中遇到堆栈溢出。
精简的标注模型
所以,别无选择:放弃基于区域的标注,并编写一个可以将蒙版转换为一组(!)基于点的标注的例程。然后,基于点的标注的内部将使用 `graphicsPath` 有效地确定边界和内部区域。这些将完美缩放,并具有提供蒙版所有信息的额外好处:边界点、内部区域和子区域。最重要的是,`annotations` 类变得更加、更加简单。
类 Annotations
包含标注的所有代码及其所有集合的类。
- 类
AnnotationContainer
用于包含标注的类。
- 类
AnnotationContainerCollection
定义强类型容器集合的类。
- 类
Annotation
- 类
AnnotationCollection
定义强类型标注集合的类。
与之前的模型相比,这是一个很大的改进!
从蒙版确定一组封闭轮廓的例程基于一篇题为“一种使用轮廓跟踪技术的线性时间分量标记算法”的文章,作者是 Fu Chang 等人(台湾台北信息科学研究所)。它并未完全实现,但Nonetheless工作得相当好,而且速度非常快。
图像处理
虽然我将在不久的将来专门写一篇文章来介绍我的图像处理例程,但我已将 C# 源代码包含在下载文件中。它远非完成,并非所有例程都经过了彻底测试,但它包含了一些用于处理区域和蒙版的例程,以及算术图像操作、图像极值、中值滤波器、卷积、缩放/重采样、二值形态学(侵蚀、膨胀、开运算、闭运算)等……
结论
- 简单最好:经过 6 个月的不断演变,最终得到了最高效、最简单的类层次结构。
- GDI+ 区域不适合图像处理,请使用蒙版图像。
- 为了让 .NET 获得任何速度,你会发现自己使用大量的 unsafe 代码,这简直又回到了 C:分配内存、释放内存、检查泄漏等……此外,许多 GDI+ 对象不是托管的,你需要非常小心地释放它们!