Esempio n. 1
0
def fixMasks(img_path, mask_path, csv_path, out_size='', out_dir='',
             save_video=1, write_text=0, show_img=1, frames_reader=None,
             img_ext='jpg', mask_ext='png', out_ext='mkv', codec='H264', fps=30, border=0, fixed_ar=0,
             include_binary=1, include_orig=1, show_bbox=1, map_to_bbox=0, apply_contour=0,
             writer=None, raw_mask=0):
    global _pause, _exit

    if map_to_bbox and not csv_path:
        csv_path = os.path.join(img_path, 'annotations.csv')

    img_files = [os.path.join(img_path, k) for k in os.listdir(img_path) if
                 os.path.splitext(k.lower())[1][1:] == img_ext]

    mask_files = [os.path.join(mask_path, k) for k in os.listdir(mask_path) if
                  os.path.splitext(k.lower())[1][1:] == mask_ext]

    n_img_files, n_mask_files = len(img_files), len(mask_files)

    if n_img_files == 0:
        raise IOError('No img_files of type {} found in {}'.format(img_ext, img_path))

    if n_mask_files == 0:
        raise IOError('No mask_files of type {} found in {}'.format(mask_ext, mask_path))

    print('Found {} image and {} mask files'.format(n_img_files, n_mask_files))

    win_name = 'patch and mask'

    text_fmt = ('green', 0, 5, 1.0, 1)
    text_color = utils.col_rgb[text_fmt[0]]
    text_font = utils.CVConstants.fonts[text_fmt[2]]
    text_font_size = text_fmt[3]
    text_thickness = text_fmt[4]
    text_location = (5, 15)
    if cv2.__version__.startswith('2'):
        font_line_type = cv2.CV_AA
    else:
        font_line_type = cv2.LINE_AA

    # n_disp_img = 1
    # if include_orig:
    #     n_disp_img += 1
    # if include_binary:
    #     n_disp_img += 1

    retrieval_mode = None

    if apply_contour == 1:
        retrieval_mode = cv2.RETR_EXTERNAL
    elif apply_contour == 2:
        retrieval_mode = cv2.RETR_CCOMP
    elif apply_contour == 3:
        retrieval_mode = cv2.RETR_TREE

    out_path = ''
    if save_video:
        out_name = os.path.basename(mask_path)
        if apply_contour:
            out_name += '_contour_{}'.format(apply_contour)
        out_name += '.' + out_ext
        if not out_dir:
            out_dir = os.path.dirname(mask_path)
        out_path = os.path.join(out_dir, out_name)

    seq_name = os.path.basename(img_path)

    print('img_path: ', img_path)
    print('mask_path: ', mask_path)
    print('csv_path: ', csv_path)
    print('seq_name: ', seq_name)

    # if n_img_files != n_mask_files:
    #     raise IOError('Mismatch between n_img_files: {} and n_mask_files: {}'.format(n_img_files, n_mask_files))
    one_to_one_mode = 0
    if n_img_files == n_mask_files:
        print('Using one_to_one_mode instead of filename matching to associate masks with images')
        one_to_one_mode = 1

    if csv_path:
        df = pd.read_csv(csv_path)

    if out_path and writer is None:
        if out_size:
            out_size = tuple([int(x) for x in out_size.split('x')])
            if 0 in out_size:
                img_h, img_w = cv2.imread(img_files[0]).shape[:2]
                if out_size[0] == 0 and out_size[1] == 0:
                    out_w, out_h = img_w, img_h
                elif out_size[0] == 0:
                    out_h = out_size[1]
                    out_w = int(img_w * (float(out_h) / float(img_h)))
                elif out_size[1] == 0:
                    out_w = out_size[0]
                    out_h = int(img_h * (float(out_w) / float(img_w)))
                out_size = (out_w, out_h)
        else:
            out_size = (1920, 1080)

        image_exts = ['jpg', 'bmp', 'png']
        if out_ext[0] in image_exts:
            writer = ImageWriter(out_path)
        else:
            writer = cv2.VideoWriter()
            writer_params = {
                'filename': out_path,
                'fps': int(fps),
                'frameSize': out_size,
            }
            if cv2.__version__.startswith('2'):
                writer_params['fourcc'] = cv2.cv.CV_FOURCC(*codec)
            else:
                writer_params['apiPreference'] = cv2.CAP_FFMPEG
                writer_params['fourcc'] = cv2.VideoWriter_fourcc(*codec)

            writer.open(**writer_params)
            if not writer.isOpened():
                raise IOError('Video file {:s} could not be opened'.format(out_path))
            print('Writing {}x{} video to {}'.format(out_size[0], out_size[1], out_path))

    n_valid_masks = 0
    for file_id in range(n_img_files):
        img_file = img_files[file_id]
        img_file = img_file.replace('\\', '/')

        filename = os.path.basename(img_file)
        filename_no_ext = os.path.splitext(filename)[0]

        if one_to_one_mode:
            curr_mask_files = [mask_files[file_id], ]
        else:
            curr_mask_files = [k for k in mask_files if
                               os.path.basename(k).startswith(filename_no_ext)]
            # filename_no_ext_rev = filename_no_ext[::-1]
            # curr_mask_files = [k for k in mask_files if
            #                    os.path.splitext(os.path.basename(k))[0][::-1].startswith(filename_no_ext_rev)
            #                    and os.path.commonprefix([os.path.basename(k), filename_no_ext])]

        if not curr_mask_files:
            # print('No matching curr_mask file found for {} with filename_no_ext: {}'.format(
            #     img_file, filename_no_ext))
            continue

        img = cv2.imread(img_file)
        if img is None:
            raise IOError('img_file could not be read: {}'.format(img_file))

        img_h, img_w = img.shape[:2]

        if csv_path:
            bboxes = df.loc[df['filename'] == filename]
            n_bboxes = len(bboxes.index)
            df = df.drop(bboxes.index[:n_bboxes])

            if one_to_one_mode and n_bboxes > 1:
                print('Considering only one out of {} boxes for {}'.format(n_bboxes, filename))
                n_bboxes = 1

            n_masks = len(curr_mask_files)
            if n_masks != n_bboxes:
                raise IOError('Mismatch between n_bboxes: {} and n_masks: {} for {}'.format(
                    n_bboxes, n_masks, img_file))

            mask_img = np.zeros_like(img)

            for box_id in range(n_bboxes):
                mask_file = curr_mask_files[box_id].replace('\\', '/')
                curr_mask = cv2.imread(mask_file)
                if curr_mask is None:
                    raise IOError('mask_file could not be read: {}'.format(mask_file))

                if apply_contour:
                    if apply_contour > 1:
                        contours, _ = cv2.findContours(curr_mask[:, :, 0].astype(np.uint8), retrieval_mode,
                                                       cv2.CHAIN_APPROX_NONE)[-2:]
                        curr_mask = np.zeros_like(curr_mask, dtype=np.uint8)
                        cv2.drawContours(curr_mask, contours, -1, (255, 255, 255), -1)
                    else:
                        contours, _ = Shape.contourPtsFromMask(curr_mask)
                        curr_mask, _ = Shape.contourPtsToMask(contours, curr_mask)

                mask_h, mask_w = curr_mask.shape[:2]

                bbox = bboxes.iloc[box_id]
                xmin = bbox.loc['xmin']
                ymin = bbox.loc['ymin']
                xmax = bbox.loc['xmax']
                ymax = bbox.loc['ymax']

                mask_img = map_mask_to_bbox((xmin, ymin, xmax, ymax), curr_mask,
                                            fixed_ar, border, mask_img.shape, mask_img)
                if show_bbox:
                    cv2.rectangle(img, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)

                if map_to_bbox == 2:
                    img = img[ymin:ymax, xmin:xmax, :]
                    mask_img = mask_img[ymin:ymax, xmin:xmax, :]
        else:
            mask_file = curr_mask_files[0].replace('\\', '/')
            mask_img = cv2.imread(mask_file)
            if mask_img is None:
                raise IOError('mask_file could not be read: {}'.format(mask_file))

            mask_h, mask_w = mask_img.shape[:2]

            if img_h != mask_h or img_w != mask_w:
                mask_img = cv2.resize(mask_img, (img_w, img_h))

        if raw_mask:
            mask_img *= 255

        blended_img = np.asarray(Image.blend(Image.fromarray(img), Image.fromarray(mask_img), 0.5))

        def paintMouseHandler(event, x, y, flags=None, param=None):
            nonlocal mask_pts, contour_pts, blended_img, mask_img, disp_img, del_thresh, mag_patch_size, mag_win_size, \
                mouse_x, mouse_y, prev_mouse_pt, draw_mask_kb, paint_mode

            paint_mode = 1
            mouse_x, mouse_y = x, y
            # refresh_paint_win = 1
            draw_marker = 1
            marker_col = (0, 255, 0)
            # _show_magnified_window = 0

            if event == cv2.EVENT_MOUSEMOVE:
                # print('flags: {}'.format(flags))
                # refresh_paint_win = 1
                if flags == 1 or flags == 25:
                    # left button
                    min_x, min_y = x - del_thresh, y - del_thresh
                    max_x, max_y = x + del_thresh, y + del_thresh
                    mask_img[min_y:max_y, min_x:max_x, :] = 255
                    blended_img[min_y:max_y, min_x:max_x, :] = (shape_patch[min_y:max_y, min_x:max_x,
                                                                :] + 255.0) / 2.0
                    marker_col = (0, 255, 0)
                elif flags == 17:
                    # shift + left button
                    min_x, min_y = x - del_thresh, y - del_thresh
                    max_x, max_y = x + del_thresh, y + del_thresh
                    mask_img[min_y:max_y, min_x:max_x, :] = 0
                    blended_img[min_y:max_y, min_x:max_x, :] = (shape_patch[min_y:max_y, min_x:max_x, :]) / 2.0
                    marker_col = (0, 0, 255)
                elif flags == 32:
                    draw_marker = 0
                elif flags == 16:
                    marker_col = (0, 0, 255)
                elif flags == 8:
                    draw_marker = 0
                # else:
                #     draw_marker = 0
            elif event == cv2.EVENT_LBUTTONDOWN:
                # print('flags: {}'.format(flags))
                pass
            elif event == cv2.EVENT_RBUTTONUP:
                # print('flags: {}'.format(flags))
                pass
            elif event == cv2.EVENT_MBUTTONDOWN:
                contour_pts, mask_pts = self.contourPtsFromMask(mask_img)
                draw_mask_kb = 1
                # print('flags: {}'.format(flags))
            elif event == cv2.EVENT_MOUSEWHEEL:
                if flags > 0:
                    if flags == mouse_whl_keys_to_flags['ctrl+alt+shift'][0]:
                        mag_win_size += 10
                        print('magnified window size increased to {}'.format(mag_win_size))
                    elif flags == mouse_whl_keys_to_flags['ctrl+shift'][0]:
                        mag_patch_size -= 1
                        if mag_patch_size < 5:
                            mag_patch_size = 5
                    else:
                        if del_thresh < 10:
                            del_thresh += 1
                        else:
                            del_thresh += 5
                        print('del_thresh increased to {}'.format(del_thresh))
                else:
                    if flags == mouse_whl_keys_to_flags['ctrl+alt+shift'][1]:
                        mag_win_size -= 10
                        if mag_win_size < 100:
                            mag_win_size = 100
                        print('magnified window size decreased to {}'.format(mag_win_size))

                    elif flags == mouse_whl_keys_to_flags['ctrl+shift'][1]:
                        mag_patch_size += 1
                    else:
                        if del_thresh < 10:
                            del_thresh = max(del_thresh - 1, 1)
                        else:
                            del_thresh -= 5
                        print('del_thresh decreased to {}'.format(del_thresh))

            if draw_marker:
                disp_img = np.copy(blended_img)
                min_x, min_y = x - del_thresh, y - del_thresh
                max_x, max_y = x + del_thresh, y + del_thresh
                cv2.rectangle(disp_img, (min_x, min_y), (max_x, max_y), marker_col, 1)
            else:
                disp_img = blended_img
            cv2.imshow(paint_win_name, disp_img)

            if show_magnified_window:
                showMagnifiedWindow(x, y, _shape_patch, draw_marker=2,
                                    marker_col=marker_col,
                                    # win_name='Paint Magnified'
                                    )
            # cv2.imshow('binary mask', mask_img)
            prev_mouse_pt = (x, y)


        if include_orig and include_binary and 3 * img_w > out_size[0]:
            disp_img = np.concatenate((img, mask_img), axis=0)
            disp_img = np.concatenate((disp_img, cv2.resize(blended_img, (0, 0), fx=2, fy=2)), axis=1)

        else:
            disp_img = blended_img
            if include_binary:
                disp_img = np.concatenate((mask_img, disp_img), axis=1)
            if include_orig:
                disp_img = np.concatenate((img, disp_img), axis=1)


        disp_img = resizeAR(disp_img, out_size[0], out_size[1])

        if save_video:
            if write_text:
                cv2.putText(disp_img, '{} frame {:d}'.format(seq_name, file_id + 1), text_location,
                            text_font, text_font_size, text_color, text_thickness, text_line_type)
            writer.write(disp_img)

        if show_img:
            cv2.imshow(win_name, disp_img)
            k = cv2.waitKey(1 - _pause)
            if k == 27:
                break
            elif k == ord('q'):
                _exit = 1
                break
            elif k == 32:
                _pause = 1 - _pause

        if _exit:
            break

        sys.stdout.write('\rDone {:d}/{:d} files'.format(
            file_id, n_img_files))
        sys.stdout.flush()
        n_valid_masks += 1

    sys.stdout.write('\n')
    sys.stdout.flush()

    if n_valid_masks == 0:
        raise IOError('No valid masks found')

    # if save_video:
    #     writer.release()

    if show_img:
        cv2.destroyWindow(win_name)

    return writer, out_size
Esempio n. 2
0
def main():
    global _pause, _quit
    params = VisParams()
    paramparse.process(params)

    # _args = [k for k in sys.argv[1:] if not k.startswith('vis.')]
    # vis_args = ['--{}'.format(k.replace('vis.', '')) for k in sys.argv[1:] if k.startswith('vis.')]

    # processArguments(_args, params)
    # params = _params

    seq_paths = params.seq_paths
    root_dir = params.root_dir
    csv_paths = params.csv_paths
    csv_root_dir = params.csv_root_dir
    class_names_path = params.class_names_path
    data_type = params.data_type
    n_frames = params.n_frames
    seq_prefix = params.seq_prefix
    n_vis = params.n_vis
    vis_size = params.vis_size
    enable_masks = params.enable_masks
    show_img = params.show_img
    save = params.save
    save_fmt = params.save_fmt
    save_dir = params.save_dir
    labels = params.labels
    grid_size = params.grid_size
    only_boxes = params.only_boxes
    crop_size = params.crop_size

    if crop_size:
        crop_size = tuple([int(x) for x in crop_size.split('x')])
        print('Cropping a region of size {}x{} around the box'.format(
            *crop_size))
    else:
        crop_size = ()

    if grid_size:
        grid_size = [int(k) for k in grid_size.split('x')]
        print('Using a grid size of {}x{}'.format(*grid_size))
    else:
        grid_size = None

    # params = Namespace(**params)

    if vis_size:
        vis_size = [int(x) for x in vis_size.split('x')]

    # get parameters
    # _params = ServerParams()
    # _params.processArguments()

    # print('vis_args: ', _params.vis.__dict__)
    # processArguments2(_params, vis_args)

    # print('_params: ', _params)

    # setup logger
    logging_fmt = '%(levelname)s::%(module)s::%(funcName)s::%(lineno)s :  %(message)s'
    logging_level = logging.INFO
    # logging_level = logging.DEBUG
    # logging_level = PROFILE_LEVEL_NUM
    logging.basicConfig(level=logging_level, format=logging_fmt)
    _logger = logging.getLogger()
    _logger.setLevel(logging.INFO)

    if seq_paths:
        if os.path.isfile(seq_paths):
            seq_paths = [
                x.strip() for x in open(seq_paths).readlines() if x.strip()
            ]
        else:
            seq_paths = seq_paths.split(',')
        if root_dir:
            seq_paths = [os.path.join(root_dir, name) for name in seq_paths]

    elif root_dir:
        seq_paths = [
            os.path.join(root_dir, name) for name in os.listdir(root_dir)
            if os.path.isdir(os.path.join(root_dir, name))
        ]
        seq_paths.sort(key=sortKey)
    else:
        raise IOError('Either seq_paths or root_dir must be provided')

    if csv_paths:
        if os.path.isfile(csv_paths):
            csv_paths = [
                x.strip() for x in open(csv_paths).readlines() if x.strip()
            ]
        else:
            csv_paths = csv_paths.split(',')
        if csv_root_dir:
            csv_paths = [
                os.path.join(csv_root_dir, name) for name in csv_paths
            ]
    elif csv_root_dir:
        csv_paths = [
            os.path.join(csv_root_dir, name)
            for name in os.listdir(csv_root_dir)
            if os.path.isfile(os.path.join(csv_root_dir, name))
            and name.endswith('.csv')
        ]
        csv_paths.sort(key=sortKey)
    else:
        csv_paths = [
            os.path.join(seq_path, data_type + '.csv')
            for seq_path in seq_paths
        ]

    seq_path_ids = []

    if seq_prefix:
        seq_path_ids = [
            _id for _id, seq_path in enumerate(seq_paths)
            if os.path.basename(seq_path).startswith(seq_prefix)
        ]
        seq_paths = [seq_paths[_id] for _id in seq_path_ids]
        csv_paths = [csv_paths[_id] for _id in seq_path_ids]

    n_seq, n_csv = len(seq_paths), len(csv_paths)
    if n_seq != n_csv:
        raise IOError(
            'Mismatch between image {} and annotation {} lengths'.format(
                n_seq, n_csv))

    class_names = open(class_names_path, 'r').readlines()
    class_dict = {x.strip(): i for (i, x) in enumerate(class_names)}
    print('class_dict: ', class_dict)
    print('labels: ', labels)

    if n_vis > 0:
        if save:
            save_fname = '{:s}_{:s}.{:s}'.format(save_dir, getDateTime(),
                                                 save_fmt)
            save_path = os.path.join('log', save_fname)
            writer = ImageWriter(save_path, _logger)
            _logger.info('Saving {:s} image sequence to {:s}'.format(
                save_fmt, save_path))

        if n_seq % n_vis != 0:
            raise AssertionError('n_seq: {} not multiple of n_vis: {}'.format(
                n_seq, n_vis))
        n_groups = int(n_seq / n_vis)
        seq_id = 0
        label = ''
        for i in range(n_groups):

            vis_gen = []
            for j in range(n_vis):
                if labels:
                    label = labels[j]
                vis_gen.append(
                    visualize(params.vis,
                              _logger,
                              seq_paths[seq_id],
                              csv_paths[seq_id],
                              class_dict,
                              n_frames=n_frames,
                              generator_mode=1,
                              enable_masks=enable_masks,
                              label=label,
                              only_boxes=only_boxes,
                              crop_size=crop_size))
                seq_id += 1
            for imgs in zip(*vis_gen):
                # img_stacked = np.hstack(imgs)
                stack_params = {'grid_size': grid_size, 'preserve_order': 1}
                if crop_size:
                    stack_params['annotations'] = labels
                img_stacked = stackImages_ptf(imgs, **stack_params)
                img_stacked = cv2.cvtColor(img_stacked, cv2.COLOR_RGB2BGR)

                if vis_size:
                    img_stacked = resizeAR(img_stacked, vis_size[0],
                                           vis_size[1])
                if save:
                    writer.write(img_stacked)

                if show_img:
                    cv2.imshow('img_stacked', img_stacked)
                    key = cv2.waitKey(1 - _pause) % 256
                    if key == 27:
                        break
                    elif key == ord('q'):
                        _quit = 1
                        break
                    elif key == 32:
                        _pause = 1 - _pause
            if _quit:
                break
    if save:
        writer.release()

    else:
        for i in range(n_seq):
            visualize(params.vis,
                      _logger,
                      seq_paths[i],
                      csv_paths[i],
                      class_dict,
                      n_frames=n_frames,
                      enable_masks=enable_masks)
            if _quit:
                break
Esempio n. 3
0
                    if status == "MATCH!":
                        cv2.rectangle(img, (int(bb[0]), int(bb[1])), (int(bb[2]), int(bb[3])), green, 2)
                    else:
                        cv2.rectangle(img, (int(bb[0]), int(bb[1])), (int(bb[2]), int(bb[3])), light_red, 2)

                color = light_red
                if status == "MATCH!":
                    color = green
                text = "Result: " + status + " "
                img, line_width = utils.draw_text_in_image(img, text, (margin + line_width, v_pos), color,
                                                           line_width)
                if ovmax > 0:  # if there is intersections between the bounding-boxes
                    bbgt = [float(x) for x in gt_match["bbox"].split()]
                    cv2.rectangle(img, (int(bbgt[0]), int(bbgt[1])), (int(bbgt[2]), int(bbgt[3])), light_blue, 2)

                img_res_ar = resizeAR(img, save_w, save_h)
                cv2.imshow("Animation", img_res_ar)
                video_out.write(img_res_ar)
                k = cv2.waitKey(1 - _pause)
                if k == ord('q') or k == 27:
                    video_out.release()
                    cv2.destroyAllWindows()
                    sys.exit(0)
                elif k == ord('c'):
                    end_class = 1
                    break
                elif k == ord('s'):
                    break
                elif k == 32:
                    _pause = 1 - _pause
Esempio n. 4
0
    bkg_pkl_path = os.path.join(bkg_path, 'bkg_imgs.pkl')

if load_bkg and os.path.isfile(bkg_pkl_path):
    print('Loading background images from {}'.format(bkg_pkl_path))
    with open(bkg_pkl_path, 'rb') as f:
        bkg_imgs = pickle.load(f)
else:
    print('Reading background image sequence from {}'.format(bkg_path))
    bkg_imgs = []
    for i in range(n_bkgs):
        _bkg_fname = bkg_file_list[i]
        bkg_img_path = os.path.join(bkg_path, _bkg_fname)
        bkg_img = cv2.imread(bkg_img_path)
        orig_shape = bkg_img.shape
        if bkg_size:
            bkg_img, resize_factor, _, _ = resizeAR(bkg_img, bkg_width, bkg_height,
                                                    return_factors=True, add_border=False)
            print('bkg_img.shape: ', bkg_img.shape)
        bkg_imgs.append({
            'name': _bkg_fname,
            'path': bkg_img_path,
            'image': bkg_img,
            'resize_factor': resize_factor,
            'orig_shape': orig_shape}
        )
        sys.stdout.write('\rDone {:d} frames'.format(i + 1))
        sys.stdout.flush()
    print()
    print('Saving background images to {}'.format(bkg_pkl_path))
    with open(bkg_pkl_path, 'wb') as f:
        pickle.dump(bkg_imgs, f, pickle.HIGHEST_PROTOCOL)
Esempio n. 5
0
            # gt_file = os.path.join(pkl_files_path, seq_name, '{}_ground_truth.json'.format(file_id))
            # ground_truth_data = json.load(open(gt_file))
            # if gt_file not in loaded_json:
            #     loaded_json.add(gt_file)
            #     for obj in ground_truth_data:
            #         obj["used"] = False

            if show_animation and missing_detections:
                # print('\nfile_id: ', file_id)
                # print('missing_detections:\n ', missing_detections)
                for bb in missing_detections:
                    cv2.rectangle(img, (bb[0], bb[1]), (bb[2], bb[3]), magenta,
                                  2)

                img = resizeAR(img, save_w, save_h)
                img = cv2.copyMakeBorder(img,
                                         0,
                                         bottom_border,
                                         0,
                                         0,
                                         cv2.BORDER_CONSTANT,
                                         value=BLACK)
                height, _ = img.shape[:2]
                v_pos = int(height - margin - (bottom_border / 2))
                text = "{}: {} ".format(seq_name, ground_truth_img[0])
                img, line_width = utils.draw_text_in_image(
                    img, text, (margin, v_pos), white, 0)
                text = "Class [" + str(class_index + 1) + "/" + str(
                    n_classes) + "]: " + class_name + " "
                img, line_width = utils.draw_text_in_image(