我的项目背景及赛题介绍

卫星的利用非常宽泛,许多行业每天都依赖其运作。咱们通常会依据高度把人造地球卫星运行的轨道简略地分类为低轨道(200千米~2000千米)、中轨道(2000千米~20000千米)和高轨道(20000千米以上)。

地球同步静止轨道属于高轨道,与赤道立体成0度角,静止轨道卫星运行方向与地球自转方向雷同,运行周期与地球同步,和地球上的咱们放弃绝对静止,下面运行着很多国家的大型通信卫星。无限的地球同步静止轨道资源宝贵,因而,为使运行中的卫星免受可能的碰撞,对运行空间内空间碎片和天然天体等未知空间指标进行及时的检测、跟踪、预警和编目是“太空捍卫兵士”保障卫星流动失常衰弱的一项重要工作。

本我的项目基于2020年欧空局联结阿德莱德大学举办的地球同步静止轨道及左近的指标检测SpotGEO Challenge比赛,实现“太空捍卫兵士”——太空空间指标检测零碎,从而检测低成本望远镜采集图像中的强劲空间指标,包含空间碎片、非单干飞行器等等。

我的项目链接:https://aistudio.baidu.com/aistudio/projectdetail/2285947?shared=1

数据集介绍

目前,国内上用于空间指标探测辨认的零碎个别包含地基零碎和天基零碎两局部,观测设施包含巡天望远镜和CCD摄像机等等。本较量提供的数据集是由搭载在地基望远镜上的低成本CMOS相机在夜间拍摄失去,相机曝光工夫为40s,间断拍摄5帧成为一个序列。

地基望远镜数据采集示意图

在相机曝光工夫内,除了地球静止轨道左近的指标或天体之外的其余背景恒星与地球存在相对速度,所以在图片中背景恒星出现条纹状。而GEO指标放弃绝对静止,在图像中大多以斑点或短条纹的状态呈现。帧序列拍摄过程中,相机所在的望远镜做匀速转动,所以空间指标的静止轨迹为直线。

数据集示例

这是较量提供的数据集的构造组成,解压后的数据集同级目录下包含train和test两个文件夹以及对应的两个标注文件。训练集和测试集别离蕴含若干序列以及组成序列的帧图像组成的两级目录。图片格式为PNG格局,尺寸大小是640x480,整个数据集的图片总数量为 32000张,其中训练集蕴含1280个序列6400张,测试集5120个序列25600张。

标注文件格式:每幅图像的标注包含四组值,别离为是帧序列号、帧图像序号、指标数量以及对应地位坐标(x,y)。

数据集组成示例

指标个性

咱们把须要解决的问题进一步具体化,概括起来就是星空背景下的序列图像小指标检测。

指标个性: 在图像中,咱们关注的指标在图像里大多以斑点或短条纹的状态呈现,而非齐全以点指标的模式存在,指标整体亮度也较暗,这是因为较长的曝光工夫和大气畸变、传感器缺点等起因产生的像素弥散景象。而且除此之外,因为云层笼罩、大气/天气影响、光污染、恒星遮挡(背景恒星碰巧越过轨道物体地位)等各项情况因素也减少了问题的难度。数据集中会存在异样高亮的伪指标、或者指标对象只呈现在序列内5帧图像中的某几帧中等等问题。

指标静止个性: 咱们利用标注信息将一个序列内的5帧图像的指标地位匹配在一幅图中,出现显著的匀速直线静止轨迹。

问题解析

问题转化

联合指标个性,咱们将数据集中的标注点地位视为bbox标记框的核心地位,取中心点上下左右宽度为3个像素,失去指标标注框。左上角的坐标和右下角的坐标值依据长宽偏移量计算失去,这样将问题转化为类别数为2的指标检测问题。

标注图示

整体开发流程

本我的项目应用飞桨全流程开发工具PaddleX。整个我的项目工作次要包含数据预处理、模型训练及导出以及模型部署三局部:

开发流程

数据预处理过程的工作次要包含:

1.数据荡涤

首先将不存在任何指标的帧序列删除;

#数据荡涤import jsondef read_annotation_file(path):    annotation_list = json.load(open(path))    # Transform list of annotations into dictionary    annotation_dict = {}    for annotation in annotation_list:        sequence_id = annotation['sequence_id']        if sequence_id not in annotation_dict:            annotation_dict[sequence_id] = {}        annotation_dict[sequence_id][annotation['frame']] = annotation['object_coords']   #just pull out the object_coords    return annotation_dictanopath = 'work/train_anno.json'train_annotation= read_annotation_file(anopath)ori_seq = len(train_annotation)print('\n原始序列数量:', ori_seq)#依据num_objects字段删除训练有效序列for i in range(1, ori_seq):    if len(train_annotation[i][1]) == 0:        del train_annotation[i]# train_annotation is data numpyreal_seq = len(train_annotation)print('\n无效序列数量:', real_seq)

2.数据集标注格局转换

为方便使用PaddleX数据接口,将原始的标注文件从新转换为VOC格局

from pycocotools.coco import COCOimport os, cv2, shutilfrom lxml import etree, objectifyfrom tqdm import tqdmfrom PIL import ImageCKimg_dir = './SpotGEOvoc/VOCImages'CKanno_dir = './SpotGEOvoc/VOCAnnotations'def catid2name(coco):  # 将名字和id号建设一个字典    classes = dict()    for cat in coco.dataset['categories']:        classes[cat['id']] = cat['name']        # print(str(cat['id'])+":"+cat['name'])    return classesdef get_CK5(origin_anno_dir, origin_image_dir, verbose=False):    dataTypes = ['train']    for dataType in dataTypes:        annFile = '{}_anno.json'.format(dataType)        annpath = os.path.join(origin_anno_dir, annFile)        print(annpath)        coco = COCO(annpath)        classes = catid2name(coco)        imgIds = coco.getImgIds()        # imgIds=imgIds[0:1000]#测试用,抽取10张图片,看下存储成果        for imgId in tqdm(imgIds):            img = coco.loadImgs(imgId)[0]            showbycv(coco, dataType, img, classes, origin_image_dir, verbose=False)def main():    base_dir = './SpotGEOvoc'  # step1 这里是一个新的文件夹,寄存转换后的图片和标注    image_dir = os.path.join(base_dir, 'VOCImages')  # 在上述文件夹中生成images,annotations两个子文件夹    anno_dir = os.path.join(base_dir, 'VOCAnnotations')    mkr(image_dir)    mkr(anno_dir )    origin_image_dir = './SpotGEOv2'  # step 2原始的coco的图像寄存地位    origin_anno_dir = './SpotGEOv2'  # step 3 原始的coco的标注寄存地位    verbose = True  # 是否须要看下标记是否正确的开关标记,若是true,就会把标记展现到图片上    get_CK5(origin_anno_dir, origin_image_dir, verbose)

3.将原始训练数据进行训练集和验证集划分

!paddlex --split_dataset --format VOC --dataset_dir MyDataset --val_value 0.2 --test_value 0

对于模型的抉择和开发:因为我的项目最终面向端侧部署,所以轻量高效的检测模型是首选。这里我应用的是飞桨特色模型PP-YOLOv2,该模型由百度飞桨团队基于PP-YOLO模型进行优化改良和降级,网络结构如下图所示。Baseline Model为PP-YOLO,骨干网络为ResNet50-vd,组合增加优化组件蕴含Deformable Conv、SSLD、CoordConv、DropBlock、SPP、Larger Batch Size、EMA、IoU Loss、IoU Aware、Grid Sensitive等10个Tricks。

模型训练主体只须要这些代码,配置好数据集格局和门路,而后批改num_classes参数,类别数是除去背景类,也就是总类别数-1。调整设置好一系列训练参数,而后就开始模型训练。

num_classes = 1model = pdx.det.PPYOLOv2(num_classes=num_classes, backbone='ResNet50_vd_dcn')model.train(    num_epochs=3600,    train_dataset=train_dataset,    train_batch_size=4,    eval_dataset=eval_dataset,    learning_rate=0.001 / 8,    warmup_steps=1000,    warmup_start_lr=0.0,    save_interval_epochs=36,    lr_decay_epochs=[216, 243],    save_dir='output/PPyolov2_r50vd_dcn')

而后期待模型训练完评估好后果之后再进行模型导出及部署。

!paddlex --export_inference --model_dir=/home/aistudio/output/PPyolov2_r50vd_dcn/best_model --save_dir=/home/aistudio/inference

最初,本我的项目基于 Nvidia Jetson Nano平台实现了一套理论的演示零碎。

在Jetson NANO开发板上进行飞桨模型部署,从后期筹备到推理程序验证的全流程次要包含以下几局部。

软件局部,端侧推理程序次要是以下三局部,不得不再次赞叹API是真香!

具体的推理代码如下:

## python部署流程import globimport numpy as npimport threadingimport timeimport randomimport osimport base64import cv2import jsonimport paddlex as pdxos.environ['CUDA_VISIBLE_DEVICES']='0'predictor = pdx.deploy.Predictor(model_dir='./infer', use_gpu=True, gpu_id=0, use_trt=True)def get_images(image_path, support_ext=".jpg|.jpeg|.png"):    if not os.path.exists(image_path):        raise Exception(f"Image path {image_path} invalid")    if os.path.isfile(image_path):        return [image_path]    imgs = []    for item in os.listdir(image_path):        ext = os.path.splitext(item)[1][1:].strip().lower()        if (len(ext) > 0 and ext in support_ext):            item_path = os.path.join(image_path, item)            imgs.append(item_path)    return imgsdef crest_dir_not_exist(path):    if not  os.path.exists(path):        os.mkdir(path)def run(img_path,img_name,save_path):    result = predictor.predict(img_file=img_name, warmup_iters=100, repeats=100)    time2= time.time()    pdx.det.visualize(img_name, result, threshold=0.5, save_dir=save_path)    time3 = time.time()    print("Visual Time: {}s".format(time3-time2))if __name__ == "__main__":    test_path = 'visual/'    save_path = 'output/visual/'    crest_dir_not_exist(save_path)    L = get_images(test_path)    N = len(L)    print(N)    for i in range(N):        print(L[i])        run(test_path, L[i],save_path)

理论的后果演示动图如下所示。

以上就是我的分享,感兴趣的小伙伴能够点击下方我的项目链接,一起交流学习吧。

https://aistudio.baidu.com/aist