示例#1
0
    def __init__(self,
                 path,
                 features="ResNET_PCA512.npy",
                 split="test",
                 framerate=2,
                 chunk_size=240,
                 receptive_field=80):
        self.path = path
        self.listGames = getListGames(split)
        self.features = features
        self.chunk_size = chunk_size
        self.receptive_field = receptive_field
        self.dict_event = EVENT_DICTIONARY_V2
        self.num_action_classes = 17
        self.labels_actions = "Labels-v2.json"
        self.labels_replays = "Labels-cameras.json"
        self.framerate = framerate

        #logging.info("Checking/Download features and labels locally")
        downloader = SoccerNetDownloader(path)
        downloader.downloadGames(files=[
            self.labels_actions, self.labels_replays, f"1_{self.features}",
            f"2_{self.features}"
        ],
                                 split=[split],
                                 verbose=False)
示例#2
0
    def __init__(self,
                 path,
                 features="ResNET_PCA512.npy",
                 split="test",
                 version=1,
                 framerate=2,
                 chunk_size=240,
                 receptive_field=80,
                 num_detections=45):
        self.path = path
        #self.listGames = getListGames(split)os.path.join(self.dataset_path + self.datatype)
        self.listGames = getListGames(split, task="camera-changes")
        # self.listGames = np.load(os.path.join(self.path, split))
        self.features = features
        self.chunk_size = chunk_size
        self.receptive_field = receptive_field
        self.framerate = framerate
        if version == 1:
            self.dict_event = EVENT_DICTIONARY_V1
            self.num_classes = 3
            self.labels = "Labels.json"
            self.K_parameters = K_V1 * framerate
            self.num_detections = 5
        elif version == 2:
            self.dict_change = Camera_Change_DICTIONARY
            self.dict_type = Camera_Type_DICTIONARY
            self.num_classes_sgementation = 13
            self.num_classes_camera_change = 1
            self.labels = "Labels-cameras.json"
            self.K_parameters = K_V2 * framerate
            self.num_detections = num_detections

        logging.info("Checking/Download features and labels locally")
        downloader = SoccerNetDownloader(path)
        downloader.downloadGames(
            files=[self.labels, f"1_{self.features}", f"2_{self.features}"],
            split=[split],
            verbose=False,
            task="camera-changes",
            randomized=True)
示例#3
0
    def __init__(self,
                 path,
                 features="ResNET_PCA512.npy",
                 split="test",
                 framerate=2,
                 chunk_size=240,
                 receptive_field=80):
        self.path = path
        self.listGames = getListGames(split)
        self.features = features
        self.chunk_size = chunk_size
        self.receptive_field = receptive_field
        self.framerate = framerate

        self.dict_event = EVENT_DICTIONARY_V2
        self.num_classes = 17
        self.labels = "Labels-v2.json"
        self.K_parameters = K_V2 * framerate
        self.num_detections = 15
        self.split = split

        logging.info("Checking/Download features and labels locally")
        downloader = SoccerNetDownloader(path)
        if split == "challenge":
            downloader.downloadGames(
                files=[f"1_{self.features}", f"2_{self.features}"],
                split=[split],
                verbose=False)
        else:
            downloader.downloadGames(files=[
                self.labels, f"1_{self.features}", f"2_{self.features}"
            ],
                                     split=[split],
                                     verbose=False)
    def __init__(self, rootFolder,
                 feature="ResNET",
                 video="LQ",
                 back_end="TF2",
                 overwrite=False,
                 transform="crop",
                 tmp_HQ_videos=None,
                 grabber="opencv",
                 FPS=2.0,
                 split="all"):
        self.rootFolder = rootFolder
        self.feature = feature
        self.video = video
        self.back_end = back_end
        self.verbose = True
        self.transform = transform
        self.overwrite = overwrite
        self.grabber = grabber
        self.FPS = FPS
        self.split = split

        self.tmp_HQ_videos = tmp_HQ_videos
        if self.tmp_HQ_videos:
            self.mySoccerNetDownloader = SoccerNetDownloader(self.rootFolder)
            self.mySoccerNetDownloader.password = self.tmp_HQ_videos

        if "TF2" in self.back_end:

            # create pretrained encoder (here ResNet152, pre-trained on ImageNet)
            base_model = keras.applications.resnet.ResNet152(include_top=True,
                                                             weights='imagenet',
                                                             input_tensor=None,
                                                             input_shape=None,
                                                             pooling=None,
                                                             classes=1000)

            # define model with output after polling layer (dim=2048)
            self.model = Model(base_model.input,
                               outputs=[base_model.get_layer("avg_pool").output])
            self.model.trainable = False
示例#5
0
    def __init__(self,
                 path,
                 features="ResNET_PCA512.npy",
                 split=["test"],
                 version=1,
                 framerate=2,
                 chunk_size=240):
        self.path = path
        self.listGames = getListGames(split)
        self.features = features
        self.chunk_size = chunk_size
        self.framerate = framerate
        self.version = version
        self.split = split
        if version == 1:
            self.dict_event = EVENT_DICTIONARY_V1
            self.num_classes = 3
            self.labels = "Labels.json"
        elif version == 2:
            self.dict_event = EVENT_DICTIONARY_V2
            self.num_classes = 17
            self.labels = "Labels-v2.json"

        logging.info("Checking/Download features and labels locally")
        downloader = SoccerNetDownloader(path)
        for s in split:
            if s == "challenge":
                downloader.downloadGames(
                    files=[f"1_{self.features}", f"2_{self.features}"],
                    split=[s],
                    verbose=False)
            else:
                downloader.downloadGames(files=[
                    self.labels, f"1_{self.features}", f"2_{self.features}"
                ],
                                         split=[s],
                                         verbose=False)
示例#6
0
    def __init__(self,
                 path,
                 features="ResNET_PCA512.npy",
                 split="train",
                 version=1,
                 framerate=2,
                 chunk_size=240,
                 receptive_field=80,
                 num_detections=45):
        self.path = path
        self.listGames = getListGames(split, task="camera-changes")
        #self.listGames = np.load(os.path.join(self.path, split))
        self.features = features
        self.chunk_size = chunk_size
        self.receptive_field = receptive_field
        self.framerate = framerate
        if version == 1:
            self.dict_event = EVENT_DICTIONARY_V1
            self.num_classes = 3
            self.labels = "Labels.json"
            self.K_parameters = K_V1 * framerate
            self.num_detections = 5
        elif version == 2:
            self.dict_change = Camera_Change_DICTIONARY
            self.dict_type = Camera_Type_DICTIONARY
            self.num_classes_sgementation = 13
            self.num_classes_camera_change = 1
            self.labels = "Labels-cameras.json"
            self.K_parameters = K_V2 * framerate
            self.num_detections = num_detections

        logging.info("Checking/Download features and labels locally")
        downloader = SoccerNetDownloader(path)
        downloader.downloadGames(
            files=[self.labels, f"1_{self.features}", f"2_{self.features}"],
            split=[split],
            verbose=False,
            task="camera-changes",
            randomized=True)

        logging.info("Pre-compute clips")

        clip_feats = []
        clip_labels = []

        self.game_feats = list()
        self.game_labels = list()
        self.game_change_labels = list()
        self.game_anchors = list()
        game_counter = 0
        for game in tqdm(self.listGames):
            # Load features
            #10% of dataset
            # if np.random.randint(10, size=1)<8:
            #      continue
            feat_half1 = np.load(
                os.path.join(self.path, game, "1_" + self.features))
            feat_half2 = np.load(
                os.path.join(self.path, game, "2_" + self.features))

            # Load labels
            #path2="/content/drive/My Drive/project/path/to/soccernet/data (1)/"
            labels = json.load(open(os.path.join(path, game, self.labels)))

            label_half1 = np.zeros(
                (feat_half1.shape[0], self.num_classes_sgementation))
            label_half2 = np.zeros(
                (feat_half2.shape[0], self.num_classes_sgementation))
            label_change_half1 = np.zeros(
                (feat_half1.shape[0], self.num_classes_camera_change))
            label_change_half2 = np.zeros(
                (feat_half2.shape[0], self.num_classes_camera_change))

            for annotation in labels["annotations"]:
                time = annotation["gameTime"]
                camera_type = annotation["label"]
                camera_change = annotation["change_type"]
                half = int(time[0])

                minutes = int(time[-5:-3])
                seconds = int(time[-2::])
                framerate = self.framerate
                frame = framerate * (seconds + 60 * minutes)

                if camera_type in self.dict_type:

                    label_type = self.dict_type[camera_type]

                    if half == 1:
                        frame = min(frame, feat_half1.shape[0] - 1)
                        label_half1[frame][label_type] = 1

                    if half == 2:
                        frame = min(frame, feat_half2.shape[0] - 1)
                        label_half2[frame][label_type] = 1

                #Onehot for camera changee
                if camera_change in self.dict_change:

                    label_change = self.dict_change[camera_change]

                    if half == 1:
                        frame = min(frame, feat_half1.shape[0] - 1)
                        label_change_half1[frame] = 1

                    if half == 2:
                        frame = min(frame, feat_half2.shape[0] - 1)
                        label_change_half2[frame] = 1
            shift_half1 = oneHotToAlllabels(label_half1)
            shift_half2 = oneHotToAlllabels(label_half2)

            #anchors_half1 = getChunks_anchors(shift_half1, game_counter, self.chunk_size, self.receptive_field)
            anchors_half1 = getChunks_anchors(label_change_half1, game_counter,
                                              self.chunk_size,
                                              self.receptive_field)
            game_counter = game_counter + 1
            # with np.printoptions(threshold=np.inf):
            #     print('anchors_half1',anchors_half1)
            #anchors_half2 = getChunks_anchors(shift_half2, game_counter, self.chunk_size, self.receptive_field)
            anchors_half2 = getChunks_anchors(label_change_half2, game_counter,
                                              self.chunk_size,
                                              self.receptive_field)

            game_counter = game_counter + 1

            self.game_feats.append(feat_half1)
            self.game_feats.append(feat_half2)
            self.game_labels.append(shift_half1)
            self.game_labels.append(shift_half2)
            # with np.printoptions(threshold=np.inf):
            #     print('game_labels',self.game_labels)
            self.game_change_labels.append(label_change_half1)
            self.game_change_labels.append(label_change_half2)
            # with np.printoptions(threshold=np.inf):
            #     print('game_change_labels',self.game_change_labels)
            for anchor in anchors_half1:
                self.game_anchors.append(anchor)
            for anchor in anchors_half2:
                self.game_anchors.append(anchor)
import SoccerNet
from SoccerNet.Downloader import SoccerNetDownloader

mySoccerNetDownloader = SoccerNetDownloader(
    LocalDirectory="/path/to/SoccerNet")

mySoccerNetDownloader.password = input("Password for videos?:\n")

mySoccerNetDownloader.downloadGames(
    files=["Labels-v2.json", "1_ResNET_TF2.npy", "2_ResNET_TF2.npy"],
    split=["train", "valid", "test", "challenge"])  # download Features
示例#8
0
    def __init__(self,
                 path,
                 features="ResNET_PCA512.npy",
                 split=["train"],
                 version=1,
                 framerate=2,
                 chunk_size=240):
        self.path = path
        self.listGames = getListGames(split)
        self.features = features
        self.chunk_size = chunk_size
        self.version = version
        if version == 1:
            self.num_classes = 3
            self.labels = "Labels.json"
        elif version == 2:
            self.dict_event = EVENT_DICTIONARY_V2
            self.num_classes = 17
            self.labels = "Labels-v2.json"

        logging.info("Checking/Download features and labels locally")
        downloader = SoccerNetDownloader(path)
        downloader.downloadGames(
            files=[self.labels, f"1_{self.features}", f"2_{self.features}"],
            split=split,
            verbose=False)

        logging.info("Pre-compute clips")

        self.game_feats = list()
        self.game_labels = list()

        # game_counter = 0
        for game in tqdm(self.listGames):
            # Load features
            feat_half1 = np.load(
                os.path.join(self.path, game, "1_" + self.features))
            feat_half1 = feat_half1.reshape(-1, feat_half1.shape[-1])
            feat_half2 = np.load(
                os.path.join(self.path, game, "2_" + self.features))
            feat_half2 = feat_half2.reshape(-1, feat_half2.shape[-1])
            # print("feat_half1.shape",feat_half1.shape)

            feat_half1 = feats2clip(torch.from_numpy(feat_half1),
                                    stride=self.chunk_size,
                                    clip_length=self.chunk_size)
            feat_half2 = feats2clip(torch.from_numpy(feat_half2),
                                    stride=self.chunk_size,
                                    clip_length=self.chunk_size)

            # print("feat_half1.shape",feat_half1.shape)
            # Load labels
            labels = json.load(open(os.path.join(self.path, game,
                                                 self.labels)))

            label_half1 = np.zeros((feat_half1.shape[0], self.num_classes + 1))
            label_half1[:, 0] = 1  # those are BG classes
            label_half2 = np.zeros((feat_half2.shape[0], self.num_classes + 1))
            label_half2[:, 0] = 1  # those are BG classes

            for annotation in labels["annotations"]:

                time = annotation["gameTime"]
                event = annotation["label"]

                half = int(time[0])

                minutes = int(time[-5:-3])
                seconds = int(time[-2::])
                frame = framerate * (seconds + 60 * minutes)

                if version == 1:
                    if "card" in event: label = 0
                    elif "subs" in event: label = 1
                    elif "soccer" in event: label = 2
                    else: continue
                elif version == 2:
                    if event not in self.dict_event:
                        continue
                    label = self.dict_event[event]

                # if label outside temporal of view
                if half == 1 and frame // self.chunk_size >= label_half1.shape[
                        0]:
                    continue
                if half == 2 and frame // self.chunk_size >= label_half2.shape[
                        0]:
                    continue

                if half == 1:
                    label_half1[frame //
                                self.chunk_size][0] = 0  # not BG anymore
                    label_half1[frame //
                                self.chunk_size][label +
                                                 1] = 1  # that's my class

                if half == 2:
                    label_half2[frame //
                                self.chunk_size][0] = 0  # not BG anymore
                    label_half2[frame //
                                self.chunk_size][label +
                                                 1] = 1  # that's my class

            self.game_feats.append(feat_half1)
            self.game_feats.append(feat_half2)
            self.game_labels.append(label_half1)
            self.game_labels.append(label_half2)

        self.game_feats = np.concatenate(self.game_feats)
        self.game_labels = np.concatenate(self.game_labels)
示例#9
0
    def __init__(self,
                 path,
                 features="ResNET_PCA512.npy",
                 split="train",
                 framerate=2,
                 chunk_size=240,
                 receptive_field=80,
                 chunks_per_epoch=6000):
        self.path = path
        self.listGames = getListGames(split)
        self.features = features
        self.chunk_size = chunk_size
        self.receptive_field = receptive_field
        self.chunks_per_epoch = chunks_per_epoch
        self.dict_event = EVENT_DICTIONARY_V2
        self.num_action_classes = 17
        self.labels_actions = "Labels-v2.json"
        self.labels_replays = "Labels-cameras.json"

        #logging.info("Checking/Download features and labels locally")
        downloader = SoccerNetDownloader(path)
        downloader.downloadGames(files=[
            self.labels_actions, self.labels_replays, f"1_{self.features}",
            f"2_{self.features}"
        ],
                                 split=[split],
                                 verbose=False)

        logging.info("Pre-compute clips")

        clip_feats = []
        clip_labels = []

        self.game_feats = list()
        self.replay_labels = list()
        self.replay_anchors = list()
        self.game_anchors = list()

        game_counter = 0
        for game in tqdm(self.listGames):
            # Load the features
            feat_half1 = np.load(
                os.path.join(self.path, game, "1_" + self.features))
            feat_half2 = np.load(
                os.path.join(self.path, game, "2_" + self.features))

            # load the replay labels
            labels_replays = json.load(
                open(os.path.join(self.path, game, self.labels_replays)))
            previous_timestamp = 0

            anchors_replay_half1 = list()
            anchors_replay_half2 = list()

            for annotation in labels_replays["annotations"]:

                time = annotation["gameTime"]

                half = int(time[0])

                minutes = int(time[-5:-3])
                seconds = int(time[-2::])
                frame = framerate * (seconds + 60 * minutes)

                if not "link" in annotation:
                    previous_timestamp = frame
                    continue

                event = annotation["link"]["label"]

                if not event in self.dict_event or int(
                        annotation["link"]["half"]) != half:
                    previous_timestamp = frame
                    continue

                if previous_timestamp == frame:
                    previous_timestamp = frame
                    continue

                time_event = annotation["link"]["time"]
                minutes_event = int(time_event[0:2])
                seconds_event = int(time_event[3:])
                frame_event = framerate * (seconds_event + 60 * minutes_event)

                label = self.dict_event[event]
                if half == 1:
                    anchors_replay_half1.append([
                        game_counter, previous_timestamp, frame, frame_event,
                        label
                    ])

                if half == 2:
                    anchors_replay_half2.append([
                        game_counter + 1, previous_timestamp, frame,
                        frame_event, label
                    ])

                previous_timestamp = frame

            # Load action labels
            labels_actions = json.load(
                open(os.path.join(self.path, game, self.labels_actions)))

            anchors_half1 = list()
            anchors_half2 = list()

            for annotation in labels_actions["annotations"]:

                time = annotation["gameTime"]
                event = annotation["label"]

                half = int(time[0])

                minutes = int(time[-5:-3])
                seconds = int(time[-2::])
                frame = framerate * (seconds + 60 * minutes)

                if event not in self.dict_event:
                    continue
                label = self.dict_event[event]

                if half == 1:
                    frame = min(frame, feat_half1.shape[0] - 1)
                    anchors_half1.append([game_counter, frame, label])

                if half == 2:
                    frame = min(frame, feat_half2.shape[0] - 1)
                    anchors_half2.append([game_counter + 1, frame, label])

            self.game_feats.append(feat_half1)
            self.game_feats.append(feat_half2)

            self.game_anchors.append(list())
            for i in np.arange(self.num_action_classes):
                self.game_anchors[-1].append(list())
            for anchor in anchors_half1:
                self.game_anchors[-1][anchor[2]].append(anchor)

            self.game_anchors.append(list())
            for i in np.arange(self.num_action_classes):
                self.game_anchors[-1].append(list())
            for anchor in anchors_half2:
                self.game_anchors[-1][anchor[2]].append(anchor)

            for anchor in anchors_replay_half1:
                self.replay_anchors.append(anchor)
            for anchor in anchors_replay_half2:
                self.replay_anchors.append(anchor)
            game_counter = game_counter + 2
示例#10
0
    def __init__(self,
                 path,
                 features="ResNET_PCA512.npy",
                 split="train",
                 framerate=2,
                 chunk_size=240,
                 receptive_field=80,
                 chunks_per_epoch=6000):
        self.path = path
        self.listGames = getListGames(split)
        self.features = features
        self.chunk_size = chunk_size
        self.receptive_field = receptive_field
        self.chunks_per_epoch = chunks_per_epoch

        self.dict_event = EVENT_DICTIONARY_V2
        self.num_classes = 17
        self.labels = "Labels-v2.json"
        self.K_parameters = K_V2 * framerate
        self.num_detections = 15
        self.split = split

        logging.info("Checking/Download features and labels locally")
        downloader = SoccerNetDownloader(path)
        downloader.downloadGames(
            files=[self.labels, f"1_{self.features}", f"2_{self.features}"],
            split=[split],
            verbose=False)

        logging.info("Pre-compute clips")

        clip_feats = []
        clip_labels = []

        self.game_feats = list()
        self.game_labels = list()
        self.game_anchors = list()
        for i in np.arange(self.num_classes + 1):
            self.game_anchors.append(list())

        game_counter = 0
        for game in tqdm(self.listGames):
            # Load features
            feat_half1 = np.load(
                os.path.join(self.path, game, "1_" + self.features))
            feat_half2 = np.load(
                os.path.join(self.path, game, "2_" + self.features))

            # Load labels
            labels = json.load(open(os.path.join(self.path, game,
                                                 self.labels)))

            label_half1 = np.zeros((feat_half1.shape[0], self.num_classes))
            label_half2 = np.zeros((feat_half2.shape[0], self.num_classes))

            for annotation in labels["annotations"]:

                time = annotation["gameTime"]
                event = annotation["label"]

                half = int(time[0])

                minutes = int(time[-5:-3])
                seconds = int(time[-2::])
                frame = framerate * (seconds + 60 * minutes)

                if event not in self.dict_event:
                    continue
                label = self.dict_event[event]

                if half == 1:
                    frame = min(frame, feat_half1.shape[0] - 1)
                    label_half1[frame][label] = 1

                if half == 2:
                    frame = min(frame, feat_half2.shape[0] - 1)
                    label_half2[frame][label] = 1

            shift_half1 = oneHotToShifts(label_half1,
                                         self.K_parameters.cpu().numpy())
            shift_half2 = oneHotToShifts(label_half2,
                                         self.K_parameters.cpu().numpy())

            anchors_half1 = getChunks_anchors(shift_half1, game_counter,
                                              self.K_parameters.cpu().numpy(),
                                              self.chunk_size,
                                              self.receptive_field)

            game_counter = game_counter + 1

            anchors_half2 = getChunks_anchors(shift_half2, game_counter,
                                              self.K_parameters.cpu().numpy(),
                                              self.chunk_size,
                                              self.receptive_field)

            game_counter = game_counter + 1

            self.game_feats.append(feat_half1)
            self.game_feats.append(feat_half2)
            self.game_labels.append(shift_half1)
            self.game_labels.append(shift_half2)
            for anchor in anchors_half1:
                self.game_anchors[anchor[2]].append(anchor)
            for anchor in anchors_half2:
                self.game_anchors[anchor[2]].append(anchor)
class FeatureExtractor():
    def __init__(self, rootFolder,
                 feature="ResNET",
                 video="LQ",
                 back_end="TF2",
                 overwrite=False,
                 transform="crop",
                 tmp_HQ_videos=None,
                 grabber="opencv",
                 FPS=2.0,
                 split="all"):
        self.rootFolder = rootFolder
        self.feature = feature
        self.video = video
        self.back_end = back_end
        self.verbose = True
        self.transform = transform
        self.overwrite = overwrite
        self.grabber = grabber
        self.FPS = FPS
        self.split = split

        self.tmp_HQ_videos = tmp_HQ_videos
        if self.tmp_HQ_videos:
            self.mySoccerNetDownloader = SoccerNetDownloader(self.rootFolder)
            self.mySoccerNetDownloader.password = self.tmp_HQ_videos

        if "TF2" in self.back_end:

            # create pretrained encoder (here ResNet152, pre-trained on ImageNet)
            base_model = keras.applications.resnet.ResNet152(include_top=True,
                                                             weights='imagenet',
                                                             input_tensor=None,
                                                             input_shape=None,
                                                             pooling=None,
                                                             classes=1000)

            # define model with output after polling layer (dim=2048)
            self.model = Model(base_model.input,
                               outputs=[base_model.get_layer("avg_pool").output])
            self.model.trainable = False

    def extractAllGames(self):
        list_game = getListGames(self.split)
        for i_game, game in enumerate(tqdm(list_game)):
            try:
                self.extractGameIndex(i_game)
            except:
                print(f"issue with game {i_game}, {game}")

    def extractGameIndex(self, index):
        print(getListGames(self.split)[index])
        if self.video =="LQ":
            for vid in ["1.mkv","2.mkv"]:
                self.extract(video_path=os.path.join(self.rootFolder, getListGames(self.split)[index], vid))

        elif self.video == "HQ":
            
            # read config for raw HD video
            config = configparser.ConfigParser()
            if not os.path.exists(os.path.join(self.rootFolder, getListGames(self.split)[index], "video.ini")) and self.tmp_HQ_videos is not None:
                self.mySoccerNetDownloader.downloadVideoHD(
                    game=getListGames(self.split)[index], file="video.ini")
            config.read(os.path.join(self.rootFolder, getListGames(self.split)[index], "video.ini"))

            # lopp over videos
            for vid in config.sections():
                video_path = os.path.join(self.rootFolder, getListGames(self.split)[index], vid)

                # cehck if already exists, then skip
                feature_path = video_path[:-4] + f"_{self.feature}_{self.back_end}.npy"
                if os.path.exists(feature_path) and not self.overwrite:
                    print("already exists, early skip")
                    continue

                #Download video if does not exist, but remove it afterwards
                remove_afterwards = False
                if not os.path.exists(video_path) and self.tmp_HQ_videos is not None:
                    remove_afterwards = True
                    self.mySoccerNetDownloader.downloadVideoHD(game=getListGames(self.split)[index], file=vid)

                # extract feature for video
                self.extract(video_path=video_path,
                            start=float(config[vid]["start_time_second"]), 
                            duration=float(config[vid]["duration_second"]))
                
                # remove video if not present before
                if remove_afterwards:
                    os.remove(video_path)

    def extract(self, video_path, start=None, duration=None):
        print("extract video", video_path, "from", start, duration)
        # feature_path = video_path.replace(
        #     ".mkv", f"_{self.feature}_{self.back_end}.npy")
        feature_path = video_path[:-4] + f"_{self.feature}_{self.back_end}.npy"

        if os.path.exists(feature_path) and not self.overwrite:
            return
        if "TF2" in self.back_end:
            
            if self.grabber=="skvideo":
                videoLoader = Frame(video_path, FPS=self.FPS, transform=self.transform, start=start, duration=duration)
            elif self.grabber=="opencv":
                videoLoader = FrameCV(video_path, FPS=self.FPS, transform=self.transform, start=start, duration=duration)

            # create numpy aray (nb_frames x 224 x 224 x 3)
            # frames = np.array(videoLoader.frames)
            # if self.preprocess:
            frames = preprocess_input(videoLoader.frames)
            
            if duration is None:
                duration = videoLoader.time_second
                # time_second = duration
            if self.verbose:
                print("frames", frames.shape, "fps=", frames.shape[0]/duration)

            # predict the featrues from the frames (adjust batch size for smalled GPU)
            features = self.model.predict(frames, batch_size=64, verbose=1)
            if self.verbose:
                print("features", features.shape, "fps=", features.shape[0]/duration)



        # save the featrue in .npy format
        os.makedirs(os.path.dirname(feature_path), exist_ok=True)
        np.save(feature_path, features)