def __init__(self, file_json, path_img, mode, transform=None, is_mosaic=False, is_mosaic_keep_wh=False, is_mosaic_fill=False, is_debug=False, cfg=None, s_ids_cats=None, nums_cat=None, is_img_np=True, is_boxesone=True): ''' :param file_json: :param path_img: :param mode: :param transform: 这个需与 is_img_np 配对使用 :param is_mosaic: :param is_mosaic_keep_wh: :param is_mosaic_fill: :param is_debug: :param cfg: :param s_ids_cats: :param nums_cat: 每一个分类的最大图片数量 :param is_img_np: 为Ture img_np 为False 为pil 这个需与 transform 配对使用 :param is_boxesone: 归一化gt 尺寸 ''' self.file_json = file_json self.transform = transform self.mode = mode self.coco_obj = COCO(file_json) if s_ids_cats is not None: flog.warning('指定coco类型 %s', coco.loadCats(s_ids_cats)) self.s_ids_cats = s_ids_cats ids_img = [] # 限制每类的最大个数 if nums_cat is None: for idc in zip(s_ids_cats): # 类型对应哪些文件 可能是一张图片多个类型 ids_ = self.coco_obj.getImgIds(catIds=idc) ids_img += ids_ else: # 限制每类的最大个数 for idc, num_cat in zip(s_ids_cats, nums_cat): # 类型对应哪些文件 可能是一张图片多个类型 ids_ = self.coco_obj.getImgIds(catIds=idc)[:num_cat] # ids_ = self.coco.getImgIds(catIds=idc)[:1000] ids_img += ids_ # print(ids_) # 这个只支持单个元素 self.ids_img = list(set(ids_img)) # 去重 else: self.ids_img = self.coco_obj.getImgIds() # 所有图片的id 画图数量 # self.classes_ids self.classes_ids self._init_load_classes() # 除了coco数据集,其它不管 self.is_debug = is_debug self.is_mosaic = is_mosaic self.cfg = cfg self.path_img = path_img self.is_mosaic_keep_wh = is_mosaic_keep_wh self.is_mosaic_fill = is_mosaic_fill self.is_img_np = is_img_np # img_np False 是img_pil if not os.path.exists(path_img): raise Exception('coco path_img 路径不存在', path_img)
def init_od_e(cfg, seed=0): # -----------通用系统配置---------------- torch.set_printoptions(linewidth=320, sci_mode=False, precision=5, profile='long') np.set_printoptions(linewidth=320, suppress=True, formatter={'float_kind': '{:11.5g}'.format }) # format short g, %precision=5 matplotlib.rc('font', **{'size': 11}) # 防止OpenCV进入多线程(使用PyTorch DataLoader) cv2.setNumThreads(0) # 随机种子 torch.manual_seed(seed) np.random.seed(seed) torch.cuda.manual_seed(seed) torch.cuda.manual_seed_all(seed) random.seed(seed) np.random.seed(seed) # from yolo5 Speed-reproducibility tradeoff https://pytorch.org/docs/stable/notes/randomness.html torch.manual_seed(seed) if seed == 0: # slower, more reproducible cudnn.benchmark, cudnn.deterministic = False, True else: # faster, less reproducible cudnn.benchmark, cudnn.deterministic = True, False if cfg.IS_MULTI_SCALE: cfg.tcfg_size = [640, 640] flog.warning("多尺度训练 ------ 开 最大 %s" % cfg.tcfg_size) else: cfg.tcfg_size = cfg.IMAGE_SIZE flog.warning("多尺度训练 ------ 关 %s", cfg.IMAGE_SIZE)
def model_out4one(model, img_np, data_transform, size_ts, labels_lsit, target=None, is_keeep=False): img_ts_one, boxes, labels = data_transform(img_np) img_ts4 = img_ts_one.unsqueeze_(0) '''---------------预测开始--------------''' ids_batch, p_boxes_ltrb, p_keypoints, p_labels, p_scores = model(img_ts4) size_input = size_ts if is_keeep: max1 = max(size_ts) size_input = torch.tensor([max1, max1]) # 用于恢复bbox及ke szie_scale4bbox = size_input.repeat(2) if p_labels is None or len(p_labels) == 0: _text = '未检测出来,id为:%s' if target is not None: _text = _text % target['image_id'] flog.warning(_text) plabels_text = None p_scores_float = None p_boxes_ltrb = p_boxes_ltrb else: plabels_text = [] p_scores_float = [] for i, label in enumerate(p_labels): plabels_text.append(labels_lsit[int(label.item())]) p_scores_float.append(p_scores[i].item()) p_boxes_ltrb = p_boxes_ltrb * szie_scale4bbox return p_boxes_ltrb, p_scores_float, plabels_text
def spilt_data2folder(path_root, val_rate=0.3): names_class = [cla for cla in os.listdir(path_root) if ".txt" not in cla] path_train_root = os.path.join(os.path.dirname(path_root), 'train') path_val_root = os.path.join(os.path.dirname(path_root), 'val') for n in names_class: path_train_n = os.path.join(path_train_root, n) path_val_n = os.path.join(path_val_root, n) if not os.path.exists(path_train_n): os.makedirs(path_train_n) else: flog.warning('文件夹已存在 %s', path_train_n) exit(-1) if not os.path.exists(path_val_n): os.makedirs(path_val_n) else: flog.warning('文件夹已存在 %s', path_val_n) exit(-1) path_cla_imgs = os.path.join(path_root, n) name_images = os.listdir(path_cla_imgs) num = len(name_images) eval_index = random.sample(name_images, k=int(num * val_rate)) for i, n in tqdm(enumerate(name_images)): path_img = os.path.join(path_cla_imgs, n) if n in eval_index: # 验值集 path_img_new = os.path.join(path_val_n, n) else: path_img_new = os.path.join(path_train_n, n) copy(path_img, path_img_new) print("\r[{}] processing [{}/{}]".format(n, i + 1, num), end="") # processing bar print("spilt_data2folder done!")
def handle_keypoints(self, coco_ann): ''' :param coco_ann: 这里只会是一维标签 :return: ''' k_ = np.array(coco_ann['keypoints']) ''' widerface 不需要加 mask 这个是标注是否可用的的定义 # 如果关键点在物体segment内,则认为可见. # v=0 表示这个关键点没有标注(这种情况下x=y=v=0) # v=1 表示这个关键点标注了但是不可见(被遮挡了) # v=2 表示这个关键点标注了同时也可见 ''' inds = np.arange(2, len(k_), 3) # 每隔两个选出 [ 2 5 8 11 14] mask = np.ones(len(coco_ann['keypoints']), dtype=np.float32) mask[inds] = 1 _t = k_[inds] != 2 if _t.any() and _t.sum() != len(_t): # 有 且 不是全部的进入 _s = '标签不全为2 %s' % k_ flog.error(_s) # raise Exception(_s) inds = np.arange(2, len(k_), 3) # 每隔两个选出 ones = np.ones(len(coco_ann['keypoints']), dtype=np.float32) ones[inds] = 0 nonzero = np.nonzero(ones) # 取非零索引 keypoint_np = k_[nonzero] # 选出10个数 if np.all(keypoint_np == 0): flog.warning('出现全0 keypoints %s' % coco_ann) return None return keypoint_np
def __call__(self, img, target): # f_plt_show_cv(image,boxes) for t in self.transforms: img, target = t(img, target) if target is not None: if len(target['boxes']) != len(target['labels']): flog.warning('!!! 数据有问题 Compose %s %s %s ', len(target['boxes']), len(target['labels']), t) return img, target
def fdatas_l2(batch_data, device, cfg, epoch, model): ''' cpu转gpu 输入模型前数据处理方法 定制 image = torch.nn.functional.interpolate( image[None], scale_factor=scale_factor, mode='bilinear', align_corners=False)[0] images = torch.nn.functional.interpolate(images, size=input_size, mode='bilinear', align_corners=False) :param batch_data: :param device: :return: ''' images, targets = batch_data if model.training and cfg.IS_MULTI_SCALE: if epoch != cfg.tcfg_epoch and epoch % 10 == 0: # if epoch % 1 == 0: if fis_mgpu(): randints = torch.randint(low=10, high=19, size=[1], device=device) dist.broadcast(randints, src=0) randint = randints[0].item() else: randint = random.randint(*cfg.MULTI_SCALE_VAL) cfg.tcfg_size = [randint * 32] * 2 # (320~608) 9个尺寸 flog.warning("多尺度训练 epoch:{},尺度{}".format(epoch + 1, cfg.tcfg_size)) cfg.tcfg_epoch = epoch # 避免重复判断 images = torch.nn.functional.interpolate(images, size=cfg.tcfg_size, mode='bilinear', align_corners=False) images = images.to(device) for target in targets: target['boxes'] = target['boxes'].to(device) target['labels'] = target['labels'].to(device) target['size'] = target['size'].to(device) if cfg.NUM_KEYPOINTS > 0: target['keypoints'] = target['keypoints'].to(device) # for key, val in target.items(): # target[key] = val.to(device) return images, targets
def f_show_coco_pics(coco, path_img, ids_img=None): ''' 遍历所有图片打开查看 :param coco: :param path_img: :return: ''' # id = 1 # imgIds = coco.getImgIds(imgIds=[id]) if not ids_img: ids = coco.getImgIds() else: ids = ids_img for id in ids: img_info = coco.loadImgs([id]) # 这里原始返回list # 本地加载 h,w,c # img = io.imread(os.path.join(path_img, img_info[0]['file_name'])) file = os.path.join(path_img, img_info[0]['file_name']) if not os.path.exists(file): raise Exception('path不存在%s' % file) img = cv2.imread(file) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # flog.debug('imgsize %s', img.shape[:2][::-1]) # 加载图片基本信息 h w id filename # 获取该图片的所有标注的id annIds = coco.getAnnIds(imgIds=img_info[0]['id']) anns = coco.loadAnns(annIds) # annotation 对象 # img_pil = f_open_cocoimg(path_img, coco, id) # for ann in anns: # box_ltwh = np.array(ann['bbox'])[None] # print(box_ltwh) # ltwh # box_ltrb = ltwh2ltrb(box_ltwh) # show_anc4pil(img_pil, box_ltrb) flog.warning('宽高:%s x %s' % (img.shape[1], img.shape[0])) plt.axis('off') plt.imshow(img) coco.showAnns(anns) # 显示标注 plt.show()
def cre_transform_base4np(cfg): flog.warning('预处理使用 cre_transform_base4np', ) data_transform = { "train": Compose([ Resize(cfg.IMAGE_SIZE), Normalize(cfg.PIC_MEAN, cfg.PIC_STD), ConvertColor(current='BGR', transform='RGB'), ToTensor(is_box_oned=True), ], cfg) } data_transform["val"] = Compose([ Resize(cfg.IMAGE_SIZE), Normalize(cfg.PIC_MEAN, cfg.PIC_STD), ConvertColor(current='BGR', transform='RGB'), ToTensor(is_box_oned=False), ], cfg) return data_transform
def __init__(self, backbone, cfg): super(YOLOv1, self).__init__() if cfg.MODE_TRAIN == 1 or cfg.MODE_TRAIN == 4: # base 或 IOU 损失及预测 flog.warning('-------------- LossYOLOv1 ------------- %s', ) self.net = YOLOv1_Net(backbone, cfg, cfg.NUM_CLASSES + 1) # 带conf self.losser = LossYOLOv1(cfg=cfg) self.preder = PredictYOLOv1(cfg=cfg) elif cfg.MODE_TRAIN == 2: # 去conf 只有cls reg分支 flog.warning('-------------- LossYOLOv1_cr ------------- %s', ) self.net = YOLOv1_Net(backbone, cfg, cfg.NUM_CLASSES) # 只有cls及reg分支 self.losser = LossYOLOv1_cr(cfg=cfg) self.preder = PredictYOLOv1_cr(cfg=cfg) elif cfg.MODE_TRAIN == 3: # 任意分布 高级reg算法 暂时无效? self.net = YOLOv1_Net(backbone, cfg, cfg.NUM_CLASSES, num_reg=4 * cfg.NUM_REG) # YOLOv1_Net self.losser = LossYOLOv1_cr(cfg=cfg) self.preder = PredictYOLOv1_cr(cfg=cfg)
def base_set_1gpu(cfg, id_gpu=0): # cfg.SAVE_FILE_NAME = os.path.basename(__file__) if torch.cuda.is_available(): device = torch.device('cuda:%s' % id_gpu) else: device = torch.device("cpu") cfg.IS_MIXTURE_FIX = False flog.info('模型当前设备 %s', device) cfg.device = device # cfg添加属性 if cfg.DEBUG: flog.warning('debug模式') # device = torch.device("cpu") cfg.PRINT_FREQ = 1 # cfg.PATH_SAVE_WEIGHT = None cfg.BATCH_SIZE = 5 cfg.DATA_NUM_WORKERS = 0 pass else: torch.multiprocessing.set_sharing_strategy('file_system') # 多进程开文件 return device, cfg
def __getitem__(self, index): ''' :param index: :return: tensor or np.array 根据 out: 默认ts or other is np img: h,w,c target: coco原装是 ltwh dict{ image_id: int, bboxs: ts n4 原图 ltwh -> ltrb labels: ts n, keypoints: ts n,10 size: wh } ''' # 这里生成的是原图尺寸的 target 和img_np_uint8 (375, 500, 3) if self.is_mosaic and self.mode == 'bbox': res = self.do_mosaic(index) else: res = self.open_img_tar(index) if res is None: flog.error('这个图片没有标注信息 id为%s', index) return self.__getitem__(index + 1) img, target = res if len(target['boxes']) != len(target['labels']): flog.warning('!!! 数据有问题 1111 %s %s %s ', target, len(target['boxes']), len(target['labels'])) '''---------------cocoAPI测试 查看图片在归一化前------------------''' # 这个用于调试 # if self.cfg.IS_VISUAL_PRETREATMENT: # 可视化参数 is_mosaic 这个用不起 # f_show_coco_pics(self.coco_obj, self.path_img, ids_img=[index]) if target['boxes'].shape[0] == 0: flog.warning('数据有问题 重新加载 %s', index) return self.__getitem__(index + 1) if self.transform is not None: img, target = self.transform(img, target) # if self.is_img_np: # # 输入 ltrb 原图 # # f_plt_show_cv(img, gboxes_ltrb=target['boxes']) # # img, boxes, labels = self.transform(img, target['boxes'], target['labels']) # img, target = self.transform(img, target) # # 这里会刷新 boxes, labels # # f_plt_show_cv(img, gboxes_ltrb=boxes) # else: # # 预处理输入 PIL img 和 np的target # img, target = self.transform(img, target) if len(target['boxes']) != len(target['labels']): flog.warning('!!! 数据有问题 ttttttttt %s %s %s ', target, len(target['boxes']), len(target['labels'])) # target['boxes'] = torch.tensor(target['boxes'], dtype=torch.float) # target['labels'] = torch.tensor(target['labels'], dtype=torch.int64) target['size'] = torch.tensor(target['size'], dtype=torch.float) # 用于恢复真实尺寸 # if self.mode == 'keypoints': # target['keypoints'] = torch.tensor(target['keypoints'], dtype=torch.float) if target['boxes'].shape[0] == 0: flog.debug('二次检查出错 %s', index) return self.__getitem__(index + 1) if len(target['boxes']) != len(target['labels']): flog.warning('!!! 数据有问题 22222 %s %s %s ', target, len(target['boxes']), len(target['labels'])) # flog.warning('数据debug 有问题 %s %s %s ', target, len(target['boxes']), len(target['labels'])) return img, target
def f_evaluate4fmap(model, data_loader, is_keep, cfg): ''' 1 通过 voc2fmap.py 创建 gtinfo 2 设置 IS_FMAP_EVAL 开启 指定 PATH_EVAL_IMGS 和 PATH_EVAL_INFO 文件夹 3 加载 classes_ids_voc 4 支持 degbug 设置 5 生成 dt_info label conf ltrb真实值 tvmonitor 0.471781 0 13 174 244 cup 0.414941 274 226 301 265 6 f_fix_txt(gt_path, DR_PATH) 使gt 与 dt 一致 7 f_recover_gt(gt_path) # 恢复 gt 8 到 D:\tb\tb\ai_code\DL\f_tools\datas\f_map\output 查看结果 查打开 f_do_fmap plot_res 9 恢复在 CONFIG中 :param model: :param data_loader: :param is_keep: :return: ''' path_dt_info = data_loader.dataset.path_dt_info ids2classes = data_loader.dataset.ids2classes metric_logger = MetricLogger(delimiter=" ") header = "Test: " print_freq = max(int(len(data_loader) / 5), 1) for batch_data in metric_logger.log_every(data_loader, print_freq, header): start_time = time.time() _dataset = data_loader.dataset img_ts4, targets = batch_data sizes = [] files_txt = [] for target in targets: size_ = target['size'] if is_keep: # keep修复 max1 = max(size_) size_ = [max1, max1] sizes.append(torch.tensor(size_)) # tesor # sizes.append(target['size']) files_txt.append(os.path.join(path_dt_info, target['name_txt'])) ids_batch, p_boxes_ltrb, p_labels, p_scores = model(img_ts4) for i, (szie, file_txt) in enumerate(zip(sizes, files_txt)): mask = ids_batch == i # 构建 batch 次的mask if torch.any(mask): # 如果最终有目标存在 将写出info中 lines_write = [] for label, score, bbox in zip(p_labels[mask], p_scores[mask], p_boxes_ltrb[mask]): _bbox = [ str(i.item()) for i in list((bbox * szie.repeat(2)).type(torch.int64).data) ] bbox_str = ' '.join(_bbox) _line = ids2classes[str(int(label.item()))] + ' ' + str( score.item()) + ' ' + bbox_str + '\n' lines_write.append(_line) with open(file_txt, "w") as f: f.writelines(lines_write) else: flog.warning('没有预测出框 %s', files_txt) pass end_time = time.time() - start_time metric_logger.update(eval_time=end_time) # 这个填字典 添加的字段 flog.info('dt_info 生成完成') # path_dt_info = data_loader.dataset.path_dt_info path_gt_info = data_loader.dataset.path_gt_info path_imgs = data_loader.dataset.path_imgs # f_recover_gt(path_gt_info) f_fix_txt(path_gt_info, path_dt_info) f_do_fmap(path_gt=path_gt_info, path_dt=path_dt_info, path_img=path_imgs, confidence=cfg.THRESHOLD_PREDICT_CONF, iou_map=[], ignore_classes=[], console_pinter=True, plot_res=False, animation=True)
def handler_face_5(): # 这个可以直接创建json path_root = r'M:\AI\datas\face_5' path_copy_dst = os.path.join(path_root, 'images_13466') # file_path = os.path.join(path_root, 'train/trainImageList.txt') # train_type = 'train' # train test val # num_file = 999999999 file_path = os.path.join(path_root, 'train/testImageList.txt') train_type = 'test' # train test val num_file = 200 # 这个是最大文件数 mode = 'keypoints' # bbox segm keypoints caption is_copy = False path_img_src = os.path.join(path_root, 'train', 'lfw_5590') # is_copy = False 则无效 # ['2007_000027.jpg', '174.0', '101.0', '349.0', '351.0', 'person'] size_ann = 1 + 4 + 5 * 3 + 1 # 用于csv验证 name_keypoints = [ "left_eye", "right_eye", "nose", "left_mouth", "right_mouth", ] skeleton = [[3, 1], [3, 2], [3, 4], [3, 5]] # 连接顺序 if os.path.exists(file_path): f = open(file_path, 'r') else: raise Exception('标签文件不存在: %s' % file_path) lines = f.readlines() idx = 0 res = [] # 标签数 ''' 创建类型cls文件 ''' name_cls = 'human_face' classes_ids = {name_cls: 1} # 1开始 cre_cls_json(classes_ids, name_cls, path_root) t_names = set() # 用于验证重复 for line in tqdm(lines[:num_file], desc='标注框个数'): msg = line.strip().split(' ') idx += 1 # print('idx-', idx, ' : ', len(msg)) file_path = msg[0] # print(file_path) file_name = file_path.split('\\')[1] bbox = [msg[1], msg[3], msg[2], msg[4]] # list不支持数组索引 keypoint = msg[5:15] keypoint_coco = [] for i in range(int(len(keypoint) / 2)): # 转换并添加2 x = keypoint[i * 2 + 0] y = keypoint[i * 2 + 1] if float(x) == 0 and float(y) == 0: flog.warning('xy均为0 %s', line) keypoint_coco.extend([x, y, '0']) else: keypoint_coco.extend([x, y, '2']) _t = [] # 类别在后面写入时加的 _t.append(file_name) _t.extend(bbox) _t.extend(keypoint_coco) t_names.add(file_name) # _t.extend(name_cls) # 写死 res.append(_t) copy_img(file_path, is_copy, path_copy_dst, path_img_src, t_names) ''' 创建csv 文件格式 [文件名,box,keypoint,类型] ''' file_csv = cre_csv(name_cls, path_root, res, train_type) annotations = pd.read_csv(file_csv, header=None).values to_coco_4keypoint( annotations, classes_ids, path_copy_dst, path_root, size_ann=size_ann, name_keypoints=name_keypoints, skeleton=skeleton, is_copy=False, is_move=False, file_coco=mode + '_' + train_type + '_' + str(len(res)) # 标签数 )
def data_clean(coco_obj, coco_img_ids, catid2clsid, path_img=None): ''' 用于加载coco 查看和清理无效GT 后用于训练 :param coco_obj: :param coco_img_ids: :param catid2clsid: {1: 0, 2: 1, 3: 2} :param path_img: :return: ''' records = [] ct = 0 for img_id in coco_img_ids: img_info = coco_obj.loadImgs(img_id)[0] file_name = img_info['file_name'] im_w = float(img_info['width']) im_h = float(img_info['height']) ins_anno_ids = coco_obj.getAnnIds(imgIds=img_id, iscrowd=False) # 读取这张图片所有标注anno的id instances = coco_obj.loadAnns( ins_anno_ids) # 这张图片所有标注anno。每个标注有'segmentation'、'bbox'、... coco_targets = [] anno_id = [] # 注解id for inst in instances: # print("inst['bbox']", inst['bbox']) # 确保 ltwh 点在图片中 coco默认 ltwh x, y, box_w, box_h = inst['bbox'] # 读取物体的包围框 x1 = max(0, x) y1 = max(0, y) x2 = min(im_w - 1, x1 + max(0, box_w - 1)) y2 = min(im_h - 1, y1 + max(0, box_h - 1)) # ltwh -> ltrb if inst['area'] > 0 and x2 >= x1 and y2 >= y1: inst['clean_bbox'] = [x1, y1, x2, y2] # inst增加一个键值对 # print("inst['clean_bbox']", inst['clean_bbox']) coco_targets.append(inst) # 这张图片的这个物体标注保留 anno_id.append(inst['id']) else: flog.warning( 'Found an invalid bbox in annotations: im_id: {}, ' 'area: {} x1: {}, y1: {}, x2: {}, y2: {}.'.format( img_id, float(inst['area']), x1, y1, x2, y2)) num_bbox = len(coco_targets) # 这张图片的物体数 # 左上角坐标+右下角坐标+类别id gt_bbox = np.zeros((num_bbox, 4), dtype=np.float32) gt_class = np.zeros((num_bbox, 1), dtype=np.int32) gt_score = np.ones((num_bbox, 1), dtype=np.float32) # 得分的标注都是1 is_crowd = np.zeros((num_bbox, 1), dtype=np.int32) difficult = np.zeros((num_bbox, 1), dtype=np.int32) gt_poly = [None] * num_bbox for i, target in enumerate(coco_targets): catid = target['category_id'] gt_class[i][0] = catid2clsid[catid] # id类型顺序转换 gt_bbox[i, :] = target['clean_bbox'] is_crowd[i][0] = target['iscrowd'] if 'segmentation' in target: gt_poly[i] = target['segmentation'] # 分割 if path_img is not None: file_img = os.path.join(path_img, file_name) img_pil = Image.open(file_img).convert('RGB') # 原图数据 f_show_3box4pil(img_pil, gt_bbox, is_oned=False) coco_rec = { 'im_file': file_name, 'im_id': np.array([img_id]), 'h': im_h, 'w': im_w, 'is_crowd': is_crowd, 'gt_class': gt_class, 'anno_id': anno_id, 'gt_bbox': gt_bbox, 'gt_score': gt_score, 'gt_poly': gt_poly, } # 显示文件信息 # flog.debug('Load file: {}, im_id: {}, h: {}, w: {}.'.format(file_names, img_id, im_h, im_w)) records.append(coco_rec) # 注解文件。 ct += 1 flog.info('加载 {} 个图片 .'.format(ct)) return records
def load_anns(self, index, img_wh): ''' ltwh --> ltrb :param index: :return: bboxs: np(num_anns, 4) labels: np(num_anns) ''' # annotation_ids = self.coco.getAnnIds(self.image_ids[index], iscrowd=False) annotation_ids = self.coco_obj.getAnnIds(self.ids_img[index]) # ann的id # anns is num_anns x 4, (x1, x2, y1, y2) bboxs_np = np.zeros((0, 4), dtype=np.float32) # np创建 空数组 高级 labels = [] keypoints_np = [] # skip the image without annoations if len(annotation_ids) == 0: return None coco_anns = self.coco_obj.loadAnns(annotation_ids) for a in coco_anns: x, y, box_w, box_h = a['bbox'] # ltwh # 得 ltrb x1 = max(0, x) # 修正lt最小为0 左上必须在图中 y1 = max(0, y) x2 = min(img_wh[0] - 1, x1 + max(0, box_w - 1)) # 右下必须在图中 y2 = min(img_wh[1] - 1, y1 + max(0, box_h - 1)) if a['area'] > 0 and x2 >= x1 and y2 >= y1: a['bbox'] = [x1, y1, x2, y2] # 修正 并写入ltrb else: flog.warning('标记框有问题 %s 跳过', a) continue bbox = np.zeros((1, 4), dtype=np.float32) bbox[0, :4] = a['bbox'] if self.mode == 'keypoints': ''' # 如果关键点在物体segment内,则认为可见. # v=0 表示这个关键点没有标注(这种情况下x=y=v=0) # v=1 表示这个关键点标注了但是不可见(被遮挡了) # v=2 表示这个关键点标注了同时也可见 ''' keypoints = self.handle_keypoints(a) if keypoints is None: flog.warning('全0 keypoints %s 跳过') continue keypoints_np.append(keypoints) # 全部通过后添加 bboxs_np = np.append(bboxs_np, bbox, axis=0) labels.append(self.ids_old_new[a['category_id']]) # bboxs = ltwh2ltrb(bboxs) # 前面 已转 if bboxs_np.shape[0] == 0: flog.error('这图标注 不存在 %s', coco_anns) return None # raise Exception('这图标注 不存在 %s', coco_anns) # 转tensor if self.mode == 'bbox': return [torch.tensor(bboxs_np, dtype=torch.float), torch.tensor(labels, dtype=torch.float)] elif self.mode == 'keypoints': keypoints_np = np.array(keypoints_np) # list转np # 有标注的情况下 keypoints_np 一定有 return [torch.tensor(bboxs_np, dtype=torch.float), torch.tensor(labels, dtype=torch.float), torch.tensor(keypoints_np, dtype=torch.float)]
def load_weight(file_weight, model, optimizer=None, lr_scheduler=None, device=torch.device('cpu'), is_mgpu=False, ffun=None): start_epoch = 0 # 只匹配需要的 # model_dict = model.state_dict() # 获取模型每层的参数阵 # checkpoint = torch.load(file_weight, map_location=device) # pretrained_dict = checkpoint['model'] # dd = {} # for k, v in pretrained_dict.items(): # if k in model_dict: # shape_1 = model_dict[k].shape # shape_2 = pretrained_dict[k].shape # if shape_1 == shape_2: # dd[k] = v # else: # print('shape mismatch in %s. shape_1=%s, while shape_2=%s.' % (k, shape_1, shape_2)) # model_dict.update(dd) # model.load_state_dict(model_dict) # flog.warning('手动加载完成:%s',file_weight) # return start_epoch if file_weight and os.path.exists(file_weight): checkpoint = torch.load(file_weight, map_location=device) '''对多gpu的k进行修复''' if 'model' in checkpoint: pretrained_dict_y = checkpoint['model'] else: pretrained_dict_y = checkpoint # 特殊处理 # if True: # del pretrained_dict['module.head_yolov1.weight'] # del pretrained_dict['module.head_yolov1.bias'] # # del pretrained_dict['module.ClassHead.1.conv1x1.weight'] # # del pretrained_dict['module.ClassHead.1.conv1x1.bias'] # # del pretrained_dict['module.ClassHead.2.conv1x1.weight'] # # del pretrained_dict['module.ClassHead.2.conv1x1.bias'] # model.load_state_dict(pretrained_dict, strict=False) # start_epoch = checkpoint['epoch'] + 1 # flog.error('已特殊加载 feadre 权重文件为 %s', file_weight) # return start_epoch ''' debug ''' if ffun is not None: pretrained_dict = ffun(pretrained_dict_y) else: pretrained_dict = pretrained_dict_y dd = {} # 多GPU处理 ss = 'module.' for k, v in pretrained_dict.items(): if is_mgpu: if ss not in k: dd[ss + k] = v else: dd = pretrained_dict_y break # dd[k] = v else: dd[k.replace(ss, '')] = v '''重组权重''' # load_weights_dict = {k: v for k, v in weights_dict.items() # if model.state_dict()[k].numel() == v.numel()} keys_missing, keys_unexpected = model.load_state_dict(dd, strict=False) if len(keys_missing) > 0 or len(keys_unexpected): flog.error('missing_keys %s', keys_missing) # 这个是 model 的属性 flog.error('unexpected_keys %s', keys_unexpected) # 这个是 pth 的属性 if optimizer: optimizer.load_state_dict(checkpoint['optimizer']) if lr_scheduler and checkpoint['lr_scheduler']: lr_scheduler.load_state_dict(checkpoint['lr_scheduler']) if 'epoch' in checkpoint: start_epoch = checkpoint['epoch'] + 1 else: start_epoch = 0 flog.warning('已加载 feadre 权重文件为 %s', file_weight) else: # raise Exception(' 未加载 feadre权重文件 ') flog.error(' 未加载 feadre权重文件 %s', file_weight) if fis_mgpu(): path = os.path.join(tempfile.gettempdir(), "_init_weights_tmp.pt") checkpoint_path = path if is_main_process(): torch.save(model.state_dict(), checkpoint_path) # import torch.distributed as dist torch.distributed.barrier() # 多GPU阻塞 model.load_state_dict( torch.load(checkpoint_path, map_location=device)) flog.error('已默认加载临时文件 %s', path) return start_epoch
coco_obj = COCO(file_json) id_ = 1 image_info = coco_obj.loadImgs(id_)[0] file_img = os.path.join(path_img, image_info['file_name']) img_np = cv2.imread(file_img) annotation_ids = coco_obj.getAnnIds(id_) bboxs = np.zeros((0, 4), dtype=np.float32) # np创建 空数组 高级 labels = [] coco_anns = coco_obj.loadAnns(annotation_ids) for a in coco_anns: # skip the annotations with width or height < 1 if a['bbox'][2] < 1 or a['bbox'][3] < 1: flog.warning('标记框有问题 %s', a) continue labels.append(a['category_id']) bbox = np.zeros((1, 4), dtype=np.float32) bbox[0, :4] = a['bbox'] bboxs = np.append(bboxs, bbox, axis=0) bboxs_ltrb = ltwh2ltrb(bboxs) # f_plt_show_cv(img_np, gboxes_ltrb=torch.tensor(bboxs_ltrb), labels_text=labels, is_recover_size=False) # fd = RandomMirror() # fd = Expand(mean=(0.406, 0.456, 0.485)) # fd = RandomSampleCrop() # fd = Normalize(mean=(0.406, 0.456, 0.485), std=(0.225, 0.224, 0.229))