예제 #1
0
def __add_missing_boxes_to_mask2(mask1: np.ndarray, mask2: np.ndarray, distance_threshold=10):
    mask1 = mask1.copy()
    mask2 = mask2.copy()

    mask1_rps = get_region_props(mask1)
    mask2_rps = get_region_props(mask2)

    missing_boxes = []

    # if there are boxes in mask 1 but there is no box in mask 2
    # add all the boxes of mask 1 to mask 2
    if len(mask1_rps) > 0 and len(mask2_rps) == 0:
        missing_boxes.extend(mask1_rps)
    # if there are some boxes in mask 1 and mask 2
    # If these are not present in mask2 these will be copied to that
    elif len(mask1_rps) > 0 and len(mask2_rps) > 0:
        distance_matrix = get_distance_matrix(mask1_rps, mask2_rps)
        for i, dm in enumerate(distance_matrix):
            min_distance = np.min(dm)
            # if current box of mask 1 doesn't exist in mask 2
            # add this mask in mask 2
            if min_distance > distance_threshold:
                missing_boxes.append(mask1_rps[i])

    for missing_box in missing_boxes:
        foreground_number = int(np.max(mask1))

        y1, x1, y2, x2 = missing_box.bbox
        mask2[y1:y2, x1:x2] = foreground_number

    return mask2
def main_process(params):
    frame_number = params['frame_number']
    video_masks = params['video_masks']
    frame_paths = params['frame_paths']

    left_frame_number = frame_number - window_of_search
    right_frame_number = frame_number + window_of_search

    left_mask_path = video_masks[left_frame_number]
    right_mask_path = video_masks[right_frame_number]
    middle_mask_path = video_masks[frame_number]

    left_frame_index = get_index_of_frame(left_mask_path, frame_paths)
    right_frame_index = get_index_of_frame(right_mask_path, frame_paths)
    middle_frame_index = get_index_of_frame(middle_mask_path, frame_paths)

    if left_frame_index is None or right_frame_index is None or middle_frame_index is None:
        print(
            f'Left, middle or right frame was not found {os.path.basename(middle_mask_path)}\nContinuing by neglecting it.'
        )
        return ''

    # from left index to before middle index
    previous_frames = frame_paths[left_frame_index:middle_frame_index]
    previous_frames = previous_frames[-1::-1]

    # from next of middle index to right index
    next_frames = frame_paths[middle_frame_index + 1:right_frame_index + 1]

    middle_frame = cv2.imread(frame_paths[middle_frame_index])
    middle_mask = cv2.imread(middle_mask_path)
    middle_mask_rps = get_region_props(middle_mask)

    for middle_mask_rp in middle_mask_rps:
        y1, x1, y2, x2 = middle_mask_rp.bbox

        previous_frame_presence = track_in_frames(middle_frame,
                                                  (y1, x1, y2, x2),
                                                  previous_frames,
                                                  masks_folder)
        next_frame_presence = track_in_frames(middle_frame, (y1, x1, y2, x2),
                                              next_frames, masks_folder)

        # if box is present in either previous or next frame for number of times
        if previous_frame_presence >= should_present_in_frames or next_frame_presence >= should_present_in_frames:
            is_tp = True
        else:
            is_tp = False

        if not is_tp:
            y1, x1, y2, x2 = get_safe_extended_pixels(middle_mask.shape[0],
                                                      middle_mask.shape[1], 1,
                                                      y1, x1, y2, x2)
            middle_mask[y1:y2, x1:x2] = 0

    middle_mask_filename = os.path.basename(middle_mask_path)
    middle_mask_filename_wo_ext, _ = os.path.splitext(middle_mask_filename)
    mask_output_path = os.path.join(masks_output_folder,
                                    f'{middle_mask_filename_wo_ext}.png')
    cv2.imwrite(mask_output_path, middle_mask)
def merge_boxes_using_distance(mask1: np.ndarray, mask2: np.ndarray, distance_threshold=30,
                               log_file_path=None, filename=None) -> np.ndarray:
    mask1 = mask1.copy()
    mask2 = mask2.copy()

    if len(mask1.shape) == 3 and mask1.shape[2] == 3:
        mask1 = cv2.cvtColor(mask1, cv2.COLOR_BGR2GRAY)
    if len(mask2.shape) == 3 and mask2.shape[2] == 3:
        mask2 = cv2.cvtColor(mask2, cv2.COLOR_BGR2GRAY)

    mask1_region_props = get_region_props(mask1)
    mask2_region_props = get_region_props(mask2)

    new_mask = mask1.copy()

    if len(mask1_region_props) == 0:
        for mask2_region_prop in mask2_region_props:
            y1, x1, y2, x2 = mask2_region_prop.bbox
            new_mask[y1:y2, x1:x2] = 255

            if log_file_path is not None and filename is not None:
                write_log_file(log_file_path, filename, y1, x1, y2, x2)
    else:
        distance_matrix = np.zeros((len(mask2_region_props), len(mask1_region_props)), dtype=np.float)

        for mask2_region_prop_index, mask2_region_prop in enumerate(mask2_region_props):
            y2, x2 = mask2_region_prop.centroid

            for mask1_region_prop_index, mask1_region_prop in enumerate(mask1_region_props):
                y1, x1 = mask1_region_prop.centroid

                distance = calculate_distance(y1, x1, y2, x2)
                distance_matrix[mask2_region_prop_index, mask1_region_prop_index] = distance

        for mask2_region_prop_index, box_distances in enumerate(distance_matrix):
            # minimum distance between current box with the boxes mask 1
            min_distance = float(np.min(box_distances))

            if min_distance > distance_threshold:
                region_prop = mask2_region_props[mask2_region_prop_index]
                y1, x1, y2, x2 = region_prop.bbox
                new_mask[y1:y2, x1:x2] = 255

                if log_file_path is not None and filename is not None:
                    write_log_file(log_file_path, filename, y1, x1, y2, x2)
    return new_mask
예제 #4
0
def remove_boxes_less_than_threshold(masks_folder: str, threshold=50):
    mask_paths = glob(os.path.join(masks_folder, '*'))
    for mask_path in tqdm(mask_paths, desc="Removing small boxes"):
        mask = cv.imread(mask_path)
        rps = get_region_props(mask)
        new_mask = np.zeros(mask.shape[0:2], dtype=mask.dtype)
        for rp in rps:
            y1, x1, y2, x2 = rp.bbox
            if rp.bbox_area >= threshold:
                new_mask[y1:y2, x1:x2] = 255
        cv.imwrite(mask_path, new_mask)
def merge_boxes_using_iou(mask1: np.ndarray, mask2: np.ndarray, iou_threshold=0.1) -> np.ndarray:
    mask1 = mask1.copy()
    mask2 = mask2.copy()

    if len(mask1.shape) == 3 and mask1.shape[2] == 3:
        mask1 = cv2.cvtColor(mask1, cv2.COLOR_BGR2GRAY)
    if len(mask2.shape) == 3 and mask2.shape[2] == 3:
        mask2 = cv2.cvtColor(mask2, cv2.COLOR_BGR2GRAY)

    mask1_region_props = get_region_props(mask1)
    mask2_region_props = get_region_props(mask2)

    new_mask = mask1.copy()

    if len(mask1_region_props) == 0:
        for mask2_region_prop in mask2_region_props:
            y1, x1, y2, x2 = mask2_region_prop.bbox
            new_mask[y1:y2, x1:x2] = 255
    else:
        iou_matrix = np.zeros((len(mask2_region_props), len(mask1_region_props)), dtype=np.float)

        for mask2_region_prop_index, mask2_region_prop in enumerate(mask2_region_props):
            mask2_y1, mask2_x1, mask2_y2, mask2_x2 = mask2_region_prop.bbox

            for mask1_region_prop_index, mask1_region_prop in enumerate(mask1_region_props):
                mask1_y1, mask1_x1, mask1_y2, mask1_x2 = mask1_region_prop.bbox

                box1 = (mask1_x1, mask1_y1, mask1_x2, mask1_y2)
                box2 = (mask2_x1, mask2_y1, mask2_x2, mask2_y2)
                iou = bb_intersection_over_union(box1, box2)
                iou_matrix[mask2_region_prop_index, mask1_region_prop_index] = iou

        for mask2_region_prop_index, iou_values in enumerate(iou_matrix):
            # maximum iou between current box with the boxes of mask 1
            max_iou = float(np.max(iou_values))

            if max_iou < iou_threshold:
                region_prop = mask2_region_props[mask2_region_prop_index]
                y1, x1, y2, x2 = region_prop.bbox
                new_mask[y1:y2, x1:x2] = 255
    return new_mask
예제 #6
0
def region_prop_masks(masks_folder: str):
    mask_paths = glob(os.path.join(masks_folder, '*'))
    for mask_path in tqdm(mask_paths, desc="Region proping masks"):
        mask = cv.imread(mask_path)
        rps = get_region_props(mask)
        new_mask = np.zeros(mask.shape, dtype=mask.dtype)
        foreground_pixel = np.max(mask)
        for rp in rps:
            y1, x1, y2, x2 = rp.bbox
            new_mask[y1:y2, x1:x2] = foreground_pixel

        cv.imwrite(mask_path, new_mask)
예제 #7
0
def main():
    os.makedirs(output_folder, exist_ok=True)

    mask_paths = glob(os.path.join(masks_folder, '*'))
    for mask_path in tqdm(mask_paths):
        filename = os.path.basename(mask_path)

        mask = cv2.imread(mask_path)
        rps = get_region_props(mask)

        new_mask = np.zeros(mask.shape, mask.dtype)
        for rp in rps:
            if min_box_threshold <= rp.bbox_area < max_box_threshold:
                y1, x1, y2, x2 = rp.bbox
                new_mask[y1:y2, x1:x2] = 255

        output_path = os.path.join(output_folder, filename)
        cv2.imwrite(output_path, new_mask)
def is_box_present_in_mask(box, mask, distance_threshold):
    y1, x1, y2, x2 = box
    cx = x1 + (x2 - x1) / 2
    cy = y1 + (y2 - y1) / 2

    distances = []
    mask_rps = get_region_props(mask)
    for mask_rp in mask_rps:
        cy2, cx2 = mask_rp.centroid
        distance = calculate_distance(cy, cx, cy2, cx2)
        distances.append(distance)

    if len(distances) == 0:
        return False
    else:
        min_distance = min(distances)
        if min_distance <= distance_threshold:
            return True
        else:
            return False
예제 #9
0
def main():
    args = get_args()
    frames_folder = args.frames_folder
    labels_mask_folder = args.labels_mask_folder
    output_folder = args.output_folder
    save_boxes_as_json = args.save_boxes_as_json

    output_json_folder = output_folder + '_json'

    os.makedirs(output_folder, exist_ok=True)

    if save_boxes_as_json == 1:
        os.makedirs(output_json_folder, exist_ok=True)

    frame_paths = glob(path.join(frames_folder, '*.png'))
    frame_paths.sort()

    for frame_path in tqdm(frame_paths):
        filename = path.basename(frame_path)
        filename_wo_ext, _ = path.splitext(filename)

        labels_mask_path = path.join(labels_mask_folder, filename)

        frame = cv2.imread(frame_path)

        labels_mask = cv2.imread(labels_mask_path)
        labels_mask = cv2.cvtColor(labels_mask, cv2.COLOR_BGR2GRAY)

        crf_mask = np.zeros(labels_mask.shape, dtype=np.uint8)
        crf_boxes = []

        region_props = get_region_props(labels_mask)
        for region_prop in region_props:
            __labels_mask = np.zeros(labels_mask.shape, labels_mask.dtype)

            y1, x1, y2, x2 = region_prop.bbox

            __labels_mask[y1:y2, x1:x2] = 255

            y1, x1, y2, x2 = get_safe_extended_pixels(labels_mask.shape[0], labels_mask.shape[1], patch_extra_pixels,
                                                      y1, x1, y2, x2)

            crf_mask_patch = calculate_crf_on_labels(frame[y1:y2, x1:x2], __labels_mask[y1:y2, x1:x2])

            temp_mask = np.zeros(labels_mask.shape, dtype=np.uint8)
            temp_mask[y1:y2, x1:x2] = crf_mask_patch

            # extending foreground mask before saving
            temp_mask = expand_labels(temp_mask, 3)

            # to make sure only foreground pixels are copied and not the background one
            crf_mask[temp_mask > 0] = temp_mask[temp_mask > 0]

            # for saving as json file
            temp_rps = get_region_props(temp_mask)
            for temp_rp in temp_rps:
                temp_y1, temp_x1, temp_y2, temp_x2 = temp_rp.bbox
                crf_boxes.append([temp_y1, temp_x1, temp_y2, temp_x2])

        crf_mask = convert_segmented_area_to_bounding_box(crf_mask)

        output_file_path = path.join(output_folder, filename)
        cv2.imwrite(output_file_path, crf_mask)

        if save_boxes_as_json == 1:
            output_json_file = path.join(output_json_folder, f'{filename_wo_ext}.json')
            with open(output_json_file, 'w') as f:
                json.dump(crf_boxes, f)
def get_tracked_volumes(frames_list: List[np.ndarray],
                        masks_list: List[np.ndarray],
                        key_frame_number: int,
                        detection_masks_list: List[np.ndarray] = None):
    key_frame = frames_list[key_frame_number]

    # from frame 0 to less than key frame
    previous_frames = frames_list[0:key_frame_number]
    # reverse frames
    previous_frames = previous_frames[-1::-1]

    # from keyframe+1 to end
    next_frames = frames_list[key_frame_number + 1:]

    final_volumes = []
    # get boxes for key frames
    boxes = get_region_props(masks_list[key_frame_number])
    if detection_masks_list is not None:
        boxes.extend(get_region_props(detection_masks_list[key_frame_number]))
    for box in boxes:
        y1, x1, y2, x2 = box.bbox
        w = x2 - x1
        h = y2 - y1

        if w < 10:
            w = 10

        if h < 10:
            h = 10

        tracker = cv.TrackerCSRT_create()
        try:
            tracker.init(key_frame, (x1, y1, w, h))
        except:
            print('Box ignored because tracker could not initialize')
            continue

        key_frame_patch_location = get_safe_extended_pixels(
            key_frame.shape[0], key_frame.shape[1], extra_pixels, y1, x1, y2,
            x2)
        extended_height = key_frame_patch_location[
            2] - key_frame_patch_location[0]
        extended_width = key_frame_patch_location[
            3] - key_frame_patch_location[1]
        key_frame_patch = key_frame[
            key_frame_patch_location[0]:key_frame_patch_location[2],
            key_frame_patch_location[1]:key_frame_patch_location[3]]

        previous_patches = get_patches_by_tracker_extend_version(
            tracker, previous_frames, extended_height, extended_width)
        previous_patches = previous_patches[-1::-1]

        next_patches = get_patches_by_tracker_extend_version(
            tracker, next_frames, extended_height, extended_width)

        final_volume = []
        final_volume.extend(previous_patches)
        final_volume.append(key_frame_patch)
        final_volume.extend(next_patches)

        final_volumes.append({
            'location': key_frame_patch_location,
            'volume': final_volume
        })
    return final_volumes