def visualize_bounding_boxes(ibs, config, version, gid_list=None, randomize=False, num_images=10, output_path=None): if gid_list is None: gid_list = general_get_imageset_gids(ibs, 'TEST_SET', **config) if randomize: random.shuffle(gid_list) if num_images not in [-1, None]: num_images = min(num_images, len(gid_list)) gid_list = gid_list[:num_images] uuid_list = ibs.get_image_uuids(gid_list) assert version is not None version = version.lower() if version == 'prediction': print('\tGather Predictions') val_dict = localizer_parse_pred(ibs, test_gid_list=gid_list, **config) elif version == 'ground_truth': print('\tGather Ground-Truth') val_dict = general_parse_gt(ibs, test_gid_list=gid_list, **config) if output_path is None: output_path = abspath(expanduser(join('~', 'Desktop', 'bboxes'))) ut.ensuredir(output_path) for gid, image_uuid in zip(gid_list, uuid_list): image = ibs.get_images(gid) image = _resize(image, t_width=500) h, w, c = image.shape val_list = val_dict[image_uuid] for val in val_list: xbr = int(np.around(val['xbr'] * w)) ybr = int(np.around(val['ybr'] * h)) xtl = int(np.around(val['xtl'] * w)) ytl = int(np.around(val['ytl'] * h)) cv2.rectangle(image, (xtl, ytl), (xbr, ybr), (0, 140, 255), 4) write_filename = 'bboxes_%d_%s.png' % ( gid, version, ) write_filepath = join(output_path, write_filename) print(write_filepath) cv2.imwrite(write_filepath, image)
def classifier_visualize_training_localizations(ibs, classifier_weight_filepath, species_list=['zebra'], scheme=2, output_path=None, values=None, **kwargs): def _draw(image_dict, list_, color): for _ in list_: vals = _['gid'], _['xbr'], _['ybr'], _['xtl'], _['ytl'] gid, xbr, ybr, xtl, ytl = vals height, width = image_dict[gid].shape[:2] xbr = int(xbr * width) ybr = int(ybr * height) xtl = int(xtl * width) ytl = int(ytl * height) image = image_dict[gid] cv2.rectangle(image, (xtl, ytl), (xbr, ybr), color, 4) def _write_chips(chip_list, output_path_fmt_str): interpolation = cv2.INTER_LANCZOS4 warpkw = dict(interpolation=interpolation) chip_list = [] for _ in list_: vals = _['gid'], _['xbr'], _['ybr'], _['xtl'], _['ytl'] gid, xbr, ybr, xtl, ytl = vals height, width = image_dict[gid].shape[:2] xbr = int(xbr * width) ybr = int(ybr * height) xtl = int(xtl * width) ytl = int(ytl * height) image = image_dict[gid] # Get chips chip = image[ytl:ybr, xtl:xbr, :] chip = cv2.resize(chip, (192, 192), **warpkw) chip_list.append(chip) return chip_list # Get output path if output_path is None: output_path = abspath( expanduser(join('~', 'Desktop', 'output-bootstrap'))) ut.delete(output_path) ut.ensuredir(output_path) if values is None: # Load data print('Loading pre-trained features for filtered localizations') train_gid_list = general_get_imageset_gids(ibs, 'TRAIN_SET', **kwargs) train_gid_list = train_gid_list[:10] config = { 'algo': '_COMBINED', 'species_set': set(species_list), 'features': True, 'feature2_algo': 'resnet', 'classify': True, 'classifier_algo': 'svm', 'classifier_weight_filepath': classifier_weight_filepath, 'nms': True, 'nms_thresh': 0.50, # 'thresh' : True, # 'index_thresh' : 0.25, } print('\tGather Ground-Truth') gt_dict = general_parse_gt(ibs, test_gid_list=train_gid_list, **config) print('\tGather Predictions') pred_dict = localizer_parse_pred(ibs, test_gid_list=train_gid_list, **config) print('Mine proposals') reviewed_gid_dict = {} values = _bootstrap_mine(ibs, gt_dict, pred_dict, scheme, reviewed_gid_dict, **kwargs) mined_gid_list, mined_gt_list, mined_pos_list, mined_neg_list = values print('Prepare images') # Get images and a dictionary based on their gids image_list = ibs.get_images(mined_gid_list) image_dict = {gid: image for gid, image in zip(mined_gid_list, image_list)} # Draw positives list_ = mined_pos_list color = (0, 255, 0) chip_list = _draw(image_dict, list_, color) pos_path = join(output_path, 'positives') ut.ensuredir(pos_path) _write_chips(chip_list, join(pos_path, 'chips_pos_%05d.png')) # Draw negatives list_ = mined_neg_list color = (0, 0, 255) chip_list = _draw(image_dict, list_, color) neg_path = join(output_path, 'negatives') ut.ensuredir(neg_path) _write_chips(chip_list, join(neg_path, 'chips_neg_%05d.png')) # Draw positives list_ = mined_gt_list color = (255, 0, 0) _draw(image_dict, list_, color) print('Write images to %r' % (output_path, )) # Write images to disk for gid in image_dict: output_filename = 'localizations_gid_%d.png' % (gid, ) output_filepath = join(output_path, output_filename) cv2.imwrite(output_filepath, image_dict[gid])
def export_to_xml(ibs, species_list, species_mapping=None, offset='auto', enforce_viewpoint=False, target_size=900, purge=False, use_maximum_linear_dimension=True, use_existing_train_test=True, include_parts=False, gid_list=None, output_path=None, min_annot_size=5, **kwargs): """Create training XML for training models.""" import random from datetime import date from detecttools.pypascalmarkup import PascalVOC_Markup_Annotation if species_mapping is not None: print('Received species_mapping = %r' % (species_mapping, )) print('Using species_list = %r' % (species_list, )) def _add_annotation(bbox, theta, species_name, viewpoint, interest, decrease, part_name=None): if species_name is not None: if species_name not in species_list: return # Transformation matrix R = vt.rotation_around_bbox_mat3x3(theta, bbox) # Get verticies of the annotation polygon verts = vt.verts_from_bbox(bbox, close=True) # Rotate and transform vertices xyz_pts = vt.add_homogenous_coordinate(np.array(verts).T) trans_pts = vt.remove_homogenous_coordinate(R.dot(xyz_pts)) new_verts = np.round(trans_pts).astype(np.int).T.tolist() x_points = [pt[0] for pt in new_verts] y_points = [pt[1] for pt in new_verts] xmin = int(min(x_points) * decrease) xmax = int(max(x_points) * decrease) ymin = int(min(y_points) * decrease) ymax = int(max(y_points) * decrease) # Bounds check xmin = max(xmin, 0) ymin = max(ymin, 0) xmax = min(xmax, width - 1) ymax = min(ymax, height - 1) # Get info info = {} w_ = xmax - xmin h_ = ymax - ymin if w_ < min_annot_size: return if h_ < min_annot_size: return if viewpoint != -1 and viewpoint is not None: info['pose'] = viewpoint if interest is not None: info['interest'] = '1' if interest else '0' if part_name is not None: species_name = '%s+%s' % ( species_name, part_name, ) area = w_ * h_ print('\t\tAdding %r with area %0.04f pixels^2' % ( species_name, area, )) annotation.add_object(species_name, (xmax, xmin, ymax, ymin), **info) current_year = int(date.today().year) information = {'database_name': ibs.get_dbname()} import datetime now = datetime.datetime.now() folder = 'VOC%d' % (now.year, ) if output_path is None: output_path = ibs.get_cachedir() datadir = join(output_path, 'VOCdevkit', folder) imagedir = join(datadir, 'JPEGImages') annotdir = join(datadir, 'Annotations') setsdir = join(datadir, 'ImageSets') mainsetsdir = join(setsdir, 'Main') if purge: ut.delete(datadir) ut.ensuredir(datadir) ut.ensuredir(imagedir) ut.ensuredir(annotdir) ut.ensuredir(setsdir) ut.ensuredir(mainsetsdir) # Get all gids and process them if gid_list is None: gid_list = sorted(ibs.get_valid_gids()) sets_dict = { 'test': [], 'train': [], 'trainval': [], 'val': [], } index = 1 if offset == 'auto' else offset # Make a preliminary train / test split as imagesets or use the existing ones if not use_existing_train_test: ibs.imageset_train_test_split(**kwargs) train_gid_set = set(general_get_imageset_gids(ibs, 'TRAIN_SET', **kwargs)) test_gid_set = set(general_get_imageset_gids(ibs, 'TEST_SET', **kwargs)) print('Exporting %d images' % (len(gid_list), )) for gid in gid_list: aid_list = ibs.get_image_aids(gid) image_uri = ibs.get_image_uris(gid) image_path = ibs.get_image_paths(gid) if len(aid_list) > -1: fulldir = image_path.split('/') filename = fulldir.pop() extension = filename.split('.')[-1] # NOQA out_name = '%d_%06d' % ( current_year, index, ) out_img = '%s.jpg' % (out_name, ) _image = ibs.get_images(gid) height, width, channels = _image.shape condition = width > height if use_maximum_linear_dimension else width < height if condition: ratio = height / width decrease = target_size / width width = target_size height = int(target_size * ratio) else: ratio = width / height decrease = target_size / height height = target_size width = int(target_size * ratio) dst_img = join(imagedir, out_img) _image = vt.resize(_image, (width, height)) vt.imwrite(dst_img, _image) annotation = PascalVOC_Markup_Annotation(dst_img, folder, out_img, source=image_uri, **information) bbox_list = ibs.get_annot_bboxes(aid_list) theta_list = ibs.get_annot_thetas(aid_list) species_name_list = ibs.get_annot_species_texts(aid_list) viewpoint_list = ibs.get_annot_viewpoints(aid_list) interest_list = ibs.get_annot_interest(aid_list) part_rowids_list = ibs.get_annot_part_rowids(aid_list) zipped = zip(bbox_list, theta_list, species_name_list, viewpoint_list, interest_list, part_rowids_list) for bbox, theta, species_name, viewpoint, interest, part_rowid_list in zipped: if species_mapping is not None: species_name = species_mapping.get(species_name, species_name) _add_annotation(bbox, theta, species_name, viewpoint, interest, decrease) if include_parts and len(part_rowid_list) > 0: part_bbox_list = ibs.get_part_bboxes(part_rowid_list) part_theta_list = ibs.get_part_thetas(part_rowid_list) part_name_list = ibs.get_part_tag_text(part_rowid_list) part_zipped = zip(part_bbox_list, part_theta_list, part_name_list) for part_bbox, part_theta, part_name in part_zipped: _add_annotation(part_bbox, part_theta, species_name, viewpoint, None, decrease, part_name=part_name) out_filename = '%s.xml' % (out_name, ) dst_annot = join(annotdir, out_filename) if gid in test_gid_set: sets_dict['test'].append(out_name) elif gid in train_gid_set: state = random.uniform(0.0, 1.0) if state <= 0.75: sets_dict['train'].append(out_name) sets_dict['trainval'].append(out_name) else: sets_dict['val'].append(out_name) sets_dict['trainval'].append(out_name) else: raise AssertionError( 'All gids must be either in the TRAIN_SET or TEST_SET imagesets' ) # Write XML print('Copying:\n%r\n%r\n%r\n\n' % ( image_path, dst_img, (width, height), )) xml_data = open(dst_annot, 'w') xml_data.write(annotation.xml()) xml_data.close() while exists(dst_annot): index += 1 if offset != 'auto': break out_filename = '%d_%06d.xml' % ( current_year, index, ) dst_annot = join(annotdir, out_filename) else: print('Skipping:\n%r\n\n' % (image_path, )) for key in sets_dict.keys(): manifest_filename = '%s.txt' % (key, ) manifest_filepath = join(mainsetsdir, manifest_filename) with open(manifest_filepath, 'w') as file_: sets_dict[key].append('') content = sets_dict[key] content = '\n'.join(content) file_.write(content) print('...completed') return datadir
def export_to_coco(ibs, species_list, species_mapping={}, target_size=2400, use_maximum_linear_dimension=True, use_existing_train_test=True, gid_list=None, include_reviews=False, require_named=True, output_images=True, **kwargs): """Create training COCO dataset for training models.""" from datetime import date import datetime import random import json print('Received species_mapping = %r' % (species_mapping, )) print('Using species_list = %r' % (species_list, )) current_year = int(date.today().year) datadir = abspath(join(ibs.get_cachedir(), 'coco')) annotdir = join(datadir, 'annotations') imagedir = join(datadir, 'images') image_dir_dict = { 'train': join(imagedir, 'train%s' % (current_year, )), 'val': join(imagedir, 'val%s' % (current_year, )), 'test': join(imagedir, 'test%s' % (current_year, )), } ut.delete(datadir) ut.ensuredir(datadir) ut.ensuredir(annotdir) ut.ensuredir(imagedir) for dataset in image_dir_dict: ut.ensuredir(image_dir_dict[dataset]) info = { 'description': 'Wild Me %s Dataset' % (ibs.dbname, ), # 'url' : 'http://www.greatgrevysrally.com', 'url': 'http://www.wildme.org', 'version': '1.0', 'year': current_year, 'contributor': 'Wild Me, Jason Parham <*****@*****.**>', 'date_created': datetime.datetime.utcnow().isoformat(' '), 'ibeis_database_name': ibs.get_db_name(), 'ibeis_database_uuid': str(ibs.get_db_init_uuid()), } licenses = [ { 'url': 'http://creativecommons.org/licenses/by-nc-nd/2.0/', 'id': 3, 'name': 'Attribution-NonCommercial-NoDerivs License', }, ] assert len(species_list) == len( set(species_list)), 'Cannot have duplicate species in species_list' category_dict = {} categories = [] for index, species in enumerate(sorted(species_list)): species = species_mapping.get(species, species) categories.append({ 'id': index, 'name': species, 'supercategory': 'animal', }) category_dict[species] = index output_dict = {} for dataset in ['train', 'val', 'test']: output_dict[dataset] = { 'info': info, 'licenses': licenses, 'categories': categories, 'images': [], 'annotations': [], } # Get all gids and process them if gid_list is None: aid_list = ibs.get_valid_aids() species_list_ = ibs.get_annot_species(aid_list) flag_list = [ species_mapping.get(species_, species_) in species_list for species_ in species_list_ ] aid_list = ut.compress(aid_list, flag_list) if require_named: nid_list = ibs.get_annot_nids(aid_list) flag_list = [nid >= 0 for nid in nid_list] aid_list = ut.compress(aid_list, flag_list) gid_list = sorted(list(set(ibs.get_annot_gids(aid_list)))) # Make a preliminary train / test split as imagesets or use the existing ones if not use_existing_train_test: ibs.imageset_train_test_split(**kwargs) train_gid_set = set(general_get_imageset_gids(ibs, 'TRAIN_SET', **kwargs)) test_gid_set = set(general_get_imageset_gids(ibs, 'TEST_SET', **kwargs)) image_index = 1 annot_index = 1 aid_dict = {} print('Exporting %d images' % (len(gid_list), )) for gid in gid_list: if gid in test_gid_set: dataset = 'test' elif gid in train_gid_set: state = random.uniform(0.0, 1.0) if state <= 0.75: dataset = 'train' else: dataset = 'val' else: raise AssertionError( 'All gids must be either in the TRAIN_SET or TEST_SET imagesets' ) width, height = ibs.get_image_sizes(gid) if target_size is None: decrease = 1.0 else: condition = width > height if use_maximum_linear_dimension else width < height if condition: ratio = height / width decrease = target_size / width width = target_size height = int(target_size * ratio) else: ratio = width / height decrease = target_size / height height = target_size width = int(target_size * ratio) image_path = ibs.get_image_paths(gid) image_filename = '%012d.jpg' % (image_index, ) image_filepath = join(image_dir_dict[dataset], image_filename) if output_images: _image = ibs.get_images(gid) _image = vt.resize(_image, (width, height)) vt.imwrite(image_filepath, _image) output_dict[dataset]['images'].append({ 'license': 3, # 'file_name' : image_filename, 'file_name': basename(ibs.get_image_uris_original(gid)), 'coco_url': None, 'height': height, 'width': width, 'date_captured': ibs.get_image_datetime_str(gid).replace('/', '-'), 'flickr_url': None, 'id': image_index, 'ibeis_image_uuid': str(ibs.get_image_uuids(gid)), }) print('Copying:\n%r\n%r\n%r\n\n' % ( image_path, image_filepath, (width, height), )) aid_list = ibs.get_image_aids(gid) bbox_list = ibs.get_annot_bboxes(aid_list) theta_list = ibs.get_annot_thetas(aid_list) species_name_list = ibs.get_annot_species_texts(aid_list) viewpoint_list = ibs.get_annot_viewpoints(aid_list) nid_list = ibs.get_annot_nids(aid_list) seen = 0 zipped = zip(aid_list, bbox_list, theta_list, species_name_list, viewpoint_list, nid_list) for aid, bbox, theta, species_name, viewpoint, nid in zipped: species_name = species_mapping.get(species_name, species_name) if species_name is None: continue if species_name not in species_list: continue if require_named and nid < 0: continue # Transformation matrix R = vt.rotation_around_bbox_mat3x3(theta, bbox) verts = vt.verts_from_bbox(bbox, close=True) xyz_pts = vt.add_homogenous_coordinate(np.array(verts).T) trans_pts = vt.remove_homogenous_coordinate(R.dot(xyz_pts)) new_verts = np.round(trans_pts).astype(np.int).T.tolist() x_points = [int(np.around(pt[0] * decrease)) for pt in new_verts] y_points = [int(np.around(pt[1] * decrease)) for pt in new_verts] segmentation = ut.flatten(list(zip(x_points, y_points))) xmin = max(min(x_points), 0) ymin = max(min(y_points), 0) xmax = min(max(x_points), width - 1) ymax = min(max(y_points), height - 1) w = xmax - xmin h = ymax - ymin area = w * h # individuals = ibs.get_name_aids(ibs.get_annot_nids(aid)) reviews = ibs.get_review_rowids_from_single([aid])[0] user_list = ibs.get_review_identity(reviews) aid_tuple_list = ibs.get_review_aid_tuple(reviews) decision_list = ibs.get_review_decision_str(reviews) ids = [] decisions = [] zipped = zip(user_list, aid_tuple_list, decision_list) for user, aid_tuple, decision in zipped: if 'user:web' not in user: continue match = list(set(aid_tuple) - set([aid])) assert len(match) == 1 ids.append(match[0]) decisions.append(decision.lower()) xtl_, ytl_, w_, h_ = bbox xtl_ *= decrease ytl_ *= decrease w_ *= decrease h_ *= decrease annot = { 'bbox': [xtl_, ytl_, w_, h_], 'theta': theta, 'viewpoint': viewpoint, 'segmentation': [segmentation], 'segmentation_bbox': [xmin, ymin, w, h], 'area': area, 'iscrowd': 0, 'image_id': image_index, 'category_id': category_dict[species_name], 'id': annot_index, 'ibeis_annot_uuid': str(ibs.get_annot_uuids(aid)), 'ibeis_annot_name': str(ibs.get_annot_name_texts(aid)), # 'individual_ids' : individuals, } if include_reviews: annot['review_ids'] = list(zip(ids, decisions)) output_dict[dataset]['annotations'].append(annot) seen += 1 print('\t\tAdding %r with area %0.04f pixels^2' % ( species_name, area, )) aid_dict[aid] = annot_index annot_index += 1 # assert seen > 0 image_index += 1 for dataset in output_dict: annots = output_dict[dataset]['annotations'] for index in range(len(annots)): annot = annots[index] # Map internal aids to external annot index # individual_ids = annot['individual_ids'] # individual_ids_ = [] # for individual_id in individual_ids: # if individual_id not in aid_dict: # continue # individual_id_ = aid_dict[individual_id] # individual_ids_.append(individual_id_) # annot['individual_ids'] = individual_ids_ # Map reviews if include_reviews: review_ids = annot['review_ids'] review_ids_ = [] for review in review_ids: review_id, review_decision = review if review_id not in aid_dict: continue review_id_ = aid_dict[review_id] review_ = ( review_id_, review_decision, ) review_ids_.append(review_) annot['review_ids'] = review_ids_ # Store output_dict[dataset]['annotations'][index] = annot for dataset in output_dict: json_filename = 'instances_%s%s.json' % ( dataset, current_year, ) json_filepath = join(annotdir, json_filename) with open(json_filepath, 'w') as json_file: json.dump(output_dict[dataset], json_file) print('...completed') return datadir