예제 #1
0
    def test_preprocessing(self, data):
        """ Test preprocessing. """
        # Fetch corresponding entries
        image = data["image"]
        points = data["points"]
        line_map = data["line_map"]
        heatmap = data["heatmap"]
        image_size = image.shape[:2]

        # Resize the image before the photometric and homographic transforms
        if not (list(image.shape) == self.config["preprocessing"]["resize"]):
            # Resize the image and the point location.
            size_old = list(image.shape)
            image = cv2.resize(
                image,
                tuple(self.config['preprocessing']['resize'][::-1]),
                interpolation=cv2.INTER_LINEAR)
            image = np.array(image, dtype=np.uint8)

            points = (
                points *
                np.array(self.config['preprocessing']['resize'], np.float) /
                np.array(size_old, np.float))

            # Generate the line heatmap after post-processing
            junctions = np.flip(np.round(points).astype(np.int32), axis=1)
            heatmap = synthetic_util.get_line_heatmap(junctions,
                                                      line_map,
                                                      size=image.shape)
            heatmap = (heatmap * 255.).astype(np.uint8)

            # Update image size
            image_size = image.shape[:2]

        ### image transform ###
        image_transform = photoaug.normalize_image()
        image = image_transform(image)

        ### joint transform ###
        junction_map = self.junc_to_junc_map(points, image_size)
        to_tensor = transforms.ToTensor()
        image = to_tensor(image)
        junctions = to_tensor(points)
        junction_map = to_tensor(junction_map).to(torch.int)
        line_map = to_tensor(line_map)
        heatmap = to_tensor(heatmap)
        valid_mask = to_tensor(np.ones(image_size)).to(torch.int32)

        return {
            "image": image,
            "junctions": junctions,
            "junction_map": junction_map,
            "line_map": line_map,
            "heatmap": heatmap,
            "valid_mask": valid_mask
        }
예제 #2
0
    def __call__(self,
                 input_image,
                 junctions,
                 line_map,
                 valid_mask=None,
                 h**o=None,
                 scale=None):
        # Sample one random homography or use the given one
        if h**o is None or scale is None:
            h**o, scale = sample_homography(self.image_size,
                                            **self.homo_config)

        # Warp the image
        warped_image = cv2.warpPerspective(input_image,
                                           h**o,
                                           self.target_size,
                                           flags=cv2.INTER_LINEAR)

        valid_mask = compute_valid_mask(self.image_size, h**o,
                                        self.border_margin, valid_mask)

        # Convert junctions and line_map back to line segments
        line_segments = convert_to_line_segments(junctions, line_map)

        # Warp the segments and check the length.
        # Adjust the min_label_length
        warped_segments = warp_line_segment(line_segments, h**o,
                                            self.image_size)

        # Convert back to junctions and line_map
        junctions_new = np.concatenate(
            (warped_segments[:, :2], warped_segments[:, 2:]), axis=0)
        if junctions_new.shape[0] == 0:
            junctions_new = np.zeros([0, 2])
            line_map = np.zeros([0, 0])
            warped_heatmap = np.zeros(self.image_size)
        else:
            junctions_new = np.unique(junctions_new, axis=0)

            # Generate line map from points and segments
            line_map = get_line_map(junctions_new,
                                    warped_segments).astype(np.int)
            # Compute the heatmap
            warped_heatmap = get_line_heatmap(np.flip(junctions_new, axis=1),
                                              line_map, self.image_size)

        return {
            "junctions": junctions_new,
            "warped_image": warped_image,
            "valid_mask": valid_mask,
            "line_map": line_map,
            "warped_heatmap": warped_heatmap,
            "h**o": h**o,
            "scale": scale
        }
예제 #3
0
    def test_preprocessing_exported(self, data, numpy=False, scale=1.):
        """ Test preprocessing for the exported labels. """
        data = copy.deepcopy(data)
        # Fetch the corresponding entries
        image = data["image"]
        junctions = data["junctions"]
        line_map = data["line_map"]
        image_size = image.shape[:2]

        # Resize the image before photometric and homographical augmentations
        if not (list(image_size) == self.config["preprocessing"]["resize"]):
            # Resize the image and the point location.
            size_old = list(image.shape)[:2]  # Only H and W dimensions

            image = cv2.resize(
                image,
                tuple(self.config['preprocessing']['resize'][::-1]),
                interpolation=cv2.INTER_LINEAR)
            image = np.array(image, dtype=np.uint8)

            # In HW format
            junctions = (
                junctions *
                np.array(self.config['preprocessing']['resize'], np.float) /
                np.array(size_old, np.float))

        # Optionally convert the image to grayscale
        if self.config["gray_scale"]:
            image = (color.rgb2gray(image) * 255.).astype(np.uint8)

        # Still need to normalize image
        image_transform = photoaug.normalize_image()
        image = image_transform(image)

        # Generate the line heatmap after post-processing
        junctions_xy = np.flip(np.round(junctions).astype(np.int32), axis=1)
        image_size = image.shape[:2]
        heatmap = get_line_heatmap(junctions_xy, line_map, image_size)

        # Declare default valid mask (all ones)
        valid_mask = np.ones(image_size)

        junction_map = self.junc_to_junc_map(junctions, image_size)

        # Convert to tensor and return the results
        to_tensor = transforms.ToTensor()
        if not numpy:
            outputs = {
                "image": to_tensor(image),
                "junctions": to_tensor(junctions).to(torch.float32)[0, ...],
                "junction_map": to_tensor(junction_map).to(torch.int),
                "line_map": to_tensor(line_map).to(torch.int32)[0, ...],
                "heatmap": to_tensor(heatmap).to(torch.int32),
                "valid_mask": to_tensor(valid_mask).to(torch.int32)
            }
        else:
            outputs = {
                "image": image,
                "junctions": junctions.astype(np.float32),
                "junction_map": junction_map.astype(np.int32),
                "line_map": line_map.astype(np.int32),
                "heatmap": heatmap.astype(np.int32),
                "valid_mask": valid_mask.astype(np.int32)
            }

        return outputs
예제 #4
0
    def test_preprocessing(self, data, numpy=False):
        """ Test preprocessing for GT data. """
        data = copy.deepcopy(data)
        # Fetch the corresponding entries
        image = data["image"]
        junctions = data["junc"][:, :2]
        line_pos = data["Lpos"]
        line_neg = data["Lneg"]
        image_size = image.shape[:2]
        # Convert junctions to pixel coordinates (from 128x128)
        junctions[:, 0] *= image_size[0] / 128
        junctions[:, 1] *= image_size[1] / 128

        # Resize the image before photometric and homographical augmentations
        if not (list(image_size) == self.config["preprocessing"]["resize"]):
            # Resize the image and the point location.
            size_old = list(image.shape)[:2]  # Only H and W dimensions

            image = cv2.resize(
                image,
                tuple(self.config['preprocessing']['resize'][::-1]),
                interpolation=cv2.INTER_LINEAR)
            image = np.array(image, dtype=np.uint8)

            # In HW format
            junctions = (
                junctions *
                np.array(self.config['preprocessing']['resize'], np.float) /
                np.array(size_old, np.float))

        # Optionally convert the image to grayscale
        if self.config["gray_scale"]:
            image = (color.rgb2gray(image) * 255.).astype(np.uint8)

        # Still need to normalize image
        image_transform = photoaug.normalize_image()
        image = image_transform(image)

        # Convert to positive line map and negative line map (our format)
        num_junctions = junctions.shape[0]
        line_map_pos = self.convert_line_map(line_pos, num_junctions)
        line_map_neg = self.convert_line_map(line_neg, num_junctions)

        # Generate the line heatmap after post-processing
        junctions_xy = np.flip(np.round(junctions).astype(np.int32), axis=1)
        # Update image size
        image_size = image.shape[:2]
        heatmap_pos = get_line_heatmap(junctions_xy, line_map_pos, image_size)
        heatmap_neg = get_line_heatmap(junctions_xy, line_map_neg, image_size)
        # Declare default valid mask (all ones)
        valid_mask = np.ones(image_size)

        junction_map = self.junc_to_junc_map(junctions, image_size)

        # Convert to tensor and return the results
        to_tensor = transforms.ToTensor()
        if not numpy:
            return {
                "image": to_tensor(image),
                "junctions": to_tensor(junctions).to(torch.float32)[0, ...],
                "junction_map": to_tensor(junction_map).to(torch.int),
                "line_map_pos": to_tensor(line_map_pos).to(torch.int32)[0,
                                                                        ...],
                "line_map_neg": to_tensor(line_map_neg).to(torch.int32)[0,
                                                                        ...],
                "heatmap_pos": to_tensor(heatmap_pos).to(torch.int32),
                "heatmap_neg": to_tensor(heatmap_neg).to(torch.int32),
                "valid_mask": to_tensor(valid_mask).to(torch.int32)
            }
        else:
            return {
                "image": image,
                "junctions": junctions.astype(np.float32),
                "junction_map": junction_map.astype(np.int32),
                "line_map_pos": line_map_pos.astype(np.int32),
                "line_map_neg": line_map_neg.astype(np.int32),
                "heatmap_pos": heatmap_pos.astype(np.int32),
                "heatmap_neg": heatmap_neg.astype(np.int32),
                "valid_mask": valid_mask.astype(np.int32)
            }
예제 #5
0
    def train_preprocessing_exported(self,
                                     data,
                                     numpy=False,
                                     disable_homoaug=False,
                                     desc_training=False,
                                     H1=None,
                                     H1_scale=None,
                                     H2=None,
                                     scale=1.,
                                     h_crop=None,
                                     w_crop=None):
        """ Train preprocessing for the exported labels. """
        data = copy.deepcopy(data)
        # Fetch the corresponding entries
        image = data["image"]
        junctions = data["junctions"]
        line_map = data["line_map"]
        image_size = image.shape[:2]

        # Define the random crop for scaling if necessary
        if h_crop is None or w_crop is None:
            h_crop, w_crop = 0, 0
            if scale > 1:
                H, W = self.config["preprocessing"]["resize"]
                H_scale, W_scale = round(H * scale), round(W * scale)
                if H_scale > H:
                    h_crop = np.random.randint(H_scale - H)
                if W_scale > W:
                    w_crop = np.random.randint(W_scale - W)

        # Resize the image before photometric and homographical augmentations
        if not (list(image_size) == self.config["preprocessing"]["resize"]):
            # Resize the image and the point location.
            size_old = list(image.shape)[:2]  # Only H and W dimensions

            image = cv2.resize(
                image,
                tuple(self.config['preprocessing']['resize'][::-1]),
                interpolation=cv2.INTER_LINEAR)
            image = np.array(image, dtype=np.uint8)

            # In HW format
            junctions = (
                junctions *
                np.array(self.config['preprocessing']['resize'], np.float) /
                np.array(size_old, np.float))

        # Generate the line heatmap after post-processing
        junctions_xy = np.flip(np.round(junctions).astype(np.int32), axis=1)
        image_size = image.shape[:2]
        heatmap = get_line_heatmap(junctions_xy, line_map, image_size)

        # Optionally convert the image to grayscale
        if self.config["gray_scale"]:
            image = (color.rgb2gray(image) * 255.).astype(np.uint8)

        # Check if we need to apply augmentations
        # In training mode => yes.
        # In homography adaptation mode (export mode) => No
        if self.config["augmentation"]["photometric"]["enable"]:
            photo_trans_lst = self.get_photo_transform()
            ### Image transform ###
            np.random.shuffle(photo_trans_lst)
            image_transform = transforms.Compose(photo_trans_lst +
                                                 [photoaug.normalize_image()])
        else:
            image_transform = photoaug.normalize_image()
        image = image_transform(image)

        # Perform the random scaling
        if scale != 1.:
            image, junctions, line_map, valid_mask = random_scaling(
                image,
                junctions,
                line_map,
                scale,
                h_crop=h_crop,
                w_crop=w_crop)
        else:
            # Declare default valid mask (all ones)
            valid_mask = np.ones(image_size)

        # Initialize the empty output dict
        outputs = {}
        # Convert to tensor and return the results
        to_tensor = transforms.ToTensor()

        # Check homographic augmentation
        warp = (self.config["augmentation"]["homographic"]["enable"]
                and disable_homoaug == False)
        if warp:
            homo_trans = self.get_homo_transform()
            # Perform homographic transform
            if H1 is None:
                homo_outputs = homo_trans(image,
                                          junctions,
                                          line_map,
                                          valid_mask=valid_mask)
            else:
                homo_outputs = homo_trans(image,
                                          junctions,
                                          line_map,
                                          h**o=H1,
                                          scale=H1_scale,
                                          valid_mask=valid_mask)
            homography_mat = homo_outputs["h**o"]

            # Give the warp of the other view
            if H1 is None:
                H1 = homo_outputs["h**o"]

        # Sample points along each line segments for the descriptor
        if desc_training:
            line_points, line_indices = self.get_line_points(
                junctions,
                line_map,
                H1=H1,
                H2=H2,
                img_size=image_size,
                warp=warp)

        # Record the warped results
        if warp:
            junctions = homo_outputs["junctions"]  # Should be HW format
            image = homo_outputs["warped_image"]
            line_map = homo_outputs["line_map"]
            valid_mask = homo_outputs["valid_mask"]  # Same for pos and neg
            heatmap = homo_outputs["warped_heatmap"]

            # Optionally put warping information first.
            if not numpy:
                outputs["homography_mat"] = to_tensor(homography_mat).to(
                    torch.float32)[0, ...]
            else:
                outputs["homography_mat"] = homography_mat.astype(np.float32)

        junction_map = self.junc_to_junc_map(junctions, image_size)

        if not numpy:
            outputs.update({
                "image":
                to_tensor(image).to(torch.float32),
                "junctions":
                to_tensor(junctions).to(torch.float32)[0, ...],
                "junction_map":
                to_tensor(junction_map).to(torch.int),
                "line_map":
                to_tensor(line_map).to(torch.int32)[0, ...],
                "heatmap":
                to_tensor(heatmap).to(torch.int32),
                "valid_mask":
                to_tensor(valid_mask).to(torch.int32)
            })
            if desc_training:
                outputs.update({
                    "line_points":
                    to_tensor(line_points).to(torch.float32)[0],
                    "line_indices":
                    torch.tensor(line_indices, dtype=torch.int)
                })
        else:
            outputs.update({
                "image": image,
                "junctions": junctions.astype(np.float32),
                "junction_map": junction_map.astype(np.int32),
                "line_map": line_map.astype(np.int32),
                "heatmap": heatmap.astype(np.int32),
                "valid_mask": valid_mask.astype(np.int32)
            })
            if desc_training:
                outputs.update({
                    "line_points": line_points.astype(np.float32),
                    "line_indices": line_indices.astype(int)
                })

        return outputs
예제 #6
0
    def train_preprocessing(self, data, numpy=False):
        """ Train preprocessing for GT data. """
        # Fetch the corresponding entries
        image = data["image"]
        junctions = data["junc"][:, :2]
        line_pos = data["Lpos"]
        line_neg = data["Lneg"]
        image_size = image.shape[:2]
        # Convert junctions to pixel coordinates (from 128x128)
        junctions[:, 0] *= image_size[0] / 128
        junctions[:, 1] *= image_size[1] / 128

        # Resize the image before photometric and homographical augmentations
        if not (list(image_size) == self.config["preprocessing"]["resize"]):
            # Resize the image and the point location.
            size_old = list(image.shape)[:2]  # Only H and W dimensions

            image = cv2.resize(
                image,
                tuple(self.config['preprocessing']['resize'][::-1]),
                interpolation=cv2.INTER_LINEAR)
            image = np.array(image, dtype=np.uint8)

            # In HW format
            junctions = (
                junctions *
                np.array(self.config['preprocessing']['resize'], np.float) /
                np.array(size_old, np.float))

        # Convert to positive line map and negative line map (our format)
        num_junctions = junctions.shape[0]
        line_map_pos = self.convert_line_map(line_pos, num_junctions)
        line_map_neg = self.convert_line_map(line_neg, num_junctions)

        # Generate the line heatmap after post-processing
        junctions_xy = np.flip(np.round(junctions).astype(np.int32), axis=1)
        # Update image size
        image_size = image.shape[:2]
        heatmap_pos = get_line_heatmap(junctions_xy, line_map_pos, image_size)
        heatmap_neg = get_line_heatmap(junctions_xy, line_map_neg, image_size)
        # Declare default valid mask (all ones)
        valid_mask = np.ones(image_size)

        # Optionally convert the image to grayscale
        if self.config["gray_scale"]:
            image = (color.rgb2gray(image) * 255.).astype(np.uint8)

        # Check if we need to apply augmentations
        # In training mode => yes.
        # In homography adaptation mode (export mode) => No
        if self.config["augmentation"]["photometric"]["enable"]:
            photo_trans_lst = self.get_photo_transform()
            ### Image transform ###
            np.random.shuffle(photo_trans_lst)
            image_transform = transforms.Compose(photo_trans_lst +
                                                 [photoaug.normalize_image()])
        else:
            image_transform = photoaug.normalize_image()
        image = image_transform(image)

        # Check homographic augmentation
        if self.config["augmentation"]["homographic"]["enable"]:
            homo_trans = self.get_homo_transform()
            # Perform homographic transform
            outputs_pos = homo_trans(image, junctions, line_map_pos)
            outputs_neg = homo_trans(image, junctions, line_map_neg)

            # record the warped results
            junctions = outputs_pos["junctions"]  # Should be HW format
            image = outputs_pos["warped_image"]
            line_map_pos = outputs_pos["line_map"]
            line_map_neg = outputs_neg["line_map"]
            heatmap_pos = outputs_pos["warped_heatmap"]
            heatmap_neg = outputs_neg["warped_heatmap"]
            valid_mask = outputs_pos["valid_mask"]  # Same for pos and neg

        junction_map = self.junc_to_junc_map(junctions, image_size)

        # Convert to tensor and return the results
        to_tensor = transforms.ToTensor()
        if not numpy:
            return {
                "image": to_tensor(image),
                "junctions": to_tensor(junctions).to(torch.float32)[0, ...],
                "junction_map": to_tensor(junction_map).to(torch.int),
                "line_map_pos": to_tensor(line_map_pos).to(torch.int32)[0,
                                                                        ...],
                "line_map_neg": to_tensor(line_map_neg).to(torch.int32)[0,
                                                                        ...],
                "heatmap_pos": to_tensor(heatmap_pos).to(torch.int32),
                "heatmap_neg": to_tensor(heatmap_neg).to(torch.int32),
                "valid_mask": to_tensor(valid_mask).to(torch.int32)
            }
        else:
            return {
                "image": image,
                "junctions": junctions.astype(np.float32),
                "junction_map": junction_map.astype(np.int32),
                "line_map_pos": line_map_pos.astype(np.int32),
                "line_map_neg": line_map_neg.astype(np.int32),
                "heatmap_pos": heatmap_pos.astype(np.int32),
                "heatmap_neg": heatmap_neg.astype(np.int32),
                "valid_mask": valid_mask.astype(np.int32)
            }
예제 #7
0
    def train_preprocessing(self, data, disable_homoaug=False):
        """ Training preprocessing. """
        # Fetch corresponding entries
        image = data["image"]
        junctions = data["points"]
        line_map = data["line_map"]
        heatmap = data["heatmap"]
        image_size = image.shape[:2]

        # Resize the image before the photometric and homographic transforms
        # Check if we need to do the resizing
        if not (list(image.shape) == self.config["preprocessing"]["resize"]):
            # Resize the image and the point location.
            size_old = list(image.shape)
            image = cv2.resize(
                image,
                tuple(self.config['preprocessing']['resize'][::-1]),
                interpolation=cv2.INTER_LINEAR)
            image = np.array(image, dtype=np.uint8)

            junctions = (
                junctions *
                np.array(self.config['preprocessing']['resize'], np.float) /
                np.array(size_old, np.float))

            # Generate the line heatmap after post-processing
            junctions_xy = np.flip(np.round(junctions).astype(np.int32),
                                   axis=1)
            heatmap = synthetic_util.get_line_heatmap(junctions_xy,
                                                      line_map,
                                                      size=image.shape)
            heatmap = (heatmap * 255.).astype(np.uint8)

            # Update image size
            image_size = image.shape[:2]

        # Declare default valid mask (all ones)
        valid_mask = np.ones(image_size)

        # Check if we need to apply augmentations
        # In training mode => yes.
        # In homography adaptation mode (export mode) => No
        # Check photometric augmentation
        if self.config["augmentation"]["photometric"]["enable"]:
            photo_trans_lst = self.get_photo_transform()
            ### Image transform ###
            np.random.shuffle(photo_trans_lst)
            image_transform = transforms.Compose(photo_trans_lst +
                                                 [photoaug.normalize_image()])
        else:
            image_transform = photoaug.normalize_image()
        image = image_transform(image)

        # Initialize the empty output dict
        outputs = {}
        # Convert to tensor and return the results
        to_tensor = transforms.ToTensor()
        # Check homographic augmentation
        if (self.config["augmentation"]["homographic"]["enable"]
                and disable_homoaug == False):
            homo_trans = self.get_homo_transform()
            # Perform homographic transform
            homo_outputs = homo_trans(image, junctions, line_map)

            # Record the warped results
            junctions = homo_outputs["junctions"]  # Should be HW format
            image = homo_outputs["warped_image"]
            line_map = homo_outputs["line_map"]
            heatmap = homo_outputs["warped_heatmap"]
            valid_mask = homo_outputs["valid_mask"]  # Same for pos and neg
            homography_mat = homo_outputs["h**o"]

            # Optionally put warpping information first.
            outputs["homography_mat"] = to_tensor(homography_mat).to(
                torch.float32)[0, ...]

        junction_map = self.junc_to_junc_map(junctions, image_size)

        outputs.update({
            "image":
            to_tensor(image),
            "junctions":
            to_tensor(np.ascontiguousarray(junctions).copy()).to(
                torch.float32)[0, ...],
            "junction_map":
            to_tensor(junction_map).to(torch.int),
            "line_map":
            to_tensor(line_map).to(torch.int32)[0, ...],
            "heatmap":
            to_tensor(heatmap).to(torch.int32),
            "valid_mask":
            to_tensor(valid_mask).to(torch.int32),
        })

        return outputs
예제 #8
0
    def export_single_primitive(self, primitive, split_size, group):
        """ Export single primitive. """
        # Check if the primitive is valid or not
        if primitive not in self.available_primitives:
            raise ValueError("[Error]: %s is not a supported primitive" %
                             primitive)
        # Set the random seed
        synthetic_util.set_random_state(
            np.random.RandomState(self.config["generation"]["random_seed"]))

        # Generate shapes
        print("\t Generating %s ..." % primitive)
        for idx in tqdm(range(split_size), ascii=True):
            # Generate background image
            image = synthetic_util.generate_background(
                self.config['generation']['image_size'],
                **self.config['generation']['params']['generate_background'])

            # Generate points
            drawing_func = getattr(synthetic_util, primitive)
            kwarg = self.config["generation"]["params"].get(primitive, {})

            # Get min_len and min_label_len
            min_len = self.config["generation"]["min_len"]
            min_label_len = self.config["generation"]["min_label_len"]

            # Some only take min_label_len, and gaussian noises take nothing
            if primitive in [
                    "draw_lines", "draw_polygon", "draw_multiple_polygons",
                    "draw_star"
            ]:
                data = drawing_func(image,
                                    min_len=min_len,
                                    min_label_len=min_label_len,
                                    **kwarg)
            elif primitive in [
                    "draw_checkerboard_multiseg", "draw_stripes_multiseg",
                    "draw_cube"
            ]:
                data = drawing_func(image,
                                    min_label_len=min_label_len,
                                    **kwarg)
            else:
                data = drawing_func(image, **kwarg)

            # Convert the data
            if data["points"] is not None:
                points = np.flip(data["points"], axis=1).astype(np.float)
                line_map = data["line_map"].astype(np.int32)
            else:
                points = np.zeros([0, 2]).astype(np.float)
                line_map = np.zeros([0, 0]).astype(np.int32)

            # Post-processing
            blur_size = self.config["preprocessing"]["blur_size"]
            image = cv2.GaussianBlur(image, (blur_size, blur_size), 0)

            # Resize the image and the point location.
            points = (
                points *
                np.array(self.config['preprocessing']['resize'], np.float) /
                np.array(self.config['generation']['image_size'], np.float))
            image = cv2.resize(
                image,
                tuple(self.config['preprocessing']['resize'][::-1]),
                interpolation=cv2.INTER_LINEAR)
            image = np.array(image, dtype=np.uint8)

            # Generate the line heatmap after post-processing
            junctions = np.flip(np.round(points).astype(np.int32), axis=1)
            heatmap = (synthetic_util.get_line_heatmap(
                junctions, line_map, size=image.shape) * 255.).astype(np.uint8)

            # Record the data in group
            num_pad = math.ceil(math.log10(split_size)) + 1
            file_key_name = self.get_padded_filename(num_pad, idx)
            file_group = group.create_group(file_key_name)

            # Store data
            file_group.create_dataset("points",
                                      data=points,
                                      compression="gzip")
            file_group.create_dataset("image", data=image, compression="gzip")
            file_group.create_dataset("line_map",
                                      data=line_map,
                                      compression="gzip")
            file_group.create_dataset("heatmap",
                                      data=heatmap,
                                      compression="gzip")