file_manager.py 6.75 KB
Newer Older
anivegesana's avatar
anivegesana committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
"""
Manage the downloading of external files that are used in YOLO networks.
"""

# from __future__ import annotations

import io
import os

from typing import Union

# define PathABC type
try:
    PathABC = Union[bytes, str, os.PathLike]
except AttributeError:
    # not Python 3.6+
    import pathlib
    PathABC = Union[bytes, str, pathlib.Path]


def get_size(path: Union[PathABC, io.IOBase]) -> int:
    """
    A unified method to find the size of a file, either by its path or an open
    file object.

    Arguments:
        path: a path (as a str or a Path object) or an open file (which must be
              seekable)

    Return:
        size of the file

    Raises:
        ValueError: the IO object given as path is not open or it not seekable
        FileNotFoundError: the given path is invalid
    """
    if isinstance(path, io.IOBase):
        if path.seekable():
            currentPos = path.tell()
            path.seek(-1, io.SEEK_END)
            size = path.tell() + 1
            path.seek(currentPos)
            return size
        else:
            raise ValueError(
                "IO object must be seekable in order to find the size.")
    else:
        return os.path.getsize(path)


def open_if_not_open(file: Union[PathABC, io.IOBase], *args,
                     **kwargs) -> io.IOBase:
    """
    Takes an input that can either be a file or a path. If the input is given as
    a file, it is returned without modification. If it is a path, it is opened
    as a file.

    Arguments:
        file: a path or file that is being opened if it already isn't
        *args, **kwargs: to see the potential additional arguments or keywords
                         that can be based into this function, consult the open
                         builtin function.

    Returns:
        opened file

    Raises:
        IOError: consult the open builtin function for the potential IO errors
                 that can be raised when opening the file
    """
    if isinstance(file, io.IOBase):
        return file
    return open(file, *args, **kwargs)


# URL names that can be accessed using the download function
urls = {
    'yolov1.cfg':
    ('https://raw.githubusercontent.com/pjreddie/darknet/master/cfg/yolov1.cfg',
     'cfg',
     '8b4b951dd646478ea4214cb389d152793ca98e5c6e67266884908ba084b6211e'),
    'yolov2.cfg':
    ('https://raw.githubusercontent.com/AlexeyAB/darknet/master/cfg/yolov2.cfg',
     'cfg',
     '57d85d77262c840b56ad5418faae4950d9c7727e0192fb70618eeaac26a19817'),
    'yolov3.cfg':
    ('https://raw.githubusercontent.com/pjreddie/darknet/master/cfg/yolov3.cfg',
     'cfg',
     '22489ea38575dfa36c67a90048e8759576416a79d32dc11e15d2217777b9a953'),
    'yolov3-spp.cfg':
    ('https://raw.githubusercontent.com/pjreddie/darknet/master/cfg/yolov3-spp.cfg',
     'cfg',
     '7a4ec2d7427340fb12059f2b0ef76d6fcfcac132cc287cbbf0be5e3abaa856fd'),
    'yolov3-tiny.cfg':
    ('https://raw.githubusercontent.com/pjreddie/darknet/master/cfg/yolov3-tiny.cfg',
     'cfg',
     '84eb7a675ef87c906019ff5a6e0effe275d175adb75100dcb47f0727917dc2c7'),
    'yolov4.cfg':
    ('https://raw.githubusercontent.com/AlexeyAB/darknet/master/cfg/yolov4.cfg',
     'cfg',
     'a6d0f8e5c62cc8378384f75a8159b95fa2964d4162e33351b00ac82e0fc46a34'),
    'yolov4-tiny.cfg':
    ('https://raw.githubusercontent.com/AlexeyAB/darknet/master/cfg/yolov4-tiny.cfg',
     'cfg',
     '6cbf5ece15235f66112e0bedebb324f37199b31aee385b7e18f0bbfb536b258e'),
    'yolov1.weights':
    ('http://pjreddie.com/media/files/yolov1/yolov1.weights', 'weights',
     'df414df832ed10e3f2788df1e0e0ae573976573b97b5eec2c824ab9e5a8ae6d6'),
    'yolov2.weights':
    ('https://pjreddie.com/media/files/yolov2.weights', 'weights',
     'd9945162ed6f54ce1a901e3ec537bdba4d572ecae7873087bd730e5a7942df3f'),
    'yolov3.weights':
    ('https://pjreddie.com/media/files/yolov3.weights', 'weights',
     '523e4e69e1d015393a1b0a441cef1d9c7659e3eb2d7e15f793f060a21b32f297'),
    'yolov3-spp.weights':
    ('https://pjreddie.com/media/files/yolov3-spp.weights', 'weights',
     '87a1e8c85c763316f34e428f2295e1db9ed4abcec59dd9544f8052f50de327b4'),
    'yolov3-tiny.weights':
    ('https://pjreddie.com/media/files/yolov3-tiny.weights', 'weights',
     'dccea06f59b781ec1234ddf8d1e94b9519a97f4245748a7d4db75d5b7080a42c'),
    'yolov4.weights':
    ('https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.weights',
     'weights',
     'e8a4f6c62188738d86dc6898d82724ec0964d0eb9d2ae0f0a9d53d65d108d562'),
    'yolov4-tiny.weights':
    ('https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v4_pre/yolov4-tiny.weights',
     'weights',
     '037676f0d929c24e1bd9a0037fe30dc416fc26e0ca2a4491a44d024873316061'),
}


def download(name: str, trust: bool = False) -> str:
    """
    Download a predefined file named `name` from the original repository.

    For example, yolov3.weights is a file that defines the pretrained YOLOv3
    model. It can be downloaded from https://pjreddie.com/media/files/yolov3.weights
    so it is downloaded from there.

    Args:
        name: Name of the file that will be downloaded
        trust: Trust the cache even if the file's hash is inconsistent
               This option can speed the loading of the file at the expense of
               security. Default value is False.

    Returns:
        The path of the downloaded file as a `str`

    Raises:
        KeyError:       Name of file is not found in the `urls` variable.
        ValueError:     Name or URL stored in the `urls` variable is invalid.
        OSError:        There was a problem saving the file when it was being
                        downloaded.
        HTTPException:  The file was not able to be downloaded.
        Exception:      Any other undocumented error that ks.utils.get_file may
                        have thrown to indicate that the file was inaccessible.
    """
    import tensorflow.keras as ks
    from http.client import HTTPException

    url, type, hash = urls[name]

    cache_dir = os.path.abspath('cache')
    full_path = os.path.join(cache_dir, type, name)
    if trust and os.path.exists(full_path):
        return full_path

    try:
        if hash is None:
            return ks.utils.get_file(name,
                                     url,
                                     cache_dir=cache_dir,
                                     cache_subdir=type)
        else:
            return ks.utils.get_file(name,
                                     url,
                                     cache_dir=cache_dir,
                                     cache_subdir=type,
                                     file_hash=hash,
                                     hash_algorithm='sha256')
    except Exception as e:
        if 'URL fetch failure on' in str(e):
            raise HTTPException(str(e)) from e
        else:
            raise