主干网络:RestNet50 + FPN + (cls,reg)
把数据分为训练集、验证集、测试集
1.0 设置xml地址和处理数据的存放地址
2.1 得到所有的xml文件
2.2 根据xml文件 和 数据集比例得到各类数据集的下标
3.1 数据集存放地址
3.2 把图片名写入指定文件文
3.3 关闭文件,释放空间。
读取.jpg、.xml文件
1 打开数据集集及最终包含图片.txt文件和.xml的文件;
2 遍历图片名,根据图片名读取图片地址和框及类别信息。
'''
1 model = retinanet.resnet_retinanet(NUM_CLASSES,inputs)
2 priors = get_anchors(model)
3 bbox_util = BBoxUtility(NUM_CLASSES, priors)
4 设置训练集和验证集数量、训练参数设置
5 model.compile()、model.fit_generator()
6 制作标签 gen = Generator(bbox_util, BATCH_SIZE, lines[:num_train], lines[num_train:],
(input_shape[0], input_shape[1]),NUM_CLASSES)
7 损失函数 smooth_l1()、focal()
'''
''' predict.py
1 导入模型
2 输入图片地址
3 打开图片,如果没有打开,就报错
4 预测
5 显示预测结果
6 函数导图:
6.1 retinanet = Retinanet() # 实例化对象
6.2 r_image = retinanet.detect_image(image) # 检测目标
6.2.1 crop_img,x_offset,y_offset = letterbox_image(image, [self.model_image_size[0],self.model_image_size[1]]) # [600,600,3] 图像加灰条
6.2.2 photo = preprocess_input(np.reshape(photo,[1,self.model_image_size[0],self.model_image_size[1],self.model_image_size[2]])) # 图片归一化
6.2.3 preds = self.retinanet_model.predict(photo) # 预测
6.2.4 self.prior = self._get_prior() # 得到先验框
6.2.5 results = self.bbox_util.detection_out(preds,self.prior,confidence_threshold=self.confidence) # 解码
6.2.6 筛选出其中得分高于confidence的框[box_4,conf_1,label_1]
6.2.7 boxes = retinanet_correct_boxes(top_ymin,top_xmin,top_ymax,top_xmax,np.array([self.model_image_size[0],self.model_image_size[1]]),image_shape) # 去掉灰条 ??????
6.2.8 画图
'''
4_(6.2.1) 图像加灰条
# 6.2.1 图像加灰条:通过图像加灰条,所有的图像都统一到相同尺寸(600,600,3),防止图片失真
crop_img,x_offset,y_offset = letterbox_image(image, [self.model_image_size[0],self.model_image_size[1]])
'''
inputs :image图片(1330,1330,3); self.model_image_size[0]=self.model_image_size[1]=600
outputs:crop_img,x_offset,y_offset
基本思想:计算目标图片和原图片宽高的最小比例,最小比例*原图片尺寸=新图片尺寸,新图片与目标图片差异的尺寸用灰条代替。
1. 根据目标尺寸和原图片尺寸计算得到新图片尺寸
2. 双线性插值法重新设置图片大小
3. 生成一张灰度图
4. 把新图粘在灰度图上就生成目标图片
5. 目标图片和新图片宽高的偏移比
'''
4_(6.2.2) 图片归一化:
'''
1. /127.5-1
2. (x-mean)/std
'''
4_(6.2.3) 预测
#
# preds = self.retinanet_model.predict(photo)
# 预测 RestNet50 + FPN + cls,reg+ anchor +
'''
retinanet_model = retinanet.resnet_retinanet(self.num_classes,inputs)
RestNet50 + FPN + (cls,reg)
Input:[-1,600,600,3]
Outputs: [] []
1. RestNet50
2. FPN
3. (cls,reg)
'''
######################## RestNet50 #######################
1 RestNet50_body
Inputs:[-1,600,600,3]--->Outputs:[y0,y1,y2,y3][150,150,256],[75,75,512],[38,38,1024],[19,19,2048]
inputs[600,600,3]-->
Z(3,3)C(64,(7,7),(2,2))-->[300,300,64]
BA('relu')M((3,3),(2,2))[150,150,64]-->
convblock+identityblock*2[150,150,256]-->
convblock+identityblock*3[75,75,512]-->
convblock+identityblock*5[38,38,1024]-->
convblock+identityblock*2[19,19,2048]
2 convblock 瓶颈结构+调整特征图大小
input_tensor-->CBA(1*1)-->CBA(3*3)-->CB(1*1)+CB(input_tensor)-->A
3 identityblock 瓶颈结构+调整特征图数量
input_tensor-->CBA(1*1)-->CBA(3*3)-->CB(1*1)+(input_tensor)-->A
'''
######################## FPN #############################
inputs: C3, C4, C5 = [150,150,256],[75,75,512],[38,38,1024],[19,19,2048]
outputs:[P3, P4, P5, P6, P7] = [75,75,256],[30,30,256],[19,19,256],[10,10,256],[5,5,256]
c5[19,19,2048]-->conv2d*2-->p5 [19,19,256]
c5-->conv2d(stride=2)-->p6 [10,10,256]
p6-->conv2d(stride=2)-->p7 [5,5,256]
conv(C4)+upsample(c5)==Add1-->conv2d-->p4 [30,30,256]
upsample(Add1)+ conv2d(C3)-->conv2d-->p3 [75,75,256]
######################### cls,reg ########################
inputs:[P3, P4, P5, P6, P7] = [75,75,256],[30,30,256],[19,19,256],[10,10,256],[5,5,256]
outputs_regressions: [-1,4]
outputs_classifications : [-1,cls]
inputs--> conv2d*4(256)-->conv2d(num_anchors * 4)-->reshape(-1,4)
inputs--> conv2d*4(256)-->conv2d(num_classes * num_anchors)-->reshape(-1,num_classes)
regression_model = make_last_layer_loc(num_classes,num_anchors)
classification_model = make_last_layer_cls(num_classes,num_anchors)
4_(6.2.4) 先验框 self.prior = self._get_prior()
'''
1. get_anchors(model) # 得到框的边长
# (scales*base)**2--> areas --> sqrt(areas /ratios) -->anchors[:,2]
# anchors[:,2]*ratios--> anchors[:,3]--> anchors
2. shift(shape, stride, anchors) #
# shape+stride-->shifts --> shifts+anchors --> shifted_anchors
3. generate_anchors(base_size=16, ratios=None, scales=None) # 遍历所有的特征层,计算对应的先验框
'''
4_(6.2.5) 解码 results = self.bbox_util.detection_out(preds,self.prior,confidence_threshold=self.confidence)
# detection_out(preds,self.prior,confidence_threshold=self.confidence)
'''
detection_out(preds,self.prior,confidence_threshold=self.confidence)
1. decode_bbox = self.decode_boxes(mbox_loc[i], mbox_priorbox)
(1) 获得先验框的宽与高
(2) 根据公式获取真实框的左上角与右下角
2. 根据预测概率的阈值,筛选框、概率、类别
3. 对种类进行循环可以帮助我们对每一个类分别进行非极大抑制。
(1) 按照概率对detection[框4,概率1、类别1]从大到小排列。
(2) 把detection第一个数据添加到best_box,计算detection[1;]的框与第一个框的iou,保留iou小于阈值的框
(3) 持续以上步骤,直到detection的数量等于1
'''
# 筛选出其中得分高于confidence的框
'''
1. conf >= self.confidence
'''
# 去掉灰条
'''
boxes = retinanet_correct_boxes(top_ymin,top_xmin,top_ymax,top_xmax,np.array([self.model_image_size[0],self.model_image_size[1]]),image_shape)
1. 计算new_shape、offset、scale
2. 对框按照offset、scale进行放缩
'''
'''
1.
2.
3.
'''