天天看点

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

作者:历史安利官

文|历史安利官

编辑|历史安利官

星体跟踪模块主要负责在天文观测图像中,寻找一颗适合导星的星体,将其作为目标星,并在后来的每一帧天文相机拍摄的图像中寻找这一个特定的目标星,记录其变历史。

星体跟踪模块的输入是天文相机拍摄的观测图像,而对外提供了关于目标星、目标星历史的相关信息。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

为了能够在天文观测图像中确定目标星,星体跟踪的实现分为两步:

首先,在天文观测图像中找到所有星体;

然后,在找到的星体中通过比较找到最适合导星的星体。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

据此可知,星体跟踪的实现需要两个功能,即星体寻找和星体评价。

因此,星体跟踪模块的实现实际上引用了星体寻找和星体评价模块。

由于星体评价模块比较小,而且结构设计与图像分割等模块类似。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

星体定位

代理模式,顾名思义就是让一个类做另一个类的代理,然后代替完成那另一个类的任务。

这样便需要前者拥有后者的接口,于是,与装饰类类似,代理类和被代理类共用一个接口以提供相同的功能。

这样,第三方类就可以通过代理类的接口访问被代理类的信息,并使用被代理类提供的功能了。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

具体步骤如下:

1.代理类与被代理类实现同一套接口标准;

2.代理类在内部保存被代理类的引用,并且其统一接口的实现使用保存的引用调用相应被代理类的方法;

3.第三方类只与代理类交互,获得功能实现,与被代理类之间没有直接联系。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

这一模式其实R是为被代理类和第三方类之间创建了一个中间通信渠道,对于功能的实现本身并没有任何影响。

其主要作用是隔离开第三方类和被代理类,将它们之间的直接通信或联系转化为间接的或者是第三方类和被代理类之间本来就无法进行直接的通信。

此时,釆用代理模式便可提供一个中间类来转发交互信息,完成两者的交互。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

导星算法在模块之间的组织上参考了实体之间的关系,即让代表天文望远镜的类在内部包含(组合)代表天文相机和代表赤道仪的类对象。

在更上层,实现导星逻辑的导星类会包含代表天文望远镜类,于是,导星类便无法与底层的天文相机和赤道仪类进行直接交流。

但是,导星类对于导星逻辑的实现需要使用相机的拍摄、赤道仪的校准,转动等功能。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

因此,我便让天文望远镜类代理天文相机类和赤道仪类,对导星逻辑的实现提供支持。

采取这种方法,可以让导星类和代表底层硬件实体的类之间分隔开来,降低之间的耦合度,底层实现的改变就不会对上层实现产生影响,提高了软件整体的可维护性和可扩展性。

策略模式,这一模式的采用可以让软件在运行时,更换功能实现的策略。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

这里所指的策略代表了实现方式,也就是说,在保持总体逻辑不变的情况下,可以更换局部使用的具体方法。

为了使得这种更换不会影响包含控制逻辑在内的上层调用代码,同样的,各个.策略必须维护统一接口。

在此之上,为了能够进行动态更换,上层使用策略的类就需要保存一个定义接口的引用,来引用具体的策略实现。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

具体步骤如下:

1.定义策略类的统一接口,让所有的具体策略类实现这一接口;

2.在使用策略的类中定义策略类的接口引用,并且提供更换策略的接口(setter)

3.使用策略的类可以在运行时创建新的策略,经过更换策略的接口进行更换后,同样的逻辑就使用了新更换完毕的策略实现。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

策略类的基本思想和多态相似,如果将策略的统一接口定义为虚函数,然后让使用策略的类根据具体策略分类,派生出相应的子类。

最后,子类按具体策略的实现重写虚函数便可以得到同样的结果。

在运行时,只要用父类的引用指向不同的子类即可。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

然而这种做法却有以下几个缺点:

将策略的接口混合在了使用策略类的接口中,使得接口更加复杂;

使用继承关系将策略分类和使用策略的类紧密的耦合在了一起,策略的修改会影响使用策略类的类结构。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

而反观策略模式,则是很好的将策略类的结构与使用策略类的结构分了开来,并且采用耦合程度较低的组合方式完成了对策略类的引用和更换。

由此一来,只要接口不变,策略类的修改便与使用策略类无关,巧妙的斩断了两个类的直接关联。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

导星算法使用策略模式来支持多种共同用途算法的更换,比如完成图像预处理的算法,可以有高斯去嗓,可以有维纳滤波等不同的去嗓算法。

将不同实现但相同用途的算法作为策略,然后导星算法的总逻辑使用这些策略,就可以在算法整体逻辑不变的同时,根据具体的应用场景改变某个部分使用的具体算法,达到更好的效果。

如此一来,导星算法的软件实现就获得了更好的灵活性,可扩展性。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

图像分割

为了在寻找星体时,将星体像素和背景像素区分开来,导星算法的星体定位步骤使用了图像分割算法。

根据对设计模式的讨论,本文提出的导星算法在设计图像分割功能实现的结构时,采用了策略模式,并为图像分割功能定义了一个专门的模块。

这一模块大致由抽象基类的继承(接口的实现)构成整体结构。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

抽象基类(接口)ImageThresh定义了图像分割功能的统一接口,将其定义为纯虚函数以迫使子类实现具体操作,并利用了C++中的函数调用操作符重载来提高使用的便利性。

具体的图像分割功能实现即为ImageThresh的子类,对其定义的纯虚函数进行具体实现,并根据具体实现使用的算法之间的关系,组织成树状的结构。

这样,使用图像分割功能的模块就可以按照策略模式的模板那样,对已经实现好的图像分割具体方法进行调用,以及任意的更换。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

导星算法的软件实现由于这样的设计,其灵活性和可扩展性得到了极大的提升

星体定位

星体定位模块的主要功能就是根据传入的星体图像,计算代表整个星体的中心位置。

传入星体定位模块的星体图像是仅仅包含单个星体的一个适当大小的矩形区域,通过对矩形区域中星体像素的考察,星体定位模块返回星体中心的位置。

在结构上,与图像分割模块类似,星体定位模块也是被当做了策略模式中的策略一角。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

星体定位模块定义StarLocator为定义接口的抽象基类,然后具体的星体定位算法由此类的子类来实现。

星体定位类结构和图像分割类结构非常相似,只是负责的功能不同,相应的接口不同。

因此,将星体定位模块独立出来,同样有助于提高导星算法软件实现的灵活性、可扩展性以及可维护性。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

星体过滤

在星体寻找模块从天文观测照片中找到星体之后,其数目可能很多,为了能够从中找出适合导星的目标星体,导星算法引入了星体过滤的功能。

星体过滤的具体实现是通过构建一系列的过滤规则,然后对特定的星体根据规则进行判断,是保留还是剔除同时,为了增强灵活性,星体过滤模块中的过滤规则之间需要能够动态组合,即运行时根据具体环境要求进行调整。

导星算法在实现星体过滤这一模块时,除了使用接口和继承之外,为了能够支持灵活动态的规则组合。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

根据前面的讲解,装饰模式中的结构定义了装饰类和被装饰类。

在将此模式运用到星体过滤模块上时,并没有发现明显的装饰与被装饰关系,所有过滤规则的地位其实是相同的。

根据装饰模式的结构在星体过滤规则的实现上做了一些修改,定义了一个默认的过滤规则。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

这一默认的过滤规则直接返回通过的结果,并且充当装饰模式中被装饰类的角色。

如此一来,便可以将其他具体的过滤规则实现为装饰类。

从装饰模式的角度来看,为被装饰类添加新功能就是为整个过滤器添加新的规则,然后将新规则的结果与原有规则的结果,通过布尔运算整合起来。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

星体过滤类定义了StarFilter抽象基类来作为星体过滤模块的接口。

默认的星体过滤规则继承了此抽象基类,并实现其过滤接口方法filterStar。

然后,通过从StarFilter接口中派生出一个装饰器类的抽象基类,装饰器的基本功能得到实现。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

最后,只要根据具体过滤规则的要求,继承装饰器类,实现过滤接口,即可完成装饰器类的实现。

由于星体过滤模块使用了装饰器模式,具体的过滤器在构造时与一般的类对象的构造之间有些区别。

构造时需要一步一步创建独立的过滤规则,然后再将它们整合起来。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

具体步骤如下:

1.构建默认的过滤规则;

2.一步一步将具体的过滤规则构建起来,设定好相应的参数;

3.使用装饰器类的设置方法或构造函数,将被装饰器类的引用保存入装饰器类;

4.使用最后结合完成的装饰器类来过滤星体,即可达到过滤规则结合的目的。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

在装饰器模式的帮助下,星体过滤的规则可以在程序运行时进行动态调整,如增减规则,调整规则的参数等操作。

如果使用普通的接口和继承方式,那么不止是各个独立的规则需要创建一个类来实现过滤,每种可能的规则组合要在程序运行时能够调整,就需要为每种组合来定义一个新的类,并实现星体过滤接口。

这是一个很大的工作量,特别是当星体过滤规则需要新增规则时。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

由此可以看出,使用装饰器模式,不仅将规则的结合和调整机会延伸到了运行时,更为规则实现的变更构建了一个抽象隔离,这极大地提高了导星算法程序实现的灵活性和可扩展性。

星体寻找星体寻找模块的任务是,在天文图片中找出其中存在的星体,并根据星体图像计算能够代表星体的中心位置。

与图像分割模块类似,星体寻找定义了StarFinder抽象基类来定义接口。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

接口同样以纯虚函数fmdStars的形式定义,具体的寻找算法会对这一接口进行实现不过,同样作为策略摸式使用的一环,星体寻找模块不仅处于图像分割模块所代表的策略角度,即向更上层的模块提供寻找星体功能的实现,还是使用策略的一方。

星体寻找模块引用了之前提到的图像分割、星体过滤以及星体定位模块,即采用了图像分割、星体过滤以及星体定位的策略来完成星体寻找的功能。

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

根据策略模式的设计思路,星体寻找类StarFinder在构造时引入了对图像分割、星体过滤、星体定位模块接口类的引用,并且也提供了设置接口以方便更换具体的实现子类。

这些引用会指向具体的策略实现,作为使用方,StarFinder类的子类只需要直接调用上述引用模块定义的接口即可。

而不用关心具体实现的是哪一个算法,上述引用模块中具体算法实现的更改也不会影响到星体寻找模块。

参考文献

天文导星的各类模式,使用与工作状态,接口之间的互相转接信息

继续阅读