doanh25032004's picture
Upload folder using huggingface_hub
872b0a0 verified
Raw
History Blame Contribute Delete
35.8 kB
# -*- coding: utf-8 -*-
import os
from utils.tools import tools
import cv2
import numpy as np
from copy import deepcopy
import torch
import warnings # ignore warnings
import torch.nn.functional as F
import torch.optim as optim
from dataset.kitti_dataset import kitti_train, kitti_flow
from model.upflow import UPFlow_net
from torch.utils.data import DataLoader
import time
''' scripts for training:
1. simply using photo loss and smooth loss
2. add occlusion checking
3. add teacher-student loss(ARFlow)
'''
class Trainer_model(tools.abs_test_model):
class config(tools.abstract_config): # TODO
def __init__(self, **kwargs):
self.lr = 1e-2
self.weight_decay = 1e-5
self.optmizer_name = 'adam'
self.gamma = 0.95
self.gpu_opt = None # None is multi GPU
self.model_path = '/data/luokunming/Optical_Flow_all/training/unsup_PWC_flyc_photo_smooth/unsupPWC_epoch_27_Flyc_epe_error(5.125).pth' # loading the model
self.load_relax = False # load the pretrain model的时候是不是放宽松要求
self.print_every = 20
# parameters of spatial transform
self.if_train_sp = False # 开关,是否使用spatial transform增强
self.sptrans_add_noise = True
self.sptrans_hflip = True
self.sptrans_rotate = [-0.01, 0.01, -0.01, 0.01]
self.sptrans_squeeze = [1.0, 1.0, 1.0, 1.0]
self.sptrans_trans = [0.04, 0.005]
self.sptrans_vflip = True
self.sptrans_zoom = [1.0, 1.4, 0.99, 1.01]
self.spatial_trans_if_mask = True # 在spatial transform蒸馏的时候使用使用occ mask
self.spatial_trans_eps = 0.0
self.spatial_trans_q = 1.0
self.spatial_trans_loss_weight = 0.01 # 计算在loss里面的权重
self.sp_input_or_sp_input = 1
self.train_sp_msd_loss_weight = 0 # sp的时候也算多尺度的损失
self.train_sp_msd_loss_style = 'down' # 暂时只有'down'和'up'
self.final_sp_train_weight = 0 # 用clean的输出来监督一波final, 必须要'sp_input_or_sp_input' <=0才能使用
self.final_sp_train_style = 'down' # 暂时没有用,
self.multi_scale_eval = False # 验证的时候也对比计算多尺度的结果
self.train_dir = '/data/luokunming/Optical_Flow_all/training/demo_unsupervised_train' # 这个参数主函数里面会设置
self.update(kwargs)
def __call__(self, net_work: tools.abstract_model):
# load network
if self.model_path is not None:
net_work.load_model(self.model_path, if_relax=self.load_relax)
return Trainer_model(self, net_work)
def __init__(self, conf: config, net_work: tools.abstract_model):
super(Trainer_model, self).__init__(conf=conf, net_work=net_work)
self.conf = conf
self.net_work=net_work
if self.conf.optmizer_name == 'adam':
self.optimizer = optim.Adam(self.net_work.parameters(), lr=self.lr, amsgrad=True, weight_decay=self.weight_decay)
else:
raise ValueError('wrong optmizer name: %s' % self.conf.optmizer_name)
self.data_clock = tools.Clock_luo()
self.msd_loss_meter = tools.AverageMeter()
self.sp_msd_loss_meter = tools.AverageMeter()
self.final_sp_loss_meter = tools.AverageMeter()
self.app_loss_meter = tools.AverageMeter()
self.appd_loss_meter = tools.AverageMeter()
self.inpaint_img_loss_meter = tools.AverageMeter()
self.spatial_trans_loss_meter = tools.AverageMeter()
self.multi_scale_loss_meter = tools.AverageMeter()
self.census_loss_meter = tools.AverageMeter()
self.best_name = ''
self.occ_check_model = tools.occ_check_model(occ_type=self.conf.occ_type, occ_alpha_1=self.conf.alpha_1, occ_alpha_2=self.conf.alpha_2,
sum_abs_or_squar=self.conf.occ_check_sum_abs_or_squar, obj_out_all=self.conf.occ_check_obj_out_all)
self.print_str = ''
self.cnt = 0
self.temp_save_eval_test = []
# ===== spatial transform =====
'''
class config():
def __init__(self):
self.add_noise = False
self.hflip = False
self.rotate = [-0.01, 0.01, -0.01, 0.01]
self.squeeze = [1.0, 1.0, 1.0, 1.0]
self.trans = [0.04, 0.005]
self.vflip = False
self.zoom = [1.0, 1.4, 0.99, 1.01]
'''
class sp_conf():
def __init__(self, conf):
self.add_noise = conf.sptrans_add_noise # False
self.hflip = conf.sptrans_hflip # False
self.rotate = conf.sptrans_rotate # [-0.01, 0.01, -0.01, 0.01]
self.squeeze = conf.sptrans_squeeze # [1.0, 1.0, 1.0, 1.0]
self.trans = conf.sptrans_trans # [0.04, 0.005]
self.vflip = conf.sptrans_vflip # False
self.zoom = conf.sptrans_zoom # [1.0, 1.4, 0.99, 1.01]
self.sp_transform = tools.SP_transform.RandomAffineFlow(
sp_conf(self.conf), addnoise=self.conf.sptrans_add_noise).cuda() #
def train_batch(self, batch_step, im1, im2, *args, **kwargs): # 训练一个batch
if self.data_clock.start_flag:
self.data_clock.end()
if_print = batch_step % self.conf.print_every == 0
frame_1_ls = []
frame_2_ls = []
print_str = '%s %s Epoch%d Iter%d [%.4fs]' % (self.conf.print_name, self.best_name, self.epoch, batch_step, self.data_clock.get_during())
if_show = batch_step % self.conf.show_every == 0 and self.conf.show_every > 0
batch_N = im1.shape[0]
im1_crop_ori, im2_crop_ori, start = args
sp_img1_ori, sp_img2_ori = kwargs['im1_crop_at'], kwargs['im2_crop_at'] # final的图片
_, _, h_, w_ = im1_crop_ori.size()
# self.save_image(im1, 'im1')
# self.save_image(im2, 'im2')
# self.save_image(im1_crop_ori, 'im1_crop_ori')
# self.save_image(im2_crop_ori, 'im2_crop_ori')
# self.save_image(sp_img1_ori, 'sp_img1_ori')
# self.save_image(sp_img2_ori, 'sp_img2_ori')
# while True:
# print('return')
# time.sleep(1)
# 决定输入给网络的数据
im1_crop, im2_crop = im1_crop_ori, im2_crop_ori
# ============================================================= 网络输出 ===================================================================
self.optimizer.zero_grad()
# =========== 计算photo loss和smooth loss以及census loss ===========
if self.conf.model_name.lower() in ['pwcirrbiv5_v4', ]:
input_dict = {'im1': im1_crop, 'im2': im2_crop, 'im1_sp': sp_img1_ori, 'im2_sp': sp_img2_ori,
'im1_raw': im1, 'im2_raw': im2, 'start': start, 'if_loss': True, 'if_show': if_show}
output_dict = self.net_work(input_dict)
flow_fw, flow_bw = output_dict['flow_f_out'], output_dict['flow_b_out']
occ_fw, occ_bw = output_dict['occ_fw'], output_dict['occ_bw']
photo_loss, smooth_loss, census_loss = output_dict['photo_loss'].mean(), output_dict['smooth_loss'].mean(), output_dict['census_loss']
im1_warp = output_dict['im1_warp']
im2_warp = output_dict['im2_warp']
loss = photo_loss + smooth_loss
if census_loss is None:
pass
else:
census_loss = census_loss.mean()
loss += census_loss
self.census_loss_meter.update(val=census_loss.item(), num=batch_N)
print_str += ' cens %.4f(%.4f)' % (self.census_loss_meter.val, self.census_loss_meter.avg)
if output_dict['msd_loss'] is None:
pass
else:
msd_loss = output_dict['msd_loss'].mean()
loss += msd_loss
self.msd_loss_meter.update(val=msd_loss.item(), num=batch_N)
print_str += ' msd %.4f(%.4f)' % (self.msd_loss_meter.val, self.msd_loss_meter.avg)
if 'app_loss' not in output_dict.keys():
pass
elif output_dict['app_loss'] is None:
pass
else:
app_loss = output_dict['app_loss'].mean()
loss += app_loss
self.app_loss_meter.update(val=app_loss.item(), num=batch_N)
print_str += ' app %.4f(%.4f)' % (self.app_loss_meter.val, self.app_loss_meter.avg)
self.photo_loss_meter.update(val=photo_loss.item(), num=batch_N)
self.smooth_loss_meter.update(val=smooth_loss.item(), num=batch_N)
print_str += ' ph %.4f(%.4f)' % (self.photo_loss_meter.val, self.photo_loss_meter.avg)
print_str += ' sm %.4f(%.4f)' % (self.smooth_loss_meter.val, self.smooth_loss_meter.avg)
elif self.conf.model_name.lower() in ['pwcirrbiv5_v5', ]:
input_dict = {'im1': im1_crop, 'im2': im2_crop, 'im1_sp': sp_img1_ori, 'im2_sp': sp_img2_ori,
'im1_raw': im1, 'im2_raw': im2, 'start': start, 'if_loss': True, 'if_show': if_show}
output_dict = self.net_work(input_dict)
flow_fw, flow_bw = output_dict['flow_f_out'], output_dict['flow_b_out']
occ_fw, occ_bw = output_dict['occ_fw'], output_dict['occ_bw']
photo_loss, smooth_loss, census_loss = output_dict['photo_loss'].mean(), output_dict['smooth_loss'].mean(), output_dict['census_loss']
im1_warp = output_dict['im1_warp']
im2_warp = output_dict['im2_warp']
loss = photo_loss + smooth_loss
if census_loss is None:
pass
else:
census_loss = census_loss.mean()
loss += census_loss
self.census_loss_meter.update(val=census_loss.item(), num=batch_N)
print_str += ' cens %.4f(%.4f)' % (self.census_loss_meter.val, self.census_loss_meter.avg)
if output_dict['msd_loss'] is None:
pass
else:
msd_loss = output_dict['msd_loss'].mean()
loss += msd_loss
self.msd_loss_meter.update(val=msd_loss.item(), num=batch_N)
print_str += ' msd %.4f(%.4f)' % (self.msd_loss_meter.val, self.msd_loss_meter.avg)
if 'occ_loss' not in output_dict.keys():
pass
elif output_dict['occ_loss'] is None:
pass
else:
occ_loss = output_dict['occ_loss'].mean()
loss += occ_loss
self.occ_loss_meter.update(val=occ_loss.item(), num=batch_N)
print_str += ' occ %.4f(%.4f)' % (self.occ_loss_meter.val, self.occ_loss_meter.avg)
self.photo_loss_meter.update(val=photo_loss.item(), num=batch_N)
self.smooth_loss_meter.update(val=smooth_loss.item(), num=batch_N)
print_str += ' ph %.4f(%.4f)' % (self.photo_loss_meter.val, self.photo_loss_meter.avg)
print_str += ' sm %.4f(%.4f)' % (self.smooth_loss_meter.val, self.smooth_loss_meter.avg)
else:
raise ValueError('wrong model: %s' % self.conf.model_name)
# =========== 计算spatial transform的等变损失 ===========
if self.conf.if_train_sp:
# s = {'imgs': [sp_img1, sp_img2], 'flows_f': [flow_fw], 'masks_f': [occ_fw]}
# s=deepcopy(s)
if self.conf.sp_input_or_sp_input >= 1: # 取clean的图片算sp
sp_img1, sp_img2 = im1_crop_ori, im2_crop_ori
elif self.conf.sp_input_or_sp_input > 0:
if tools.random_flag(threshold_0_1=self.conf.sp_input_or_sp_input):
sp_img1, sp_img2 = sp_img1_ori, sp_img2_ori
else:
sp_img1, sp_img2 = im1_crop_ori, im2_crop_ori
else: # 取final的图片算sp
sp_img1, sp_img2 = sp_img1_ori, sp_img2_ori
flow_fw_pseudo_label, occ_fw_pseudo_label = flow_fw.clone().detach(), occ_fw.clone().detach()
flow_bw_pseudo_label, occ_bw_pseudo_label = flow_bw.clone().detach(), occ_bw.clone().detach()
# 使用final的数据多train一次
if self.conf.final_sp_train_weight > 0 and self.conf.sp_input_or_sp_input <= 0:
input_dict_final_sp = {'im1': sp_img1_ori, 'im2': sp_img2_ori, 'if_loss': False,
'if_final_sp_train': True, 'final_sp_train_style': self.conf.final_sp_train_style,
'final_fw_label': flow_fw_pseudo_label, 'final_fw_occ': occ_fw_pseudo_label,
'final_bw_label': flow_bw_pseudo_label, 'final_bw_occ': occ_bw_pseudo_label}
output_dict_final_sp = self.net_work(input_dict_final_sp)
if output_dict_final_sp['final_sp_loss'] is None:
pass
else:
final_sp_loss = output_dict_final_sp['final_sp_loss'].mean() * self.conf.final_sp_train_weight
loss += final_sp_loss
self.final_sp_loss_meter.update(val=final_sp_loss.item(), num=batch_N)
print_str += ' finalsp %.4f(%.4f)' % (self.final_sp_loss_meter.val, self.final_sp_loss_meter.avg)
s = {'imgs': [sp_img1, sp_img2], 'flows_f': [flow_fw_pseudo_label], 'masks_f': [occ_fw_pseudo_label]}
st_res = self.sp_transform(s)
flow_t, noc_t = st_res['flows_f'][0], st_res['masks_f'][0]
# run 2nd pass spatial transform
im1_crop_st, im2_crop_st = st_res['imgs']
if self.conf.train_sp_msd_loss_weight > 0:
input_dict_sp = {'im1': im1_crop_st, 'im2': im2_crop_st, 'if_loss': False,
'if_sp_msd_loss': True, 'fw_pseudo_label': flow_t, 'fw_occ_pseudo': noc_t, 'sp_msd_loss_style': self.conf.train_sp_msd_loss_style}
else:
input_dict_sp = {'im1': im1_crop_st, 'im2': im2_crop_st, 'if_loss': False}
output_dict_sp = self.net_work(input_dict_sp)
flow_fw_st, flow_bw_st = output_dict_sp['flow_f_out'], output_dict_sp['flow_b_out']
if not self.conf.spatial_trans_if_mask:
noc_t = torch.ones_like(noc_t)
if self.conf.spatial_trans_q <= 0:
l_atst = (flow_fw_st - flow_t).abs()
else:
l_atst = ((flow_fw_st - flow_t).abs() + self.conf.spatial_trans_eps) ** self.conf.spatial_trans_q
l_atst = (l_atst * noc_t).mean() / (noc_t.mean() + 1e-6)
l_atst *= self.conf.spatial_trans_loss_weight
loss += l_atst
self.spatial_trans_loss_meter.update(val=l_atst.item(), num=batch_N)
print_str += ' sp %.4f(%.4f)' % (self.spatial_trans_loss_meter.val, self.spatial_trans_loss_meter.avg)
if output_dict_sp['sp_msd_loss'] is None:
pass
else:
sp_msd_loss = output_dict_sp['sp_msd_loss'].mean() * self.conf.train_sp_msd_loss_weight
loss += sp_msd_loss
self.sp_msd_loss_meter.update(val=sp_msd_loss.item(), num=batch_N)
print_str += ' spmsd %.4f(%.4f)' % (self.sp_msd_loss_meter.val, self.sp_msd_loss_meter.avg)
loss.backward()
self.optimizer.step()
# show training
if if_print:
print(print_str)
# show img
if if_show:
if_show_bw = False # 是否展示backward flow过程
# base thing
im1_crop, im2_crop, im1_warp, flow_fw, occ_fw = tools.tensor_gpu(im1_crop, im2_crop, im1_warp, flow_fw, occ_fw, check_on=False)
frame_1_ls += [('im1', im1_crop), ('im1 ', im1_crop), ('flow forward', flow_fw), ('occ forward', occ_fw)]
frame_2_ls += [('im2', im2_crop), ('im1_warp', im1_warp), ('flow forward', flow_fw), ('occ forward', occ_fw)]
if if_show_bw:
im2_warp, flow_bw, occ_bw = tools.tensor_gpu(im2_warp, flow_bw, occ_bw, check_on=False)
frame_1_ls += [('im2_warp', im2_warp), ('flow backward', flow_bw), ('occ backward', occ_bw)]
frame_2_ls += [('im2', im2_crop), ('flow backward', flow_bw), ('occ backward', occ_bw)]
# ============================ 有的模型 要加一些操作 =====================
if self.conf.model_name.lower() == '加油':
pass
elif self.conf.model_name.lower() in ['pwcirrbiv5', ]:
pass
elif self.conf.model_name.lower() in ['pwcirrbiv5_v5', ]:
fw_im1 = output_dict['im1_warp_ss']
fw_im2 = output_dict['im2_warp_ss']
fw_im1_, fw_im2_ = tools.tensor_gpu(fw_im1.clone().detach(), fw_im2.clone().detach(), check_on=False)
frame_1_ls += [('fw_im1_', fw_im1_), ('fw_im2_', fw_im2_), ]
frame_2_ls += [('fw_im1_', fw_im1_), ('fw_im2_', fw_im2_), ]
else:
pass # no operation
# raise ValueError(' not implemented model name: %s' % self.conf.model_name)
self.training_shower.get_batch_pair_all_list_nchw_check_flow_frame1_frame2_gif(batch_dict_ls_frame1=frame_1_ls, batch_dict_ls_frame2=frame_2_ls,
name='iter_%s_%s' % (batch_step, print_str))
self.training_shower.put_frame1_frame2_gif(name='Epoch %d Iteration %d ' % (self.epoch, batch_step))
# compute data time
self.data_clock.start()
@classmethod
def save_image_v2(cls, tensor_data, name, save_dir_dir, mask_or_flow_or_image='image', if_flow_data_save_png=False):
def decom(a):
b = tools.tensor_gpu(a, check_on=False)[0]
c = b[0, :, :, :]
c = np.transpose(c, (1, 2, 0))
return c
if mask_or_flow_or_image == 'flow':
flow_f_np = decom(tensor_data)
if flow_f_np.shape[2] == 2:
cv2.imwrite(os.path.join(save_dir_dir, name + '_s.png'), tools.flow_to_image(flow_f_np)[:, :, ::-1])
if if_flow_data_save_png:
save_path = os.path.join(save_dir_dir, name + '.png')
tools.write_kitti_png_file(save_path, flow_f_np)
elif flow_f_np.shape[2] == 3:
flow = flow_f_np[:, :, :2]
mask = flow_f_np[:, :, 2]
cv2.imwrite(os.path.join(save_dir_dir, name + '_s.png'), tools.flow_to_image(flow)[:, :, ::-1])
if if_flow_data_save_png:
save_path = os.path.join(save_dir_dir, name + '.png')
tools.write_kitti_png_file(save_path, flow, mask_data=mask)
else:
raise ValueError('flow_f_np shape not right: %s' % flow_f_np.shape)
elif mask_or_flow_or_image == 'mask':
mask = decom(tensor_data)
cv2.imwrite(os.path.join(save_dir_dir, name + '.png'), tools.Show_GIF.im_norm(mask * 255))
elif mask_or_flow_or_image == 'image':
img1_np = tools.Show_GIF.im_norm(decom(tensor_data))
# img1_np = decom(tensor_data)
cv2.imwrite(os.path.join(save_dir_dir, name + '.png'), img1_np[:, :, ::-1])
else:
raise ValueError('wrong data type: %s' % mask_or_flow_or_image)
def eval_forward(self, im1, im2, flow, *args):
# ==================================================================== 网络输出 ======================================================================
with torch.no_grad():
if self.conf.model_name.lower() == '加油':
flow_fw, flow_bw, app_flow_1, app_flow_2, _, _ = self.net_work(im1, im2) # flow from im1->im2
pred_flow = flow_fw
elif self.conf.model_name.lower() in ['pwcirrbiv5_v4', 'pwcirrbiv5_v5']:
input_dict = {'im1': im1, 'im2': im2, 'if_loss': False, 'if_test': True}
output_dict = self.net_work(input_dict)
flow_fw, flow_bw = output_dict['flow_f_out'], output_dict['flow_b_out']
flows = output_dict['flows']
pred_flow = flow_fw
elif self.conf.model_name.lower() in ['pwcirrbiv5_v4_show', 'pwcirrbiv5_v5_show']:
if self.conf.save_running_process:
running_process_dir = os.path.join(self.training_shower.save_dir, 'running_process')
sample_dir = os.path.join(running_process_dir, '%s' % self.cnt)
tools.check_dir(sample_dir)
input_dict = {'im1': im1, 'im2': im2, 'if_loss': False, 'if_test': True, 'save_running_process': True, 'process_dir': sample_dir}
else:
input_dict = {'im1': im1, 'im2': im2, 'if_loss': False, 'if_test': True}
output_dict = self.net_work(input_dict)
flow_fw, flow_bw = output_dict['flow_f_out'], output_dict['flow_b_out']
flows = output_dict['flows']
pred_flow = flow_fw
# print('======')
# tools.check_tensor(flow, 'gt flow')
# tools.check_tensor(flow_fw, 'output_flow_fw')
# for i, (fw, fb) in enumerate(flows):
# tools.check_tensor(fw, '%s scale fw' % i)
# print('======')
if len(args) > 0 and self.conf.save_running_process:
def decom(a):
b = tools.tensor_gpu(a, check_on=False)[0]
c = b[0, :, :, :]
c = np.transpose(c, (1, 2, 0))
return c
occ_mask = args[0]
# save gt occ_mask
gt_occ_mask_np = decom(occ_mask)
gt_flow_np = decom(flow)
pred_flow_np = decom(pred_flow)
# save gt_flow
cv2.imwrite(os.path.join(sample_dir, 'gt_flow_np' + '.png'), tools.flow_to_image(gt_flow_np)[:, :, ::-1])
# save pred flow_f
cv2.imwrite(os.path.join(sample_dir, 'pred_flow_f' + '.png'), tools.flow_to_image(pred_flow_np)[:, :, ::-1])
# show flow gt error image
flow_error_image = tools.lib_to_show_flow.flow_error_image_np(pred_flow_np, gt_flow_np, gt_occ_mask_np)
# print('flow_error_image', np.max(flow_error_image), np.min(flow_error_image))
cv2.imwrite(os.path.join(sample_dir, 'flow_error_image' + '.png'), tools.Show_GIF.im_norm(flow_error_image))
flow_error_image_gray = tools.lib_to_show_flow.flow_error_image_np(pred_flow_np, gt_flow_np, gt_occ_mask_np, log_colors=False)
cv2.imwrite(os.path.join(sample_dir, 'flow_error_image_gray' + '.png'), tools.Show_GIF.im_norm(flow_error_image_gray))
if self.conf.model_name.lower() == 'pwcirrbiv5_show_v3': # save some results
occmask, noc_gt_flow, nocmask = args
save_dir = os.path.join(self.training_shower.save_dir, 'saving_res')
tools.check_dir(save_dir)
dir_name = '%s' % self.cnt # + '_occ_%.3f_'%occ_value.item()
save_dir_dir = os.path.join(save_dir, dir_name)
tools.check_dir(save_dir_dir)
occ_fw = output_dict['occ_fw']
self.save_image_v2(flow_fw, 'flow_f', save_dir_dir, 'flow', True)
self.save_image_v2(flow, 'gt', save_dir_dir, 'flow', True)
self.save_image_v2(noc_gt_flow, 'noc_gt_flow', save_dir_dir, 'flow', True)
self.save_image_v2(occmask, 'gt_occ_mask', save_dir_dir, 'mask', False)
self.save_image_v2(nocmask, 'gt_noc_mask', save_dir_dir, 'mask', False)
self.save_image_v2(im1, 'im1', save_dir_dir, 'image', False)
self.save_image_v2(im2, 'im2', save_dir_dir, 'image', False)
self.save_image_v2(occ_fw, 'occ_mask', save_dir_dir, 'mask', False)
else:
raise ValueError(' not implemented model name: %s' % self.conf.model_name)
if self.conf.if_do_eval: # 管理在测试或者验证过程中, 是否展示gif结果,
self.cnt += 1
if self.conf.if_do_test:
im1_warp = tools.torch_warp(im2, pred_flow)
warp_error = torch.sqrt((im1_warp - im1) ** 2)
warp_error = warp_error.mean()
print_str = 'iter_%s warp_error%.5f' % (self.cnt, warp_error.item())
self.print_str = print_str
if self.conf.if_test_save_show_results:
im1_np, im2_np, pred_flow_np, im1_warp_np = tools.tensor_gpu(im1, im2, pred_flow, im1_warp, check_on=False)
frame_1_ls = [('im1', im1_np), ('im1 ', im1_np), ('im1_warp', im1_warp_np), ('flow pred', pred_flow_np)]
frame_2_ls = [('im2', im2_np), ('im1_warp', im1_warp_np), ('im1_warp', im1_warp_np), ('flow pred', pred_flow_np)]
self.training_shower.get_batch_pair_all_list_nchw_check_flow_frame1_frame2_gif(batch_dict_ls_frame1=frame_1_ls, batch_dict_ls_frame2=frame_2_ls,
name=print_str)
else:
im1_warp = tools.torch_warp(im2, pred_flow)
im1_gt_warp = tools.torch_warp(im2, flow)
warp_error = torch.sqrt((im1_warp - im1) ** 2)
warp_error = warp_error.mean()
gt_warp_error = torch.sqrt((im1_warp - im1_gt_warp) ** 2)
gt_warp_error = gt_warp_error.mean()
print_str = 'iter_%s warp_error%.5f gtwarperror_%.5f' % (self.cnt, warp_error.item(), gt_warp_error.item())
self.print_str = print_str
if self.conf.if_do_eval_save_show_result:
im1_np, im2_np, gt_flow_np, pred_flow_np, im1_warp_np, im1_gt_warp_np = tools.tensor_gpu(im1, im2, flow, pred_flow, im1_warp, im1_gt_warp, check_on=False)
frame_1_ls = [('im1', im1_np), ('im1', im1_np), ('gt_warp_im1', im1_gt_warp_np), ('flow pred', pred_flow_np)]
frame_2_ls = [('im2', im2_np), ('im1_warp', im1_warp_np), ('im1_warp', im1_warp_np), ('flow gt', gt_flow_np)]
self.training_shower.get_batch_pair_all_list_nchw_check_flow_frame1_frame2_gif(batch_dict_ls_frame1=frame_1_ls, batch_dict_ls_frame2=frame_2_ls,
name=print_str)
if self.conf.if_save_flow_in_eval_or_test: # 管理是否保存flow结果,存为.png或者.flo
self.temp_save_eval_test = [pred_flow, flow] # 缓存起来
if self.conf.multi_scale_eval:
return pred_flow, flows
return pred_flow
def eval_save_result(self, save_name, *args, **kwargs):
def flow_tensor_np_h_w_2(a):
a_np = tools.tensor_gpu(a, check_on=False)[0]
a_np = a_np[0, :, :, :] # n,c,h,w
a_np = np.transpose(a_np, (1, 2, 0)) # h,w,2
return a_np
if self.conf.if_do_eval:
if self.conf.if_do_eval_print:
print(self.print_str + ' ' + save_name)
if self.conf.if_do_test:
if self.conf.if_test_save_show_results:
if len(args) > 0:
sample_dir_name = args[0]
self.training_shower.put_frame1_frame2_gif(name=sample_dir_name + '_' + save_name + '_' + self.print_str)
else:
self.training_shower.put_frame1_frame2_gif(name=save_name + '_' + self.print_str)
else:
if self.conf.if_do_eval_save_show_result:
self.training_shower.put_frame1_frame2_gif(name=save_name + '_' + self.print_str)
if self.conf.if_save_flow_in_eval_or_test:
if self.conf.if_do_test: # test
save_dir = os.path.join(self.training_shower.save_dir, 'save_test_flow')
tools.check_dir(save_dir)
if len(args) > 0:
sample_dir_name = args[0]
if type(sample_dir_name) == str:
save_dir = os.path.join(save_dir, sample_dir_name)
tools.check_dir(save_dir)
if self.conf.if_save_flow_in_eval_or_test_type == 'png':
pred_flow, _ = self.temp_save_eval_test
pred_flow_np = flow_tensor_np_h_w_2(pred_flow)
save_path = os.path.join(save_dir, save_name + '.png')
# 2015上这样save是可以用的,但同样的save方法2012就不能用了
tools.write_kitti_png_file(save_path, pred_flow_np)
# 尝试一个新的方式
# tools.lib_to_show_flow.flow_write_png( u=pred_flow_np[:,:,0], v=pred_flow_np[:,:,1], fpath=save_path)
elif self.conf.if_save_flow_in_eval_or_test_type == 'flo':
pred_flow, _ = self.temp_save_eval_test
pred_flow_np = flow_tensor_np_h_w_2(pred_flow)
save_path = os.path.join(save_dir, save_name + '.flo')
tools.write_flo(flow=pred_flow_np, filename=save_path) # write_flow, or, write_flo
else:
raise ValueError('wrong if_save_flow_eval_test_type, should be png or flo, but got: %s' % self.conf.if_save_flow_in_eval_or_test_type)
else: # eval
save_dir = os.path.join(self.training_shower.save_dir, 'eval_test')
tools.check_dir(save_dir)
if len(args) > 0:
sample_dir_name = args[0]
if type(sample_dir_name) == str:
save_dir = os.path.join(save_dir, sample_dir_name)
tools.check_dir(save_dir)
if self.conf.if_save_flow_in_eval_or_test_type == 'png':
pred_flow, gt_flow = self.temp_save_eval_test
pred_flow_np = flow_tensor_np_h_w_2(pred_flow)
save_path = os.path.join(save_dir, save_name + '.png')
tools.write_kitti_png_file(save_path, pred_flow_np)
# tools.WriteKittiPngFile(save_path, pred_flow_np)
# save gt
gt_save_path = os.path.join(save_dir, save_name + '_gt.png')
tools.write_kitti_png_file(gt_save_path, flow_tensor_np_h_w_2(gt_flow))
elif self.conf.if_save_flow_in_eval_or_test_type == 'flo':
pred_flow, gt_flow = self.temp_save_eval_test
pred_flow_np = flow_tensor_np_h_w_2(pred_flow)
save_path = os.path.join(save_dir, save_name + '.flo')
tools.write_flo(flow=pred_flow_np, filename=save_path) # write_flow, or, write_flo
gt_save_path = os.path.join(save_dir, save_name + '_gt.flo')
gt_flow_np = flow_tensor_np_h_w_2(gt_flow)
tools.write_flo(flow=gt_flow_np, filename=gt_save_path) # write_flow, or, write_flo
if_check = True
if if_check:
temp = tools.read_flo(save_path) # read_flow, or, read_flo
temp_gt = tools.read_flo(gt_save_path) # read_flow, or, read_flo
temp_error = temp - pred_flow_np
temp_gt_error = temp_gt - gt_flow_np
print('pred flow save write .flo file, error: ', np.min(temp_error), np.max(temp_error), 'gt r.w.error: ', np.min(temp_gt_error), np.max(temp_gt_error))
else:
raise ValueError('wrong if_save_flow_eval_test_type, should be png or flo, but got: %s' % self.conf.if_save_flow_in_eval_or_test_type)
def train(self, epoch=0): # 进入训练状态
# torch.cuda.empty_cache()
if hasattr(torch.cuda, 'empty_cache'):
torch.cuda.empty_cache()
torch.set_grad_enabled(True)
self.net_work.train()
self.app_loss_meter.reset()
self.appd_loss_meter.reset()
self.msd_loss_meter.reset()
self.sp_msd_loss_meter.reset()
self.final_sp_loss_meter.reset()
self.occ_loss_meter.reset()
self.spatial_trans_loss_meter.reset()
self.photo_loss_meter.reset()
self.smooth_loss_meter.reset()
self.inpaint_img_loss_meter.reset()
self.multi_scale_loss_meter.reset()
if epoch % 1 == 0:
self.scheduler.step()
print('epoch', epoch, 'lr={:.6f}'.format(self.scheduler.get_lr()[0]))
self.epoch = epoch
class Train_Config(tools.abstract_config):
def __init__(self, **kwargs):
self.batchsize = 4
self.gpu_opt = None # gpu option
self.n_epoch = 1000 # number of epoch
self.if_eval = True # do evaluation during the training process
self.train_data_name = 'kitti_2015_mv' # or kitti_2012_mv
self.eval_data_name = '2015_train' # or 2015_train
self.eval_per = -1 # do evaluation every N iters
self.eval_batchsize = 1 # batch size for evaluation
self.use_prefether = True # faster loader
self.if_histmatch = False # do not use this
self.update(kwargs)
class Training():
def __init__(self, **kwargs):
self.conf = Train_Config(**kwargs)
self.data_conf = self.get_train_data(**kwargs)
def get_train_data(self, **kwargs):
'''
get dataset
data config = {
'crop_size': (256, 832),
'rho': 8,
'swap_images': True,
'normalize': True,
'horizontal_flip_aug': True,
}
'''
if self.conf.train_data_name == 'kitti_2015_mv':
data_conf = kitti_train.kitti_data_with_start_point.config(mv_type='2015', **kwargs)
elif self.conf.train_data_name == 'kitti_2012_mv':
data_conf = kitti_train.kitti_data_with_start_point.config(mv_type='2012', **kwargs)
else:
raise ValueError('not implemented train data: %s' % self.conf.train_data_name)
return data_conf
def get_network(self):
pass
def get_eval_benchmark(self):
pass
def do_training(self):
pass
param_dict = {
# training
'batchsize': 4,
'gpu_opt': None,
'n_epoch': 1000,
'if_eval': True,
'train_data_name': 'kitti_2015_mv',
'eval_data_name': '2015_train', # or 2015_train
'eval_per': -1, # 隔多少个iter做验证
'eval_batchsize': 1, # 验证batch size
'use_prefether': True, # 这个速度快一点,会好一点
# data
'crop_size': (256, 832),
'rho': 8,
'swap_images': True,
'normalize': True,
'horizontal_flip_aug': True,
# network
}