def predict(self,
                feats: Features,
                batch_data_samples: OptSampleList,
                test_cfg: ConfigType = {}) -> Predictions:
        """Predict results from features.

        Args:
            feats (Tuple[Tensor] | List[Tuple[Tensor]]): The multi-stage
                features (or multiple multi-scale features in TTA)
            batch_data_samples (List[:obj:`PoseDataSample`]): The batch
                data samples
            test_cfg (dict): The runtime config for testing process. Defaults
                to {}

        Returns:
            Union[InstanceList | Tuple[InstanceList | PixelDataList]]: If
            ``test_cfg['output_heatmap']==True``, return both pose and heatmap
            prediction; otherwise only return the pose prediction.

            The pose prediction is a list of ``InstanceData``, each contains
            the following fields:

                - keypoints (np.ndarray): predicted keypoint coordinates in
                    shape (num_instances, K, D) where K is the keypoint number
                    and D is the keypoint dimension
                - keypoint_scores (np.ndarray): predicted keypoint scores in
                    shape (num_instances, K)
        """

        flip_test = test_cfg.get('flip_test', False)
        metainfo = batch_data_samples[0].metainfo

        if flip_test:
            assert isinstance(feats, list) and len(feats) == 2
            flip_indices = metainfo['flip_indices']
            _feat, _feat_flip = feats
            _heatmaps, _displacements = self.forward(_feat)
            _heatmaps_flip, _displacements_flip = self.forward(_feat_flip)

            batch_size = _heatmaps.shape[0]

            _heatmaps = to_numpy(_heatmaps)
            _displacements = to_numpy(_displacements)

            _heatmaps_flip = to_numpy(_heatmaps_flip)
            _displacements_flip = to_numpy(_displacements_flip)
            preds = []
            for b in range(batch_size):
                _keypoints, _keypoint_scores = self.decoder.decode(
                    _heatmaps[b], _displacements[b])

                _keypoints_flip, _keypoint_scores_flip = self.decoder.decode(
                    _heatmaps_flip[b], _displacements_flip[b])

                # flip the kps coords
                real_w = self.decoder.input_size[0]
                real_h = self.decoder.input_size[1]

                # the coordinate range is 0-255  for 256x256 input size
                _keypoints_flip /= (real_w - 1)
                _keypoints_flip = flip_coordinates(
                    _keypoints_flip,
                    flip_indices=flip_indices,
                    shift_coords=False,
                    input_size=((real_w - 1), (real_h - 1)))
                _keypoints_flip *= (real_w - 1)

                _keypoints = (_keypoints + _keypoints_flip) / 2.
                # pack outputs
                preds.append(InstanceData(keypoints=_keypoints))
            return preds

        else:
            batch_heatmaps, batch_displacements = self.forward(feats)

            preds = self.decode(batch_heatmaps, batch_displacements, test_cfg,
                                metainfo)

            return preds
Predict results from features.

        Args:
            feats (Tuple[Tensor] | List[Tuple[Tensor]]): The multi-stage
                features (or multiple multi-scale features in TTA)
            batch_data_samples (List[:obj:`PoseDataSample`]): The batch
                data samples
            test_cfg (dict): The runtime config for testing process. Defaults
                to {}

        Returns:
            Union[InstanceList | Tuple[InstanceList | PixelDataList]]: If
            ``test_cfg['output_heatmap']==True``, return both pose and heatmap
            prediction; otherwise only return the pose prediction.

            The pose prediction is a list of ``InstanceData``, each contains
            the following fields:

                - keypoints (np.ndarray): predicted keypoint coordinates in
                    shape (num_instances, K, D) where K is the keypoint number
                    and D is the keypoint dimension
                - keypoint_scores (np.ndarray): predicted keypoint scores in
                    shape (num_instances, K)
        
mmpose/projects/skps/models/skps_head.py