thookham commited on
Commit
e9f9fd3
·
0 Parent(s):

Initial commit for Hugging Face sync (Clean History)

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
.gitattributes ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.ipynb filter=lfs diff=lfs merge=lfs -text
2
+ *.JPG filter=lfs diff=lfs merge=lfs -text
3
+ *.JPEG filter=lfs diff=lfs merge=lfs -text
4
+ *.pth filter=lfs diff=lfs merge=lfs -text
5
+ *.onnx filter=lfs diff=lfs merge=lfs -text
6
+ *.jpg filter=lfs diff=lfs merge=lfs -text
7
+ *.jpeg filter=lfs diff=lfs merge=lfs -text
8
+ *.png filter=lfs diff=lfs merge=lfs -text
9
+ *.PNG filter=lfs diff=lfs merge=lfs -text
10
+ /ColorizeVisualization.ipynb filter=lfs diff=lfs merge=lfs -text
11
+ *.pt filter=lfs diff=lfs merge=lfs -text
.github/CODEOWNERS ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ # See: https://help.github.com/en/articles/about-code-owners
2
+ #
3
+ # Owners will be requested for review when someone opens a pull request.
4
+ * @jantic @alexandrevicenzi
.github/ISSUE_TEMPLATE/bug_report.md ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Describe the bug**
11
+ A clear and concise description of what the bug is.
12
+
13
+ **To Reproduce**
14
+ Steps to reproduce the behavior:
15
+ 1. Go to '...'
16
+ 2. Click on '...'
17
+ 3. Scroll down to '...'
18
+ 4. See error
19
+
20
+ **Expected behavior**
21
+ A clear and concise description of what you expected to happen.
22
+
23
+ **Screenshots**
24
+ If applicable, add screenshots to help explain your problem.
25
+
26
+ **Desktop (please complete the following information):**
27
+ - OS: [e.g. iOS]
28
+ - Browser [e.g. chrome, safari]
29
+ - Version [e.g. 22]
30
+
31
+ **Smartphone (please complete the following information):**
32
+ - Device: [e.g. iPhone6]
33
+ - OS: [e.g. iOS8.1]
34
+ - Browser [e.g. stock browser, safari]
35
+ - Version [e.g. 22]
36
+
37
+ **Additional context**
38
+ Add any other context about the problem here.
.github/ISSUE_TEMPLATE/feature_request.md ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Is your feature request related to a problem? Please describe.**
11
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12
+
13
+ **Describe the solution you'd like**
14
+ A clear and concise description of what you want to happen.
15
+
16
+ **Describe alternatives you've considered**
17
+ A clear and concise description of any alternative solutions or features you've considered.
18
+
19
+ **Additional context**
20
+ Add any other context or screenshots about the feature request here.
.github/PULL_REQUEST_TEMPLATE.md ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Description
2
+
3
+ Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.
4
+
5
+ Fixes # (issue)
6
+
7
+ ## Type of change
8
+
9
+ Please delete options that are not relevant.
10
+
11
+ - [ ] Bug fix (non-breaking change which fixes an issue)
12
+ - [ ] New feature (non-breaking change which adds functionality)
13
+ - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
14
+ - [ ] This change requires a documentation update
15
+
16
+ ## How Has This Been Tested?
17
+
18
+ Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration
19
+
20
+ - [ ] Test A
21
+ - [ ] Test B
22
+
23
+ **Test Configuration**:
24
+ * Firmware version:
25
+ * Hardware:
26
+ * Toolchain:
27
+ * SDK:
28
+
29
+ ## Checklist:
30
+
31
+ - [ ] My code follows the style guidelines of this project
32
+ - [ ] I have performed a self-review of my own code
33
+ - [ ] I have commented my code, particularly in hard-to-understand areas
34
+ - [ ] I have made corresponding changes to the documentation
35
+ - [ ] My changes generate no new warnings
36
+ - [ ] I have added tests that prove my fix is effective or that my feature works
37
+ - [ ] New and existing unit tests pass locally with my changes
38
+ - [ ] Any dependent changes have been merged and published in downstream modules
.gitignore ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ *.egg-info/
24
+ .installed.cfg
25
+ *.egg
26
+ MANIFEST
27
+
28
+ # PyInstaller
29
+ # Usually these files are written by a python script from a template
30
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
31
+ *.manifest
32
+ *.spec
33
+
34
+ # Installer logs
35
+ pip-log.txt
36
+ pip-delete-this-directory.txt
37
+
38
+ # Unit test / coverage reports
39
+ htmlcov/
40
+ .tox/
41
+ .coverage
42
+ .coverage.*
43
+ .cache
44
+ nosetests.xml
45
+ coverage.xml
46
+ *.cover
47
+ .hypothesis/
48
+ .pytest_cache/
49
+
50
+ # Translations
51
+ *.mo
52
+ *.pot
53
+
54
+ # Django stuff:
55
+ *.log
56
+ local_settings.py
57
+ db.sqlite3
58
+
59
+ # Flask stuff:
60
+ instance/
61
+ .webassets-cache
62
+
63
+ # Scrapy stuff:
64
+ .scrapy
65
+
66
+ # Sphinx documentation
67
+ docs/_build/
68
+
69
+ # PyBuilder
70
+ target/
71
+
72
+ # Jupyter Notebook
73
+ .ipynb_checkpoints
74
+
75
+ # pyenv
76
+ .python-version
77
+
78
+ # celery beat schedule file
79
+ celerybeat-schedule
80
+
81
+ # SageMath parsed files
82
+ *.sage.py
83
+
84
+ # Environments
85
+ .env
86
+ .venv
87
+ env/
88
+ venv/
89
+ ENV/
90
+ env.bak/
91
+ venv.bak/
92
+
93
+ # Spyder project settings
94
+ .spyderproject
95
+ .spyproject
96
+
97
+ # Rope project settings
98
+ .ropeproject
99
+
100
+ # mkdocs documentation
101
+ /site
102
+
103
+ # mypy
104
+ .mypy_cache/
105
+
106
+ # DeOldify
107
+ data
108
+ *SymbolicLinks.sh
109
+ *.ipynb_checkpoints*
110
+ ColorizeTraining*[0-9]*.ipynb
111
+ *Colorizer[0-9]*.ipynb
112
+ lesson7-superres*.ipynb
113
+ test.py
114
+ result_images
115
+ *.prof
116
+ video
117
+ test_images/*.jpg
118
+ test_images/*.JPG
119
+ test_images/*.PNG
120
+ test_images/*.png
121
+ test_images/*.jpeg
122
+ test_images/*.JPEG
123
+ deoldify/.ipynb_checkpoints/*-checkpoint.py
124
+ tmp*
125
+
126
+ # Model weights and checkpoints
127
+ models/*.pth
128
+ models/*.pt
129
+ *.pth
130
+ *.pt
131
+ checkpoints/
132
+
133
+ # Logs and debugging
134
+ logs/
135
+ *.log
136
+ wandb/
137
+ .tensorboard/
138
+
139
+ # Output directories
140
+ output/
141
+ results/
142
+ colorized/
143
+
144
+ # IDE
145
+ .vscode/
146
+ .idea/
147
+ *.swp
148
+ *.swo
149
+ *~
150
+
151
+ # OS
152
+ .DS_Store
153
+ Thumbs.db
.pre-commit-config.yaml ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ repos:
2
+ - repo: https://github.com/ambv/black
3
+ rev: stable
4
+ hooks:
5
+ - id: black
6
+ args: [-S]
7
+ language_version: python3.6
.pylintrc ADDED
@@ -0,0 +1,579 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [MASTER]
2
+
3
+ # A comma-separated list of package or module names from where C extensions may
4
+ # be loaded. Extensions are loading into the active Python interpreter and may
5
+ # run arbitrary code.
6
+ extension-pkg-whitelist=
7
+
8
+ # Add files or directories to the blacklist. They should be base names, not
9
+ # paths.
10
+ ignore=CVS
11
+
12
+ # Add files or directories matching the regex patterns to the blacklist. The
13
+ # regex matches against base names, not paths.
14
+ ignore-patterns=
15
+
16
+ # Python code to execute, usually for sys.path manipulation such as
17
+ # pygtk.require().
18
+ #init-hook='import sys; sys.path.append("./venv/lib/python3.7/site-packages")'
19
+
20
+ # Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
21
+ # number of processors available to use.
22
+ jobs=1
23
+
24
+ # Control the amount of potential inferred values when inferring a single
25
+ # object. This can help the performance when dealing with large functions or
26
+ # complex, nested conditions.
27
+ limit-inference-results=100
28
+
29
+ # List of plugins (as comma separated values of python modules names) to load,
30
+ # usually to register additional checkers.
31
+ load-plugins=
32
+
33
+ # Pickle collected data for later comparisons.
34
+ persistent=yes
35
+
36
+ # Specify a configuration file.
37
+ #rcfile=
38
+
39
+ # When enabled, pylint would attempt to guess common misconfiguration and emit
40
+ # user-friendly hints instead of false-positive error messages.
41
+ suggestion-mode=yes
42
+
43
+ # Allow loading of arbitrary C extensions. Extensions are imported into the
44
+ # active Python interpreter and may run arbitrary code.
45
+ unsafe-load-any-extension=no
46
+
47
+
48
+ [MESSAGES CONTROL]
49
+
50
+ # Only show warnings with the listed confidence levels. Leave empty to show
51
+ # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED.
52
+ confidence=
53
+
54
+ # Disable the message, report, category or checker with the given id(s). You
55
+ # can either give multiple identifiers separated by comma (,) or put this
56
+ # option multiple times (only on the command line, not in the configuration
57
+ # file where it should appear only once). You can also use "--disable=all" to
58
+ # disable everything first and then reenable specific checks. For example, if
59
+ # you want to run only the similarities checker, you can use "--disable=all
60
+ # --enable=similarities". If you want to run only the classes checker, but have
61
+ # no Warning level messages displayed, use "--disable=all --enable=classes
62
+ # --disable=W".
63
+ disable=print-statement,
64
+ parameter-unpacking,
65
+ unpacking-in-except,
66
+ old-raise-syntax,
67
+ backtick,
68
+ long-suffix,
69
+ old-ne-operator,
70
+ old-octal-literal,
71
+ import-star-module-level,
72
+ non-ascii-bytes-literal,
73
+ raw-checker-failed,
74
+ bad-inline-option,
75
+ locally-disabled,
76
+ locally-enabled,
77
+ file-ignored,
78
+ suppressed-message,
79
+ useless-suppression,
80
+ deprecated-pragma,
81
+ use-symbolic-message-instead,
82
+ apply-builtin,
83
+ basestring-builtin,
84
+ buffer-builtin,
85
+ cmp-builtin,
86
+ coerce-builtin,
87
+ execfile-builtin,
88
+ file-builtin,
89
+ long-builtin,
90
+ raw_input-builtin,
91
+ reduce-builtin,
92
+ standarderror-builtin,
93
+ unicode-builtin,
94
+ xrange-builtin,
95
+ coerce-method,
96
+ delslice-method,
97
+ getslice-method,
98
+ setslice-method,
99
+ no-absolute-import,
100
+ old-division,
101
+ dict-iter-method,
102
+ dict-view-method,
103
+ next-method-called,
104
+ metaclass-assignment,
105
+ indexing-exception,
106
+ raising-string,
107
+ reload-builtin,
108
+ oct-method,
109
+ hex-method,
110
+ nonzero-method,
111
+ cmp-method,
112
+ input-builtin,
113
+ round-builtin,
114
+ intern-builtin,
115
+ unichr-builtin,
116
+ map-builtin-not-iterating,
117
+ zip-builtin-not-iterating,
118
+ range-builtin-not-iterating,
119
+ filter-builtin-not-iterating,
120
+ using-cmp-argument,
121
+ eq-without-hash,
122
+ div-method,
123
+ idiv-method,
124
+ rdiv-method,
125
+ exception-message-attribute,
126
+ invalid-str-codec,
127
+ sys-max-int,
128
+ bad-python3-import,
129
+ deprecated-string-function,
130
+ deprecated-str-translate-call,
131
+ deprecated-itertools-function,
132
+ deprecated-types-field,
133
+ next-method-defined,
134
+ dict-items-not-iterating,
135
+ dict-keys-not-iterating,
136
+ dict-values-not-iterating,
137
+ deprecated-operator-function,
138
+ deprecated-urllib-function,
139
+ xreadlines-attribute,
140
+ deprecated-sys-function,
141
+ exception-escape,
142
+ comprehension-escape,
143
+ # Disabled due Black
144
+ bad-continuation,
145
+ bad-whitespace,
146
+ # We don't care about these
147
+ redundant-keyword-arg,
148
+
149
+ # Enable the message, report, category or checker with the given id(s). You can
150
+ # either give multiple identifier separated by comma (,) or put this option
151
+ # multiple time (only on the command line, not in the configuration file where
152
+ # it should appear only once). See also the "--disable" option for examples.
153
+ enable=c-extension-no-member
154
+
155
+
156
+ [REPORTS]
157
+
158
+ # Python expression which should return a note less than 10 (10 is the highest
159
+ # note). You have access to the variables errors warning, statement which
160
+ # respectively contain the number of errors / warnings messages and the total
161
+ # number of statements analyzed. This is used by the global evaluation report
162
+ # (RP0004).
163
+ evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
164
+
165
+ # Template used to display messages. This is a python new-style format string
166
+ # used to format the message information. See doc for all details.
167
+ #msg-template=
168
+
169
+ # Set the output format. Available formats are text, parseable, colorized, json
170
+ # and msvs (visual studio). You can also give a reporter class, e.g.
171
+ # mypackage.mymodule.MyReporterClass.
172
+ output-format=text
173
+
174
+ # Tells whether to display a full report or only the messages.
175
+ reports=no
176
+
177
+ # Activate the evaluation score.
178
+ score=yes
179
+
180
+
181
+ [REFACTORING]
182
+
183
+ # Maximum number of nested blocks for function / method body
184
+ max-nested-blocks=5
185
+
186
+ # Complete name of functions that never returns. When checking for
187
+ # inconsistent-return-statements if a never returning function is called then
188
+ # it will be considered as an explicit return statement and no message will be
189
+ # printed.
190
+ never-returning-functions=sys.exit
191
+
192
+
193
+ [LOGGING]
194
+
195
+ # Logging modules to check that the string format arguments are in logging
196
+ # function parameter format.
197
+ logging-modules=logging
198
+
199
+
200
+ [SIMILARITIES]
201
+
202
+ # Ignore comments when computing similarities.
203
+ ignore-comments=yes
204
+
205
+ # Ignore docstrings when computing similarities.
206
+ ignore-docstrings=yes
207
+
208
+ # Ignore imports when computing similarities.
209
+ ignore-imports=no
210
+
211
+ # Minimum lines number of a similarity.
212
+ min-similarity-lines=4
213
+
214
+
215
+ [MISCELLANEOUS]
216
+
217
+ # List of note tags to take in consideration, separated by a comma.
218
+ notes=FIXME,
219
+ XXX,
220
+ TODO
221
+
222
+
223
+ [FORMAT]
224
+
225
+ # Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
226
+ expected-line-ending-format=
227
+
228
+ # Regexp for a line that is allowed to be longer than the limit.
229
+ ignore-long-lines=^\s*(# )?<?https?://\S+>?$
230
+
231
+ # Number of spaces of indent required inside a hanging or continued line.
232
+ indent-after-paren=4
233
+
234
+ # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
235
+ # tab).
236
+ indent-string=' '
237
+
238
+ # Maximum number of characters on a single line.
239
+ max-line-length=100
240
+
241
+ # Maximum number of lines in a module.
242
+ max-module-lines=1000
243
+
244
+ # List of optional constructs for which whitespace checking is disabled. `dict-
245
+ # separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
246
+ # `trailing-comma` allows a space between comma and closing bracket: (a, ).
247
+ # `empty-line` allows space-only lines.
248
+ no-space-check=trailing-comma,
249
+ dict-separator
250
+
251
+ # Allow the body of a class to be on the same line as the declaration if body
252
+ # contains single statement.
253
+ single-line-class-stmt=no
254
+
255
+ # Allow the body of an if to be on the same line as the test if there is no
256
+ # else.
257
+ single-line-if-stmt=no
258
+
259
+
260
+ [BASIC]
261
+
262
+ # Naming style matching correct argument names.
263
+ argument-naming-style=snake_case
264
+
265
+ # Regular expression matching correct argument names. Overrides argument-
266
+ # naming-style.
267
+ #argument-rgx=
268
+
269
+ # Naming style matching correct attribute names.
270
+ attr-naming-style=snake_case
271
+
272
+ # Regular expression matching correct attribute names. Overrides attr-naming-
273
+ # style.
274
+ #attr-rgx=
275
+
276
+ # Bad variable names which should always be refused, separated by a comma.
277
+ bad-names=foo,
278
+ bar,
279
+ baz,
280
+ toto,
281
+ tutu,
282
+ tata
283
+
284
+ # Naming style matching correct class attribute names.
285
+ class-attribute-naming-style=any
286
+
287
+ # Regular expression matching correct class attribute names. Overrides class-
288
+ # attribute-naming-style.
289
+ #class-attribute-rgx=
290
+
291
+ # Naming style matching correct class names.
292
+ class-naming-style=PascalCase
293
+
294
+ # Regular expression matching correct class names. Overrides class-naming-
295
+ # style.
296
+ #class-rgx=
297
+
298
+ # Naming style matching correct constant names.
299
+ const-naming-style=UPPER_CASE
300
+
301
+ # Regular expression matching correct constant names. Overrides const-naming-
302
+ # style.
303
+ #const-rgx=
304
+
305
+ # Minimum line length for functions/classes that require docstrings, shorter
306
+ # ones are exempt.
307
+ docstring-min-length=-1
308
+
309
+ # Naming style matching correct function names.
310
+ function-naming-style=snake_case
311
+
312
+ # Regular expression matching correct function names. Overrides function-
313
+ # naming-style.
314
+ #function-rgx=
315
+
316
+ # Good variable names which should always be accepted, separated by a comma.
317
+ good-names=f,
318
+ i,
319
+ j,
320
+ k,
321
+ s,
322
+ t,
323
+ ex,
324
+ Run,
325
+ _
326
+
327
+ # Include a hint for the correct naming format with invalid-name.
328
+ include-naming-hint=no
329
+
330
+ # Naming style matching correct inline iteration names.
331
+ inlinevar-naming-style=any
332
+
333
+ # Regular expression matching correct inline iteration names. Overrides
334
+ # inlinevar-naming-style.
335
+ #inlinevar-rgx=
336
+
337
+ # Naming style matching correct method names.
338
+ method-naming-style=snake_case
339
+
340
+ # Regular expression matching correct method names. Overrides method-naming-
341
+ # style.
342
+ #method-rgx=
343
+
344
+ # Naming style matching correct module names.
345
+ module-naming-style=snake_case
346
+
347
+ # Regular expression matching correct module names. Overrides module-naming-
348
+ # style.
349
+ #module-rgx=
350
+
351
+ # Colon-delimited sets of names that determine each other's naming style when
352
+ # the name regexes allow several styles.
353
+ name-group=
354
+
355
+ # Regular expression which should only match function or class names that do
356
+ # not require a docstring.
357
+ no-docstring-rgx=^_
358
+
359
+ # List of decorators that produce properties, such as abc.abstractproperty. Add
360
+ # to this list to register other decorators that produce valid properties.
361
+ # These decorators are taken in consideration only for invalid-name.
362
+ property-classes=abc.abstractproperty
363
+
364
+ # Naming style matching correct variable names.
365
+ variable-naming-style=snake_case
366
+
367
+ # Regular expression matching correct variable names. Overrides variable-
368
+ # naming-style.
369
+ variable-rgx=_?[a-z][A-Za-z0-9_]{0,30}$
370
+ argument-rgx=_?[a-z][A-Za-z0-9_]{0,30}$
371
+
372
+
373
+ [TYPECHECK]
374
+
375
+ # List of decorators that produce context managers, such as
376
+ # contextlib.contextmanager. Add to this list to register other decorators that
377
+ # produce valid context managers.
378
+ contextmanager-decorators=contextlib.contextmanager
379
+
380
+ # List of members which are set dynamically and missed by pylint inference
381
+ # system, and so shouldn't trigger E1101 when accessed. Python regular
382
+ # expressions are accepted.
383
+ generated-members=torch.mm,
384
+ torch.diag,
385
+ torch.symeig,
386
+ torch.sqrt,
387
+ torch.cat,
388
+ cv2.cvtColor,
389
+ cv2.COLOR_BGR2YUV,
390
+ cv2.COLOR_YUV2BGR,
391
+
392
+ # Tells whether missing members accessed in mixin class should be ignored. A
393
+ # mixin class is detected if its name ends with "mixin" (case insensitive).
394
+ ignore-mixin-members=yes
395
+
396
+ # Tells whether to warn about missing members when the owner of the attribute
397
+ # is inferred to be None.
398
+ ignore-none=yes
399
+
400
+ # This flag controls whether pylint should warn about no-member and similar
401
+ # checks whenever an opaque object is returned when inferring. The inference
402
+ # can return multiple potential results while evaluating a Python object, but
403
+ # some branches might not be evaluated, which results in partial inference. In
404
+ # that case, it might be useful to still emit no-member and other checks for
405
+ # the rest of the inferred objects.
406
+ ignore-on-opaque-inference=yes
407
+
408
+ # List of class names for which member attributes should not be checked (useful
409
+ # for classes with dynamically set attributes). This supports the use of
410
+ # qualified names.
411
+ ignored-classes=optparse.Values,thread._local,_thread._local
412
+
413
+ # List of module names for which member attributes should not be checked
414
+ # (useful for modules/projects where namespaces are manipulated during runtime
415
+ # and thus existing member attributes cannot be deduced by static analysis. It
416
+ # supports qualified module names, as well as Unix pattern matching.
417
+ ignored-modules=
418
+
419
+ # Show a hint with possible names when a member name was not found. The aspect
420
+ # of finding the hint is based on edit distance.
421
+ missing-member-hint=yes
422
+
423
+ # The minimum edit distance a name should have in order to be considered a
424
+ # similar match for a missing member name.
425
+ missing-member-hint-distance=1
426
+
427
+ # The total number of similar names that should be taken in consideration when
428
+ # showing a hint for a missing member.
429
+ missing-member-max-choices=1
430
+
431
+
432
+ [VARIABLES]
433
+
434
+ # List of additional names supposed to be defined in builtins. Remember that
435
+ # you should avoid to define new builtins when possible.
436
+ additional-builtins=
437
+
438
+ # Tells whether unused global variables should be treated as a violation.
439
+ allow-global-unused-variables=yes
440
+
441
+ # List of strings which can identify a callback function by name. A callback
442
+ # name must start or end with one of those strings.
443
+ callbacks=cb_,
444
+ _cb
445
+
446
+ # A regular expression matching the name of dummy variables (i.e. expected to
447
+ # not be used).
448
+ dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
449
+
450
+ # Argument names that match this expression will be ignored. Default to name
451
+ # with leading underscore.
452
+ ignored-argument-names=_.*|^ignored_|^unused_
453
+
454
+ # Tells whether we should check for unused import in __init__ files.
455
+ init-import=no
456
+
457
+ # List of qualified module names which can have objects that can redefine
458
+ # builtins.
459
+ redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
460
+
461
+
462
+ [SPELLING]
463
+
464
+ # Limits count of emitted suggestions for spelling mistakes.
465
+ max-spelling-suggestions=4
466
+
467
+ # Spelling dictionary name. Available dictionaries: en_IE (myspell), en_ZM
468
+ # (myspell), en_GB (myspell), en_HK (myspell), en_BZ (myspell), en_PH
469
+ # (myspell), en_ZA (myspell), en_MW (myspell), en_AU (myspell), en_CA
470
+ # (myspell), en_JM (myspell), en_GH (myspell), en_TT (myspell), en_SG
471
+ # (myspell), en_BW (myspell), en_US (myspell), en_NZ (myspell), en_AG
472
+ # (myspell), en_ZW (myspell), en_NA (myspell), en_IN (myspell), en_BS
473
+ # (myspell), en_DK (myspell), en_NG (myspell)..
474
+ spelling-dict=
475
+
476
+ # List of comma separated words that should not be checked.
477
+ spelling-ignore-words=
478
+
479
+ # A path to a file that contains private dictionary; one word per line.
480
+ spelling-private-dict-file=
481
+
482
+ # Tells whether to store unknown words to indicated private dictionary in
483
+ # --spelling-private-dict-file option instead of raising a message.
484
+ spelling-store-unknown-words=no
485
+
486
+
487
+ [IMPORTS]
488
+
489
+ # Allow wildcard imports from modules that define __all__.
490
+ allow-wildcard-with-all=no
491
+
492
+ # Analyse import fallback blocks. This can be used to support both Python 2 and
493
+ # 3 compatible code, which means that the block might have code that exists
494
+ # only in one or another interpreter, leading to false positives when analysed.
495
+ analyse-fallback-blocks=no
496
+
497
+ # Deprecated modules which should not be used, separated by a comma.
498
+ deprecated-modules=optparse,tkinter.tix
499
+
500
+ # Create a graph of external dependencies in the given file (report RP0402 must
501
+ # not be disabled).
502
+ ext-import-graph=
503
+
504
+ # Create a graph of every (i.e. internal and external) dependencies in the
505
+ # given file (report RP0402 must not be disabled).
506
+ import-graph=
507
+
508
+ # Create a graph of internal dependencies in the given file (report RP0402 must
509
+ # not be disabled).
510
+ int-import-graph=
511
+
512
+ # Force import order to recognize a module as part of the standard
513
+ # compatibility libraries.
514
+ known-standard-library=
515
+
516
+ # Force import order to recognize a module as part of a third party library.
517
+ known-third-party=enchant
518
+
519
+
520
+ [CLASSES]
521
+
522
+ # List of method names used to declare (i.e. assign) instance attributes.
523
+ defining-attr-methods=__init__,
524
+ __new__,
525
+ setUp
526
+
527
+ # List of member names, which should be excluded from the protected access
528
+ # warning.
529
+ exclude-protected=_asdict,
530
+ _fields,
531
+ _replace,
532
+ _source,
533
+ _make
534
+
535
+ # List of valid names for the first argument in a class method.
536
+ valid-classmethod-first-arg=cls
537
+
538
+ # List of valid names for the first argument in a metaclass class method.
539
+ valid-metaclass-classmethod-first-arg=cls
540
+
541
+
542
+ [DESIGN]
543
+
544
+ # Maximum number of arguments for function / method.
545
+ max-args=5
546
+
547
+ # Maximum number of attributes for a class (see R0902).
548
+ max-attributes=7
549
+
550
+ # Maximum number of boolean expressions in an if statement.
551
+ max-bool-expr=5
552
+
553
+ # Maximum number of branch for function / method body.
554
+ max-branches=12
555
+
556
+ # Maximum number of locals for function / method body.
557
+ max-locals=15
558
+
559
+ # Maximum number of parents for a class (see R0901).
560
+ max-parents=7
561
+
562
+ # Maximum number of public methods for a class (see R0904).
563
+ max-public-methods=20
564
+
565
+ # Maximum number of return / yield for function / method body.
566
+ max-returns=6
567
+
568
+ # Maximum number of statements in function / method body.
569
+ max-statements=50
570
+
571
+ # Minimum number of public methods for a class (see R0903).
572
+ min-public-methods=2
573
+
574
+
575
+ [EXCEPTIONS]
576
+
577
+ # Exceptions that will emit a warning when being caught. Defaults to
578
+ # "Exception".
579
+ overgeneral-exceptions=Exception
.travis.yml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ sudo: false
2
+ language: python
3
+ install: pip install tox
4
+ matrix:
5
+ include:
6
+ - python: "3.6"
7
+ env: TOX_ENV=static
8
+ - python: "3.6"
9
+ env: TOX_ENV=format
10
+ script: tox -e $TOX_ENV
CHANGELOG.md ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [2.0.0] - 2025-12-01
6
+
7
+ ### Added
8
+ - **Intel GPU Support**: Added support for Intel Arc and Data Center GPUs using Intel Extension for PyTorch (IPEX).
9
+ - **Unified Device Management**: Implemented `deoldify.device` to automatically detect and manage CUDA, XPU (Intel), and CPU devices.
10
+ - **Documentation**:
11
+ - `docs/nvidia_setup.md`: Comprehensive guide for setting up NVIDIA GPUs with CUDA 12.x.
12
+ - `docs/intel_gpu_setup.md`: Guide for setting up Intel GPUs.
13
+ - **Verification Script**: Added `verify_refactor.py` to validate environment setup and model instantiation.
14
+ - **Compatibility Layer**: Created `deoldify/fastai_compat.py` to replace the obsolete `fastai` 1.x library, ensuring compatibility with modern PyTorch.
15
+ - **Requirements Files**: Added `requirements.txt` and `requirements_intel.txt` for pip users.
16
+ - **Code Quality**:
17
+ - Comprehensive module docstring for `fastai_compat.py`.
18
+ - Type hints throughout compatibility layer.
19
+ - README badges for Python, PyTorch, CUDA versions, and license.
20
+
21
+ ### Changed
22
+ - **Core Dependencies**:
23
+ - Removed dependency on `fastai` 1.x.
24
+ - Upgraded PyTorch to 2.5+.
25
+ - Upgraded CUDA support to 12.x.
26
+ - Updated `environment.yml` for modern NVIDIA environments.
27
+ - Created `environment_intel.yml` for Intel environments.
28
+ - **Refactoring**:
29
+ - Refactored `visualize.py`, `filters.py`, `generators.py`, `unet.py`, and `layers.py` to use pure PyTorch and the new compatibility layer.
30
+ - Replaced FastAI-specific image processing with standard `torchvision` transforms.
31
+ - **Device Handling**: Updated `Learner` and `DataBunch` shims to use the new unified device manager.
32
+ - **.gitignore**: Enhanced to exclude model weights in `models/` directory, logs, IDE files, and OS-specific files.
33
+
34
+ ### Removed
35
+ - **Legacy Code**: Removed direct imports of `fastai` throughout the codebase.
36
+ - **Archived Status**: The project is now actively maintained for modern hardware.
CODE_OF_CONDUCT.md ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex, gender characteristics,
8
+ gender identity and expression, level of experience, education, socio-economic
9
+ status, nationality, personal appearance, race, caste, color, religion, or
10
+ sexual identity and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment for our
18
+ community include:
19
+
20
+ * Demonstrating empathy and kindness toward other people
21
+ * Being respectful of differing opinions, viewpoints, and experiences
22
+ * Giving and gracefully accepting constructive feedback
23
+ * Accepting responsibility and apologizing to those affected by our mistakes,
24
+ and learning from the experience
25
+ * Focusing on what is best not just for us as individuals, but for the
26
+ overall community
27
+
28
+ Examples of unacceptable behavior include:
29
+
30
+ * The use of sexualized language or imagery, and sexual attention or
31
+ advances of any kind
32
+ * Trolling, insulting or derogatory comments, and personal or political attacks
33
+ * Public or private harassment
34
+ * Publishing others' private information, such as a physical or email
35
+ address, without their explicit permission
36
+ * Other conduct which could reasonably be considered inappropriate in a
37
+ professional setting
38
+
39
+ ## Enforcement Responsibilities
40
+
41
+ Community leaders are responsible for clarifying and enforcing our standards of
42
+ acceptable behavior and will take appropriate and fair corrective action in
43
+ response to any behavior that they deem inappropriate, threatening, offensive,
44
+ or harmful.
45
+
46
+ Community leaders have the right and responsibility to remove, edit, or reject
47
+ comments, commits, code, wiki edits, issues, and other contributions that are
48
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
49
+ decisions when appropriate.
50
+
51
+ ## Scope
52
+
53
+ This Code of Conduct applies within all community spaces, and also applies when
54
+ an individual is officially representing the community in public spaces.
55
+ Examples of representing our community include using an official e-mail address,
56
+ posting via an official social media account, or acting as an appointed
57
+ representative at an online or offline event.
58
+
59
+ ## Enforcement
60
+
61
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
+ reported to the community leaders responsible for enforcement.
63
+ All complaints will be reviewed and investigated promptly and fairly.
64
+
65
+ All community leaders are obligated to respect the privacy and security of the
66
+ reporter of any incident.
67
+
68
+ ## Enforcement Guidelines
69
+
70
+ Community leaders will follow these Community Impact Guidelines in determining
71
+ the consequences for any action they deem in violation of this Code of Conduct:
72
+
73
+ ### 1. Correction
74
+
75
+ **Community Impact**: Use of inappropriate language or other behavior deemed
76
+ unprofessional or unwelcome in the community.
77
+
78
+ **Consequence**: A private, written warning from community leaders, providing
79
+ clarity around the nature of the violation and an explanation of why the
80
+ behavior was inappropriate. A public apology may be requested.
81
+
82
+ ### 2. Warning
83
+
84
+ **Community Impact**: A violation through a single incident or series of
85
+ actions.
86
+
87
+ **Consequence**: A warning with consequences for continued behavior. No
88
+ interaction with the people involved, including unsolicited interaction with
89
+ those enforcing the Code of Conduct, for a specified period of time. This
90
+ includes avoiding interactions in community spaces as well as external channels
91
+ like social media. Violating these terms may lead to a temporary or
92
+ permanent ban.
93
+
94
+ ### 3. Temporary Ban
95
+
96
+ **Community Impact**: A serious violation of community standards, including
97
+ sustained inappropriate behavior.
98
+
99
+ **Consequence**: A temporary ban from any sort of interaction or public
100
+ communication with the community for a specified period of time. No public or
101
+ private interaction with the people involved, including unsolicited interaction
102
+ with those enforcing the Code of Conduct, is allowed during this period.
103
+ Violating these terms may lead to a permanent ban.
104
+
105
+ ### 4. Permanent Ban
106
+
107
+ **Community Impact**: Demonstrating a pattern of violation of community
108
+ standards, including sustained inappropriate behavior, harassment of an
109
+ individual, or aggression toward or disparagement of classes of individuals.
110
+
111
+ **Consequence**: A permanent ban from any sort of public interaction within
112
+ the community.
113
+
114
+ ## Attribution
115
+
116
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
117
+ version 2.1, available at
118
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
119
+
120
+ Community Impact Guidelines were inspired by
121
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
122
+
123
+ [homepage]: https://www.contributor-covenant.org
124
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
125
+ [Mozilla CoC]: https://github.com/mozilla/diversity
CONTRIBUTING.md ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contributing to DeOldify
2
+
3
+ First off, thanks for taking the time to contribute! ❤️
4
+
5
+ All types of contributions are encouraged and valued. See the [Table of Contents](#table-of-contents) for different ways to help and details about how this project handles them. Please make sure to read the relevant section before making your contribution. It will make it a lot easier for us maintainers and smooth out the experience for all involved. The community looks forward to your contributions. 🎉
6
+
7
+ > And if you like the project, but just don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about:
8
+ > - Star the project
9
+ > - Tweet about it
10
+ > - Refer this project in your project's readme
11
+ > - Mention the project at local meetups and tell your friends/colleagues
12
+
13
+ ## Table of Contents
14
+
15
+ - [Code of Conduct](#code-of-conduct)
16
+ - [I Have a Question](#i-have-a-question)
17
+ - [I Want To Contribute](#i-want-to-contribute)
18
+ - [Reporting Bugs](#reporting-bugs)
19
+ - [Suggesting Enhancements](#suggesting-enhancements)
20
+
21
+ ## Code of Conduct
22
+
23
+ This project and everyone participating in it is governed by the
24
+ [DeOldify Code of Conduct](CODE_OF_CONDUCT.md).
25
+ By participating, you are expected to uphold this code. Please report unacceptable behavior
26
+ to the project maintainers.
27
+
28
+ ## I Have a Question
29
+
30
+ > If you want to ask a question, we assume that you have read the available [Documentation](README.md).
31
+
32
+ Before you ask a question, it is best to search for existing [Issues](https://github.com/thookham/DeOldify/issues) that might help you. In case you have found a suitable issue and still need clarification, you can write your question in this issue. It is also advisable to search the internet for answers first.
33
+
34
+ If you then still feel the need to ask a question and need clarification, we recommend the following:
35
+
36
+ - Open an [Issue](https://github.com/thookham/DeOldify/issues/new).
37
+ - Provide as much context as you can about what you're running into.
38
+ - Provide project and platform versions (Python version, PyTorch version, CUDA version, etc), depending on what seems relevant.
39
+
40
+ We will then take care of the issue as soon as possible.
41
+
42
+ ## I Want To Contribute
43
+
44
+ ### Reporting Bugs
45
+
46
+ #### Before Submitting a Bug Report
47
+
48
+ A good bug report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report. Please complete the following steps in advance to help us fix any potential bug as fast as possible.
49
+
50
+ - Make sure that you are using the latest version.
51
+ - Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (Make sure that you have read the [documentation](README.md). If you are looking for support, you might want to check [this section](#i-have-a-question)).
52
+ - To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the [bug tracker](https://github.com/thookham/DeOldify/issues?q=label%3Abug).
53
+ - Also make sure to search the internet (including Stack Overflow) to see if users outside of the GitHub community have discussed the issue.
54
+ - Collect information about the bug:
55
+ - Stack trace (Traceback)
56
+ - OS, Platform and Version (Windows, Linux, macOS)
57
+ - Python version, PyTorch version, CUDA version
58
+ - GPU model and driver version
59
+ - Possibly your input and the output
60
+ - Can you reliably reproduce the issue? And can you also reproduce it with older versions?
61
+
62
+ #### How to Submit a Good Bug Report
63
+
64
+ We use GitHub issues to track bugs and errors. If you run into an issue with the project:
65
+
66
+ - Open an [Issue](https://github.com/thookham/DeOldify/issues/new). (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.)
67
+ - Explain the behavior you would expect and the actual behavior.
68
+ - Please provide as much context as possible and describe the *reproduction steps* that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case.
69
+ - Provide the information you collected in the previous section.
70
+
71
+ ### Suggesting Enhancements
72
+
73
+ This section guides you through submitting an enhancement suggestion for DeOldify, **including completely new features and minor improvements to existing functionality**. Following these guidelines will help maintainers and the community to understand your suggestion and find related suggestions.
74
+
75
+ #### Before Submitting an Enhancement
76
+
77
+ - Make sure that you are using the latest version.
78
+ - Read the [documentation](README.md) carefully and find out if the functionality is already covered, maybe by an individual configuration.
79
+ - Perform a [search](https://github.com/thookham/DeOldify/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
80
+ - Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If you're just targeting a minority of users, consider writing an add-on/plugin library.
81
+
82
+ #### How to Submit a Good Enhancement Suggestion
83
+
84
+ Enhancement suggestions are tracked as [GitHub issues](https://github.com/thookham/DeOldify/issues).
85
+
86
+ - Use a **clear and descriptive title** for the issue to identify the suggestion.
87
+ - Provide a **step-by-step description of the suggested enhancement** in as much detail as possible.
88
+ - **Describe the current behavior** and **explain which behavior you expected to see instead** and why. At this point you can also tell which alternatives you do not work for you.
89
+ - You may want to include **screenshots and animated GIFs** which help you demonstrate the steps or point out the part which the suggestion is related to.
90
+ - **Explain why this enhancement would be useful** to most DeOldify users. You may also want to point out the other projects that solved it better and which could serve as inspiration.
ColorFIDBenchmarkArtistic.ipynb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:81ff2900f2459c5f9c2a2cd7e6e28369cb47be06456911b95265dfc924c68fd6
3
+ size 7379
ColorizeTrainingArtistic.ipynb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:04151afd527032964230ea44879e76ab9d62a3b544bcdf01fe56b65e18bf71a9
3
+ size 15025
ColorizeTrainingStable.ipynb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a8439478243ef7d308267f189b18e6f25073a3c28770265587c37b2aa558a3fe
3
+ size 15033
ColorizeTrainingStableLargeBatch.ipynb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2895ec4a822ce541fd73ee58f261c51237b1819135beeb5c9a15ef3ee2d0ca10
3
+ size 18892
ColorizeTrainingVideo.ipynb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cd9153345bbbd1f032e35d51511e5cc5a60f7aeea0210147a69af2188ab97455
3
+ size 12035
ColorizeTrainingWandb.ipynb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:70096ddb975b3345850df253aeae4f1a58c2e9bae90c42e681b0b674325de42c
3
+ size 27053
HF_README.md ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - image-colorization
5
+ - gan
6
+ - computer-vision
7
+ - pytorch
8
+ - onnx
9
+ library_name: pytorch
10
+ ---
11
+
12
+ # DeOldify Model Weights
13
+
14
+ This repository contains pretrained weights for **DeOldify**, a deep learning model for colorizing and restoring old black and white images and videos.
15
+
16
+ **Original Repository**: [thookham/DeOldify](https://github.com/thookham/DeOldify)
17
+ **Original Author**: Jason Antic ([jantic/DeOldify](https://github.com/jantic/DeOldify))
18
+
19
+ ## Model Overview
20
+
21
+ DeOldify uses a Self-Attention Generative Adversarial Network (SAGAN) with a novel **NoGAN** training approach to achieve stable, high-quality colorization without the typical GAN artifacts.
22
+
23
+ ### Three Specialized Models
24
+
25
+ 1. **Artistic** - Highest quality with vibrant colors and interesting details
26
+ - Best for: General images, historical photos
27
+ - Backbone: ResNet34 U-Net
28
+ - Training: 5 NoGAN cycles, 32% ImageNet
29
+
30
+ 2. **Stable** - Best for portraits and landscapes, reduced artifacts
31
+ - Best for: Faces, nature scenes
32
+ - Backbone: ResNet101 U-Net
33
+ - Training: 3 NoGAN cycles, 7% ImageNet
34
+
35
+ 3. **Video** - Optimized for smooth, flicker-free video
36
+ - Best for: Video colorization, consistency
37
+ - Backbone: ResNet101 U-Net
38
+ - Training: Initial cycle only, 2.2% ImageNet
39
+
40
+ ## Available Files
41
+
42
+ ### ONNX Models (Browser/Inference)
43
+
44
+ | File | Size | Description |
45
+ |------|------|-------------|
46
+ | `deoldify-art.onnx` | 243 MB | Artistic model in ONNX format for browser use |
47
+ | `deoldify-quant.onnx` | 61 MB | Quantized artistic model (75% smaller, slightly lower quality) |
48
+
49
+ ### PyTorch Weights (Training & Inference)
50
+
51
+ **Generator Weights** (Main):
52
+ - `ColorizeArtistic_gen.pth` (243 MB)
53
+ - `ColorizeStable_gen.pth` (834 MB)
54
+ - `ColorizeVideo_gen.pth` (834 MB)
55
+
56
+ **Critic Weights** (Main):
57
+ - `ColorizeArtistic_crit.pth` (361 MB)
58
+ - `ColorizeStable_crit.pth` (361 MB)
59
+ - `ColorizeVideo_crit.pth` (361 MB)
60
+
61
+ **PretrainOnly Weights** (For continued training):
62
+ - `ColorizeArtistic_PretrainOnly_gen.pth` (729 MB)
63
+ - `ColorizeArtistic_PretrainOnly_crit.pth` (1.05 GB)
64
+ - `ColorizeStable_PretrainOnly_crit.pth` (1.05 GB)
65
+ - `ColorizeVideo_PretrainOnly_crit.pth` (1.05 GB)
66
+
67
+ > **Note**: Stable and Video PretrainOnly generators are split files hosted on [GitHub Releases](https://github.com/thookham/DeOldify/releases/tag/v2.0-models).
68
+
69
+ ## Usage
70
+
71
+ ### Browser (ONNX)
72
+
73
+ ```html
74
+ <!DOCTYPE html>
75
+ <html>
76
+ <head>
77
+ <script src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js"></script>
78
+ </head>
79
+ <body>
80
+ <script>
81
+ async function colorize() {
82
+ // Load model from Hugging Face
83
+ const session = await ort.InferenceSession.create(
84
+ "https://huggingface.co/thookham/DeOldify/resolve/main/deoldify-art.onnx"
85
+ );
86
+
87
+ // Run inference (see full example in GitHub repo)
88
+ // ...
89
+ }
90
+ </script>
91
+ </body>
92
+ </html>
93
+ ```
94
+
95
+ ### PyTorch (Python)
96
+
97
+ ```python
98
+ from huggingface_hub import hf_hub_download
99
+ import torch
100
+
101
+ # Download model weights
102
+ model_path = hf_hub_download(
103
+ repo_id="thookham/DeOldify",
104
+ filename="ColorizeArtistic_gen.pth"
105
+ )
106
+
107
+ # Load weights (requires deoldify package installed)
108
+ # See GitHub repository for full usage examples
109
+ ```
110
+
111
+ ### Installation
112
+
113
+ ```bash
114
+ # Clone the main repository
115
+ git clone https://github.com/thookham/DeOldify
116
+ cd DeOldify
117
+
118
+ # Install dependencies
119
+ pip install -r requirements.txt
120
+
121
+ # Download a model
122
+ from huggingface_hub import hf_hub_download
123
+ model = hf_hub_download(repo_id="thookham/DeOldify", filename="ColorizeStable_gen.pth")
124
+ ```
125
+
126
+ ## Technical Details
127
+
128
+ ### Architecture
129
+ - **Generator**: U-Net with ResNet34/101 backbone, spectral normalization, self-attention layers
130
+ - **Critic**: PatchGAN discriminator
131
+ - **Loss**: Perceptual loss (VGG16) + GAN loss
132
+
133
+ ### NoGAN Training
134
+ A novel training approach that combines:
135
+ 1. Generator pretraining with feature loss
136
+ 2. Critic pretraining on generated images
137
+ 3. Short GAN training (30-60 minutes) at inflection point
138
+ 4. Optional cycle repeats for more colorful results
139
+
140
+ This eliminates typical GAN artifacts while maintaining realistic colorization.
141
+
142
+ ### Training Data
143
+ - Dataset: ImageNet subsets (1-32% depending on model)
144
+ - Resolution: 192px during training
145
+ - Augmentation: Gaussian noise for video stability
146
+
147
+ ## Model Card
148
+
149
+ ### Model Details
150
+ - **Developed by**: Jason Antic (original), Travis Hookham (modernization)
151
+ - **Model type**: Conditional GAN for image-to-image translation
152
+ - **Language(s)**: N/A (computer vision)
153
+ - **License**: MIT
154
+ - **Parent Model**: Based on FastAI U-Net and Self-Attention GAN papers
155
+
156
+ ### Intended Use
157
+ **Primary Use**: Colorizing black and white photographs and videos
158
+ **Out-of-Scope**: Real-time processing, guaranteed historical accuracy
159
+
160
+ ### Limitations
161
+ - Colors may not be historically accurate
162
+ - Performance degrades on very low quality/damaged images
163
+ - Artistic model may require render_factor tuning
164
+ - Video model trades some color vibrancy for consistency
165
+
166
+ ## Related Models & Resources
167
+
168
+ ### Similar Colorization Models on Hugging Face
169
+
170
+ **GAN-based Colorization:**
171
+ - [Hammad712/GAN-Colorization-Model](https://huggingface.co/Hammad712/GAN-Colorization-Model) - GAN model for grayscale to color transformation
172
+ - [jessicanono/filparty_colorization](https://huggingface.co/jessicanono/filparty_colorization) - ResNet-based model for historical photos
173
+
174
+ **Stable Diffusion-based:**
175
+ - [rsortino/ColorizeNet](https://huggingface.co/rsortino/ColorizeNet) - ControlNet adaptation of SD 2.1 for colorization
176
+ - [AlekseyCalvin/ColorizeTruer_KontextFluxVar6_BySAP](https://huggingface.co/AlekseyCalvin/ColorizeTruer_KontextFluxVar6_BySAP) - Advanced Flux-based colorization
177
+
178
+ **Interactive Demos (Spaces):**
179
+ - [aryadytm/Photo-Colorization](https://huggingface.co/spaces/aryadytm/Photo-Colorization)
180
+ - [Shashank009/Black-And-White-Image-Colorization](https://huggingface.co/spaces/Shashank009/Black-And-White-Image-Colorization)
181
+ - [CA611/Image-Colorization](https://huggingface.co/spaces/CA611/Image-Colorization)
182
+
183
+ ### Why Choose DeOldify?
184
+
185
+ DeOldify stands out for:
186
+ - **NoGAN Training**: Unique approach eliminating typical GAN artifacts
187
+ - **Specialized Models**: Three purpose-built models (Artistic, Stable, Video)
188
+ - **Video Support**: Flicker-free temporal consistency
189
+ - **Proven Track Record**: Powers MyHeritage InColor and widely adopted
190
+ - **ONNX Support**: Browser-ready models for offline use
191
+
192
+ ## Citation
193
+
194
+ If you use these models, please cite:
195
+
196
+ ```bibtex
197
+ @misc{deoldify,
198
+ author = {Antic, Jason},
199
+ title = {DeOldify},
200
+ year = {2019},
201
+ publisher = {GitHub},
202
+ url = {https://github.com/jantic/DeOldify}
203
+ }
204
+ ```
205
+
206
+ ## Links
207
+
208
+ - **GitHub Repository**: https://github.com/thookham/DeOldify
209
+ - **Original DeOldify**: https://github.com/jantic/DeOldify
210
+ - **MyHeritage InColor** (Commercial version): https://www.myheritage.com/incolor
211
+ - **Demo (Browser)**: See browser/ folder in GitHub repo
212
+
213
+ ## License
214
+
215
+ MIT License. See [LICENSE](https://github.com/thookham/DeOldify/blob/master/LICENSE) file.
ImageColorizer.ipynb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:becb7dac71eb07d80e0b580c227e45031d5d178fc08487dfb2ecc7348238f557
3
+ size 5670
ImageColorizerArtisticTests.ipynb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b031061b6f2b56a3bdb2b26e00d6122b2f9144454e5e62eddcbdb9521145980e
3
+ size 79684
ImageColorizerColab.ipynb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:39bcb7942400ab7a373b8053ba3df94b9159ac1fd66a6441915cd7661be145ad
3
+ size 8484
ImageColorizerColabStable.ipynb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:af0f95463e10a9c46ba3f5b1656590f2be552ae8fc90dc2bf6369275f6af4085
3
+ size 8415
ImageColorizerStableTests.ipynb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3bb167d6e3751f8ee44eafb90b636b86d299ac7f44940d5adf9be616d43d8194
3
+ size 78929
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Jason Antic
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
MANIFEST.in ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ include README.md
2
+ include LICENSE
3
+ include requirements.txt
README.md ADDED
@@ -0,0 +1,542 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # DeOldify (Modernized)
3
+
4
+ ![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)
5
+ ![PyTorch 2.5+](https://img.shields.io/badge/PyTorch-2.5+-ee4c2c.svg)
6
+ ![CUDA 12.x](https://img.shields.io/badge/CUDA-12.x-76B900.svg)
7
+ ![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)
8
+
9
+ # DeOldify (Modernized)
10
+
11
+ **DeOldify** has been modernized! This fork updates the project to support **PyTorch 2.5+**, **CUDA 12.x**, and **Intel GPUs (Arc/Data Center)**. It removes the dependency on the obsolete FastAI 1.x library, making it easier to run on modern hardware.
12
+
13
+ **Quick Start**:
14
+ - **NVIDIA GPU**: [Setup Guide](docs/nvidia_setup.md)
15
+ - **Intel GPU**: [Setup Guide](docs/intel_gpu_setup.md)
16
+
17
+ **Original Project**: The original DeOldify by Jason Antic can be found [here](https://github.com/jantic/DeOldify).
18
+
19
+ **In Browser (new!)**
20
+ You can run DeOldify directly in your browser without any installation! We've included a local browser-based implementation in this repository.
21
+
22
+ **How to use:**
23
+ 1. Navigate to the `browser/` folder in this repository.
24
+ 2. Open `index.html` in Chrome, Firefox, or Edge.
25
+ 3. Choose between the **Artistic** (higher quality) or **Quantized** (faster) model.
26
+ 4. Select an image and watch it colorize instantly!
27
+
28
+ *Note: This implementation uses ONNX models hosted on our GitHub releases and Hugging Face, ensuring privacy and availability.*
29
+
30
+ Also check out the original browser repo: https://github.com/akbartus/DeOldify-on-Browser
31
+
32
+ **Hugging Face 🤗**: All models are also available on Hugging Face: [thookham/DeOldify](https://huggingface.co/thookham/DeOldify)
33
+
34
+ The **most advanced** version of DeOldify image colorization is available here,
35
+ exclusively. Try a few images for free! [MyHeritage In Color](https://www.myheritage.com/incolor)
36
+
37
+ **Replicate:** Image: <a href="https://replicate.com/arielreplicate/deoldify_image"><img src="https://replicate.com/arielreplicate/deoldify_image/badge"></a> | Video: <a href="https://replicate.com/arielreplicate/deoldify_video"><img src="https://replicate.com/arielreplicate/deoldify_video/badge"></a>
38
+
39
+ ----------------------------
40
+
41
+ Image (artistic) [![Colab for images](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/jantic/DeOldify/blob/master/ImageColorizerColab.ipynb)
42
+ | Video [![Colab for video](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/jantic/DeOldify/blob/master/VideoColorizerColab.ipynb)
43
+
44
+ Having trouble with the default image colorizer, aka "artistic"? Try the
45
+ "stable" one below. It generally won't produce colors that are as interesting as
46
+ "artistic", but the glitches are noticeably reduced.
47
+
48
+ Image (stable) [![Colab for stable model](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/jantic/DeOldify/blob/master/ImageColorizerColabStable.ipynb)
49
+
50
+ Instructions on how to use the Colabs above have been kindly provided in video
51
+ tutorial form by Old Ireland in Colour's John Breslin. It's great! Click video
52
+ image below to watch.
53
+
54
+ [![DeOldify Tutorial](http://img.youtube.com/vi/VaEl0faDw38/0.jpg)](http://www.youtube.com/watch?v=VaEl0faDw38)
55
+
56
+ Get more updates on [Twitter
57
+ ![Twitter logo](resource_images/twitter.svg)](https://twitter.com/DeOldify).
58
+
59
+ ## Table of Contents
60
+
61
+ - [About DeOldify](#about-deoldify)
62
+ - [Example Videos](#example-videos)
63
+ - [Example Images](#example-images)
64
+ - [Stuff That Should Probably Be In A Paper](#stuff-that-should-probably-be-in-a-paper)
65
+ - [How to Achieve Stable Video](#how-to-achieve-stable-video)
66
+ - [What is NoGAN?](#what-is-nogan)
67
+ - [Why Three Models?](#why-three-models)
68
+ - [Technical Details](#the-technical-details)
69
+ - [Going Forward](#this-project-going-forward)
70
+ - [Roadmap](ROADMAP.md)
71
+ - [Getting Started Yourself](#getting-started-yourself)
72
+ - [Easiest Approach](#easiest-approach)
73
+ - [Your Own Machine](#your-own-machine-not-as-easy)
74
+ - [Pretrained Weights](#pretrained-weights)
75
+
76
+ ## About DeOldify
77
+
78
+ Simply put, the mission of this project is to colorize and restore old images and
79
+ film footage. We'll get into the details in a bit, but first let's see some
80
+ pretty pictures and videos!
81
+
82
+ ### New and Exciting Stuff in DeOldify
83
+
84
+ - Glitches and artifacts are almost entirely eliminated
85
+ - Better skin (less zombies)
86
+ - More highly detailed and photorealistic renders
87
+ - Much less "blue bias"
88
+ - **Video** - it actually looks good!
89
+ - **NoGAN** - a new and weird but highly effective way to do GAN training for
90
+ image to image.
91
+
92
+ ## Example Videos
93
+
94
+ **Note:** Click images to watch
95
+
96
+ ### Facebook F8 Demo
97
+
98
+ [![DeOldify Facebook F8 Movie Colorization Demo](http://img.youtube.com/vi/l3UXXid04Ys/0.jpg)](http://www.youtube.com/watch?v=l3UXXid04Ys)
99
+
100
+ ### Silent Movie Examples
101
+
102
+ [![DeOldify Silent Movie Examples](http://img.youtube.com/vi/EXn-n2iqEjI/0.jpg)](http://www.youtube.com/watch?v=EXn-n2iqEjI)
103
+
104
+ ## Example Images
105
+
106
+ "Migrant Mother" by Dorothea Lange (1936)
107
+
108
+ ![Migrant Mother](https://i.imgur.com/Bt0vnke.jpg)
109
+
110
+ Woman relaxing in her livingroom in Sweden (1920)
111
+
112
+ ![Sweden Living Room](https://i.imgur.com/158d0oU.jpg)
113
+
114
+ "Toffs and Toughs" by Jimmy Sime (1937)
115
+
116
+ ![Class Divide](https://i.imgur.com/VYuav4I.jpg)
117
+
118
+ Thanksgiving Maskers (1911)
119
+
120
+ ![Thanksgiving Maskers](https://i.imgur.com/n8qVJ5c.jpg)
121
+
122
+ Glen Echo Madame Careta Gypsy Camp in Maryland (1925)
123
+
124
+ ![Gypsy Camp](https://i.imgur.com/1oYrJRI.jpg)
125
+
126
+ "Mr. and Mrs. Lemuel Smith and their younger children in their farm house,
127
+ Carroll County, Georgia." (1941)
128
+
129
+ ![Georgia Farmhouse](https://i.imgur.com/I2j8ynm.jpg)
130
+
131
+ "Building the Golden Gate Bridge" (est 1937)
132
+
133
+ ![Golden Gate Bridge](https://i.imgur.com/6SbFjfq.jpg)
134
+
135
+ > **Note:** What you might be wondering is while this render looks cool, are the
136
+ > colors accurate? The original photo certainly makes it look like the towers of
137
+ > the bridge could be white. We looked into this and it turns out the answer is
138
+ > no - the towers were already covered in red primer by this time. So that's
139
+ > something to keep in mind- historical accuracy remains a huge challenge!
140
+
141
+ "Terrasse de café, Paris" (1925)
142
+
143
+ ![Cafe Paris](https://i.imgur.com/WprQwP5.jpg)
144
+
145
+ Norwegian Bride (est late 1890s)
146
+
147
+ ![Norwegian Bride](https://i.imgur.com/MmtvrZm.jpg)
148
+
149
+ Zitkála-Šá (Lakota: Red Bird), also known as Gertrude Simmons Bonnin (1898)
150
+
151
+ ![Native Woman](https://i.imgur.com/zIGM043.jpg)
152
+
153
+ Chinese Opium Smokers (1880)
154
+
155
+ ![Opium Real](https://i.imgur.com/lVGq8Vq.jpg)
156
+
157
+ ## Stuff That Should Probably Be In A Paper
158
+
159
+ ### How to Achieve Stable Video
160
+
161
+ NoGAN training is crucial to getting the kind of stable and colorful images seen
162
+ in this iteration of DeOldify. NoGAN training combines the benefits of GAN
163
+ training (wonderful colorization) while eliminating the nasty side effects
164
+ (like flickering objects in video). Believe it or not, video is rendered using
165
+ isolated image generation without any sort of temporal modeling tacked on. The
166
+ process performs 30-60 minutes of the GAN portion of "NoGAN" training, using 1%
167
+ to 3% of imagenet data once. Then, as with still image colorization, we
168
+ "DeOldify" individual frames before rebuilding the video.
169
+
170
+ In addition to improved video stability, there is an interesting thing going on
171
+ here worth mentioning. It turns out the models I run, even different ones and
172
+ with different training structures, keep arriving at more or less the same
173
+ solution. That's even the case for the colorization of things you may think
174
+ would be arbitrary and unknowable, like the color of clothing, cars, and even
175
+ special effects (as seen in "Metropolis").
176
+
177
+ ![Metropolis Special FX](https://thumbs.gfycat.com/HeavyLoneBlowfish-size_restricted.gif)
178
+
179
+ My best guess is that the models are learning some interesting rules about how to
180
+ colorize based on subtle cues present in the black and white images that I
181
+ certainly wouldn't expect to exist. This result leads to nicely deterministic and
182
+ consistent results, and that means you don't have track model colorization
183
+ decisions because they're not arbitrary. Additionally, they seem remarkably
184
+ robust so that even in moving scenes the renders are very consistent.
185
+
186
+ ![Moving Scene Example](https://thumbs.gfycat.com/FamiliarJubilantAsp-size_restricted.gif)
187
+
188
+ Other ways to stabilize video add up as well. First, generally speaking rendering
189
+ at a higher resolution (higher render_factor) will increase stability of
190
+ colorization decisions. This stands to reason because the model has higher
191
+ fidelity image information to work with and will have a greater chance of making
192
+ the "right" decision consistently. Closely related to this is the use of
193
+ resnet101 instead of resnet34 as the backbone of the generator- objects are
194
+ detected more consistently and correctly with this. This is especially important
195
+ for getting good, consistent skin rendering. It can be particularly visually
196
+ jarring if you wind up with "zombie hands", for example.
197
+
198
+ ![Zombie Hand Example](https://thumbs.gfycat.com/ThriftyInferiorIsabellinewheatear-size_restricted.gif)
199
+
200
+ Additionally, gaussian noise augmentation during training appears to help but at
201
+ this point the conclusions as to just how much are bit more tenuous (I just
202
+ haven't formally measured this yet). This is loosely based on work done in style
203
+ transfer video, described here:
204
+ <https://medium.com/element-ai-research-lab/stabilizing-neural-style-transfer-for-video-62675e203e42>.
205
+
206
+ Special thanks go to Rani Horev for his contributions in implementing this noise
207
+ augmentation.
208
+
209
+ ### What is NoGAN?
210
+
211
+ This is a new type of GAN training that I've developed to solve some key problems
212
+ in the previous DeOldify model. It provides the benefits of GAN training while
213
+ spending minimal time doing direct GAN training. Instead, most of the training
214
+ time is spent pretraining the generator and critic separately with more
215
+ straight-forward, fast and reliable conventional methods. A key insight here is
216
+ that those more "conventional" methods generally get you most of the results you
217
+ need, and that GANs can be used to close the gap on realism. During the very
218
+ short amount of actual GAN training the generator not only gets the full
219
+ realistic colorization capabilities that used to take days of progressively
220
+ resized GAN training, but it also doesn't accrue nearly as much of the artifacts
221
+ and other ugly baggage of GANs. In fact, you can pretty much eliminate glitches
222
+ and artifacts almost entirely depending on your approach. As far as I know this
223
+ is a new technique. And it's incredibly effective.
224
+
225
+ #### Original DeOldify Model
226
+
227
+ ![Before Flicker](https://thumbs.gfycat.com/CoordinatedVeneratedHogget-size_restricted.gif)
228
+
229
+ #### NoGAN-Based DeOldify Model
230
+
231
+ ![After Flicker](https://thumbs.gfycat.com/OilyBlackArctichare-size_restricted.gif)
232
+
233
+ The steps are as follows: First train the generator in a conventional way by
234
+ itself with just the feature loss. Next, generate images from that, and train
235
+ the critic on distinguishing between those outputs and real images as a basic
236
+ binary classifier. Finally, train the generator and critic together in a GAN
237
+ setting (starting right at the target size of 192px in this case). Now for
238
+ the weird part: All the useful GAN training here only takes place within a very
239
+ small window of time. There's an inflection point where it appears the critic
240
+ has transferred everything it can that is useful to the generator. Past this
241
+ point, image quality oscillates between the best that you can get at the
242
+ inflection point, or bad in a predictable way (orangish skin, overly red lips,
243
+ etc). There appears to be no productive training after the inflection point.
244
+ And this point lies within training on just 1% to 3% of the Imagenet Data!
245
+ That amounts to about 30-60 minutes of training at 192px.
246
+
247
+ The hard part is finding this inflection point. So far, I've accomplished this
248
+ by making a whole bunch of model save checkpoints (every 0.1% of data iterated
249
+ on) and then just looking for the point where images look great before they go
250
+ totally bonkers with orange skin (always the first thing to go). Additionally,
251
+ generator rendering starts immediately getting glitchy and inconsistent at this
252
+ point, which is no good particularly for video. What I'd really like to figure
253
+ out is what the tell-tale sign of the inflection point is that can be easily
254
+ automated as an early stopping point. Unfortunately, nothing definitive is
255
+ jumping out at me yet. For one, it's happening in the middle of training loss
256
+ decreasing- not when it flattens out, which would seem more reasonable on the surface.
257
+
258
+ Another key thing about NoGAN training is you can repeat pretraining the critic
259
+ on generated images after the initial GAN training, then repeat the GAN training
260
+ itself in the same fashion. This is how I was able to get extra colorful results
261
+ with the "artistic" model. But this does come at a cost currently- the output of
262
+ the generator becomes increasingly inconsistent and you have to experiment with
263
+ render resolution (render_factor) to get the best result. But the renders are
264
+ still glitch free and way more consistent than I was ever able to achieve with
265
+ the original DeOldify model. You can do about five of these repeat cycles, give
266
+ or take, before you get diminishing returns, as far as I can tell.
267
+
268
+ Keep in mind- I haven't been entirely rigorous in figuring out what all is going
269
+ on in NoGAN- I'll save that for a paper. That means there's a good chance I'm
270
+ wrong about something. But I think it's definitely worth putting out there now
271
+ because I'm finding it very useful- it's solving basically much of my remaining
272
+ problems I had in DeOldify.
273
+
274
+ This builds upon a technique developed in collaboration with Jeremy Howard and
275
+ Sylvain Gugger for Fast.AI's Lesson 7 in version 3 of Practical Deep Learning
276
+ for Coders Part I. The particular lesson notebook can be found here:
277
+ <https://github.com/fastai/course-v3/blob/master/nbs/dl1/lesson7-superres-gan.ipynb>
278
+
279
+ ## Why Three Models?
280
+
281
+ There are now three models to choose from in DeOldify. Each of these has key
282
+ strengths and weaknesses, and so have different use cases. Video is for video
283
+ of course. But stable and artistic are both for images, and sometimes one will
284
+ do images better than the other.
285
+
286
+ More details:
287
+
288
+ - **Artistic** - This model achieves the highest quality results in image
289
+ coloration, in terms of interesting details and vibrance. The most notable
290
+ drawback however is that it's a bit of a pain to fiddle around with to get the
291
+ best results (you have to adjust the rendering resolution or render_factor to
292
+ achieve this). Additionally, the model does not do as well as stable in a few
293
+ key common scenarios- nature scenes and portraits. The model uses a resnet34
294
+ backbone on a UNet with an emphasis on depth of layers on the decoder side.
295
+ This model was trained with 5 critic pretrain/GAN cycle repeats via NoGAN, in
296
+ addition to the initial generator/critic pretrain/GAN NoGAN training, at 192px.
297
+ This adds up to a total of 32% of Imagenet data trained once (12.5 hours of
298
+ direct GAN training).
299
+
300
+ - **Stable** - This model achieves the best results with landscapes and
301
+ portraits. Notably, it produces less "zombies"- where faces or limbs stay gray
302
+ rather than being colored in properly. It generally has less weird
303
+ miscolorations than artistic, but it's also less colorful in general. This
304
+ model uses a resnet101 backbone on a UNet with an emphasis on width of layers on
305
+ the decoder side. This model was trained with 3 critic pretrain/GAN cycle
306
+ repeats via NoGAN, in addition to the initial generator/critic pretrain/GAN
307
+ NoGAN training, at 192px. This adds up to a total of 7% of Imagenet data
308
+ trained once (3 hours of direct GAN training).
309
+
310
+ - **Video** - This model is optimized for smooth, consistent and flicker-free
311
+ video. This would definitely be the least colorful of the three models, but
312
+ it's honestly not too far off from "stable". The model is the same as "stable"
313
+ in terms of architecture, but differs in training. It's trained for a mere 2.2%
314
+ of Imagenet data once at 192px, using only the initial generator/critic
315
+ pretrain/GAN NoGAN training (1 hour of direct GAN training).
316
+
317
+ Because the training of the artistic and stable models was done before the
318
+ "inflection point" of NoGAN training described in "What is NoGAN???" was
319
+ discovered, I believe this amount of training on them can be knocked down
320
+ considerably. As far as I can tell, the models were stopped at "good points"
321
+ that were well beyond where productive training was taking place. I'll be
322
+ looking into this in the future.
323
+
324
+ Ideally, eventually these three models will be consolidated into one that has all
325
+ these good desirable unified. I think there's a path there, but it's going to
326
+ require more work! So for now, the most practical solution appears to be to
327
+ maintain multiple models.
328
+
329
+
330
+
331
+
332
+
333
+ ## The Technical Details
334
+
335
+ This is a deep learning based model. More specifically, what I've done is
336
+ combined the following approaches:
337
+
338
+ ### [Self-Attention Generative Adversarial Network](https://arxiv.org/abs/1805.08318)
339
+
340
+ Except the generator is a **pretrained U-Net**, and I've just modified it to
341
+ have the spectral normalization and self-attention. It's a pretty
342
+ straightforward translation.
343
+
344
+ ### [Two Time-Scale Update Rule](https://arxiv.org/abs/1706.08500)
345
+
346
+ This is also very straightforward – it's just one to one generator/critic
347
+ iterations and higher critic learning rate.
348
+ This is modified to incorporate a "threshold" critic loss that makes sure that
349
+ the critic is "caught up" before moving on to generator training.
350
+ This is particularly useful for the "NoGAN" method described below.
351
+
352
+ ### NoGAN
353
+
354
+ There's no paper here! This is a new type of GAN training that I've developed to
355
+ solve some key problems in the previous DeOldify model.
356
+ The gist is that you get the benefits of GAN training while spending minimal time
357
+ doing direct GAN training.
358
+ More details are in the [What is NoGAN?](#what-is-nogan) section (it's a doozy).
359
+
360
+ ### Generator Loss
361
+
362
+ Loss during NoGAN learning is two parts: One is a basic Perceptual Loss (or
363
+ Feature Loss) based on VGG16 – this just biases the generator model to replicate
364
+ the input image.
365
+ The second is the loss score from the critic. For the curious – Perceptual Loss
366
+ isn't sufficient by itself to produce good results.
367
+ It tends to just encourage a bunch of brown/green/blue – you know, cheating to
368
+ the test, basically, which neural networks are really good at doing!
369
+ Key thing to realize here is that GANs essentially are learning the loss function
370
+ for you – which is really one big step closer to toward the ideal that we're
371
+ shooting for in machine learning.
372
+ And of course you generally get much better results when you get the machine to
373
+ learn something you were previously hand coding.
374
+ That's certainly the case here.
375
+
376
+ **Of note:** There's no longer any "Progressive Growing of GANs" type training
377
+ going on here. It's just not needed in lieu of the superior results obtained
378
+ by the "NoGAN" technique described above.
379
+
380
+ The beauty of this model is that it should be generally useful for all sorts of
381
+ image modification, and it should do it quite well.
382
+ What you're seeing above are the results of the colorization model, but that's
383
+ just one component in a pipeline that I'm developing with the exact same approach.
384
+
385
+ ## This Project, Going Forward
386
+
387
+ So that's the gist of this project – I'm looking to make old photos and film
388
+ look reeeeaaally good with GANs, and more importantly, make the project *useful*.
389
+ In the meantime though this is going to be my baby and I'll be actively updating
390
+ and improving the code over the foreseeable future.
391
+ I'll try to make this as user-friendly as possible, but I'm sure there's going
392
+ to be hiccups along the way.
393
+
394
+ Oh and I swear I'll document the code properly...eventually. Admittedly I'm
395
+ *one of those* people who believes in "self documenting code" (LOL).
396
+
397
+ ## Best Practices & Golden Nuggets
398
+
399
+ Based on extensive community research and the original author's insights, here are the "Golden Nuggets" for getting the best results:
400
+
401
+ ### 1. Video Flicker? Use the "Video" Model!
402
+ If you are experiencing flickering in your video outputs, ensure you are using the **Video** model weights (`ColorizeVideo_gen.pth`). This model was specifically trained with **NoGAN** to prioritize temporal consistency over raw color vibrancy. The "Artistic" model will almost always flicker on video.
403
+
404
+ ### 2. The "NoGAN" Secret
405
+ The core innovation of DeOldify is **NoGAN** training. It pre-trains the generator with a conventional loss function (Perceptual Loss) before introducing the GAN component. This minimizes the "GAN artifacts" (like flicker) while keeping the colorization quality.
406
+
407
+ ### 3. Post-Processing is Key
408
+ Even with the Video model, some flicker may persist. We recommend using **FFmpeg's `deflicker` filter** as a post-processing step.
409
+ * **New Feature**: We have added a `deflicker=True` option to the `VideoColorizer` to handle this automatically!
410
+
411
+ ### 4. Alternative Implementations
412
+ * **Anime/Manga**: If you are colorizing anime sketches, check out [AnimeColorDeOldify](https://github.com/Dakini/AnimeColorDeOldify), which uses a model fine-tuned on Danbooru.
413
+ * **C# / .NET**: For a native C# implementation, see [DeOldify.NET](https://github.com/ColorfulSoft/DeOldify.NET).
414
+
415
+ ## Getting Started Yourself
416
+ have that yet so I'm not going to make it the default instruction here yet.
417
+
418
+ **Alternative Install:** User daddyparodz has kindly created an installer script
419
+ for Ubuntu, and in particular Ubuntu on WSL, that may make things easier:
420
+ <https://github.com/daddyparodz/AutoDeOldifyLocal>
421
+
422
+ #### Note on test_images Folder
423
+
424
+ The images in the `test_images` folder have been removed because they were using
425
+ Git LFS and that costs a lot of money when GitHub actually charges for bandwidth
426
+ on a popular open source project (they had a billing bug for while that was
427
+ recently fixed). The notebooks that use them (the image test ones) still point
428
+ to images in that directory that I (Jason) have personally and I'd like to keep
429
+ it that way because, after all, I'm by far the primary and most active developer.
430
+ But they won't work for you. Still, those notebooks are a convenient template
431
+ for making your own tests if you're so inclined.
432
+
433
+ #### Typical training
434
+
435
+ The notebook `ColorizeTrainingWandb` has been created to log and monitor results
436
+ through [Weights & Biases](https://www.wandb.com/). You can find a description of
437
+ typical training by consulting [W&B Report](https://app.wandb.ai/borisd13/DeOldify/reports?view=borisd13%2FDeOldify).
438
+
439
+ ## Pretrained Weights
440
+
441
+ To start right away on your own machine with your own images or videos without
442
+ training the models yourself, you'll need to download the "Completed Generator
443
+ Weights" listed below and drop them in the /models/ folder.
444
+
445
+ The colorization inference notebooks should be able to guide you from here. The
446
+ notebooks to use are named ImageColorizerArtistic.ipynb,
447
+ ImageColorizerStable.ipynb, and VideoColorizer.ipynb.
448
+
449
+ ### Completed Generator Weights
450
+
451
+ - [Artistic](https://github.com/thookham/DeOldify/releases/download/v2.0-models/ColorizeArtistic_gen.pth)
452
+ - [Stable](https://github.com/thookham/DeOldify/releases/download/v2.0-models/ColorizeStable_gen.pth)
453
+ - [Video](https://github.com/thookham/DeOldify/releases/download/v2.0-models/ColorizeVideo_gen.pth)
454
+
455
+ ### Completed Critic Weights
456
+
457
+ - [Artistic](https://github.com/thookham/DeOldify/releases/download/v2.0-models/ColorizeArtistic_crit.pth)
458
+ - [Stable](https://github.com/thookham/DeOldify/releases/download/v2.0-models/ColorizeStable_crit.pth)
459
+ - [Video](https://github.com/thookham/DeOldify/releases/download/v2.0-models/ColorizeVideo_crit.pth)
460
+
461
+ ### Pretrain Only Generator Weights
462
+
463
+ > **Note:** The Stable and Video PretrainOnly generator weights are split into multiple parts due to their size. Please download all parts (e.g., `.pth.000`, `.pth.001`) and run `python reassemble_models.py` to join them.
464
+
465
+ - [Artistic](https://github.com/thookham/DeOldify/releases/download/v2.0-models/ColorizeArtistic_PretrainOnly_gen.pth)
466
+ - [Stable (Part 1)](https://github.com/thookham/DeOldify/releases/download/v2.0-models/ColorizeStable_PretrainOnly_gen.pth.000) | [Stable (Part 2)](https://github.com/thookham/DeOldify/releases/download/v2.0-models/ColorizeStable_PretrainOnly_gen.pth.001)
467
+ - [Video (Part 1)](https://github.com/thookham/DeOldify/releases/download/v2.0-models/ColorizeVideo_PretrainOnly_gen.pth.000) | [Video (Part 2)](https://github.com/thookham/DeOldify/releases/download/v2.0-models/ColorizeVideo_PretrainOnly_gen.pth.001)
468
+
469
+ ### Pretrain Only Critic Weights
470
+
471
+ - [Artistic](https://github.com/thookham/DeOldify/releases/download/v2.0-models/ColorizeArtistic_PretrainOnly_crit.pth)
472
+ - [Stable](https://github.com/thookham/DeOldify/releases/download/v2.0-models/ColorizeStable_PretrainOnly_crit.pth)
473
+ - [Video](https://github.com/thookham/DeOldify/releases/download/v2.0-models/ColorizeVideo_PretrainOnly_crit.pth)
474
+
475
+ ### Archived Models (Browser / ONNX)
476
+
477
+ - [Artistic ONNX](https://github.com/thookham/DeOldify/releases/download/v2.0-models/deoldify-art.onnx)
478
+ - [Quantized ONNX](https://github.com/thookham/DeOldify/releases/download/v2.0-models/deoldify-quant.onnx)
479
+
480
+ ## Want the Old DeOldify?
481
+
482
+ We suspect some of you are going to want access to the original DeOldify model
483
+ for various reasons. We have that archived here: <https://github.com/dana-kelley/DeOldify>
484
+
485
+ ## Want More?
486
+
487
+ Follow [#DeOldify](https://twitter.com/search?q=%23Deoldify) on Twitter.
488
+
489
+ ## License
490
+
491
+ All code in this repository is under the MIT license as specified by the LICENSE
492
+ file.
493
+
494
+ The model weights listed in this readme under the "Pretrained Weights" section
495
+ are trained by ourselves and are released under the MIT license.
496
+
497
+ ## A Statement on Open Source Support
498
+
499
+ We believe that open source has done a lot of good for the world. After all,
500
+ DeOldify simply wouldn't exist without it. But we also believe that there needs
501
+ to be boundaries on just how much is reasonable to be expected from an open
502
+ source project maintained by just two developers.
503
+
504
+ Our stance is that we're providing the code and documentation on research that
505
+ we believe is beneficial to the world. What we have provided are novel takes
506
+ on colorization, GANs, and video that are hopefully somewhat friendly for
507
+ developers and researchers to learn from and adopt. This is the culmination of
508
+ well over a year of continuous work, free for you. What wasn't free was
509
+ shouldered by us, the developers. We left our jobs, bought expensive GPUs, and
510
+ had huge electric bills as a result of dedicating ourselves to this.
511
+
512
+ What we haven't provided here is a ready to use free "product" or "app", and we
513
+ don't ever intend on providing that. It's going to remain a Linux based project
514
+ without Windows support, coded in Python, and requiring people to have some extra
515
+ technical background to be comfortable using it. Others have stepped in with
516
+ their own apps made with DeOldify, some paid and some free, which is what we want!
517
+ We're instead focusing on what we believe we can do best- making better
518
+ commercial models that people will pay for.
519
+ Does that mean you're not getting the very best for free? Of course. We simply
520
+ don't believe that we're obligated to provide that, nor is it feasible! We
521
+ compete on research and sell that. Not a GUI or web service that wraps said
522
+ research- that part isn't something we're going to be great at anyways. We're not
523
+ about to shoot ourselves in the foot by giving away our actual competitive
524
+ advantage for free, quite frankly.
525
+
526
+ We're also not willing to go down the rabbit hole of providing endless, open
527
+ ended and personalized support on this open source project. Our position is
528
+ this: If you have the proper background and resources, the project provides
529
+ more than enough to get you started. We know this because we've seen plenty of
530
+ people using it and making money off of their own projects with it.
531
+
532
+ Thus, if you have an issue come up and it happens to be an actual bug that
533
+ having it be fixed will benefit users generally, then great- that's something
534
+ we'll be happy to look into.
535
+
536
+
537
+ In contrast, if you're asking about something that really amounts to asking for
538
+ personalized and time consuming support that won't benefit anybody else, we're
539
+ not going to help. It's simply not in our interest to do that. We have bills to
540
+ pay, after all. And if you're asking for help on something that can already be
541
+ derived from the documentation or code? That's simply annoying, and we're not
542
+ going to pretend to be ok with that.
ROADMAP.md ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DeOldify Roadmap
2
+
3
+ This document outlines the development roadmap for DeOldify (Modernized), organized by priority and timeline. The project has successfully completed a major modernization effort and is now focused on expanding hardware support and exploring new deployment options.
4
+
5
+ ## 🎯 Project Vision
6
+
7
+ Make DeOldify accessible and performant across modern hardware platforms (NVIDIA, Intel, AMD) while maintaining the cutting-edge colorization quality that made it popular. Enable deployment in diverse environments from local machines to cloud infrastructure.
8
+
9
+ ---
10
+
11
+ ## ✅ Recently Completed (v2.0 - November 2025)
12
+
13
+ ### Core Modernization
14
+ - ✅ **PyTorch 2.5+ Migration**: Removed dependency on obsolete FastAI 1.x library
15
+ - ✅ **CUDA 12.x Support**: Full support for modern NVIDIA GPUs
16
+ - ✅ **Intel GPU Support**: Arc and Data Center GPU support via Intel Extension for PyTorch (IPEX)
17
+ - ✅ **Unified Device Management**: Automatic detection and fallback (Intel → NVIDIA → CPU)
18
+ - ✅ **Compatibility Layer**: Created `deoldify.fastai_compat` for seamless PyTorch integration
19
+
20
+ ### Infrastructure & Tooling
21
+ - ✅ **Model Migration**: All weights migrated to GitHub Releases with SHA256 verification
22
+ - ✅ **Verification Scripts**: `verify_models.py` and `verify_refactor.py` for validation
23
+ - ✅ **GitHub Community Standards**: Code of Conduct, Contributing Guidelines, Security Policy
24
+ - ✅ **CI/CD**: Unit tests and automated workflows
25
+ - ✅ **Browser Implementation**: Local ONNX-based colorization in browser
26
+
27
+ ### Documentation
28
+ - ✅ **Setup Guides**: Comprehensive guides for NVIDIA and Intel GPUs
29
+ - ✅ **Hardware Guide**: Benchmarks and requirements
30
+ - ✅ **Deployment Guide**: Local serving instructions
31
+ - ✅ **Modernized Notebooks**: Updated Colab notebooks with file upload widgets
32
+
33
+ ---
34
+
35
+ ## 🔴 High Priority (Q1 2025)
36
+
37
+ ### Intel NPU Support
38
+ **Goal**: Enable Neural Processing Unit acceleration for Intel Core Ultra processors
39
+
40
+ - [ ] **Research & Investigation**
41
+ - Investigate OpenVINO toolkit integration
42
+ - Evaluate Intel Extension for PyTorch NPU capabilities
43
+ - Benchmark NPU performance vs GPU/CPU inference
44
+
45
+ - [ ] **Implementation**
46
+ - Add NPU device detection to `deoldify.device`
47
+ - Implement NPU-specific optimizations
48
+ - Update fallback chain: Intel NPU → Intel GPU → NVIDIA GPU → CPU
49
+
50
+ - [ ] **Documentation & Testing**
51
+ - Create `docs/intel_npu_setup.md`
52
+ - Add NPU tests to CI/CD pipeline
53
+ - Update hardware requirements guide
54
+
55
+ **Expected Impact**: Enable efficient inference on laptops and mobile workstations without discrete GPUs.
56
+
57
+ ---
58
+
59
+ ## 🟠 Medium Priority (Q2 2025)
60
+
61
+ ### AMD GPU Support
62
+ **Goal**: Support Radeon GPUs via ROCm
63
+
64
+ - [ ] Add ROCm device detection
65
+ - [ ] Create `environment_amd.yml` for ROCm environments
66
+ - [ ] Test on RDNA 2/3 architecture
67
+ - [ ] Document AMD setup process
68
+
69
+ ### Performance Optimizations
70
+ **Goal**: Improve inference speed and memory efficiency
71
+
72
+ - [ ] **Quantization**: INT8/FP16 inference modes
73
+ - [ ] **Dynamic Batching**: Process multiple images efficiently
74
+ - [ ] **Model Pruning**: Reduce model size without quality loss
75
+ - [ ] **ONNX Runtime**: Evaluate ONNX Runtime for cross-platform inference
76
+
77
+ ### Enhanced Browser Implementation
78
+ **Goal**: Improve browser-based colorization UX
79
+
80
+ - [ ] Add WebGPU support for hardware acceleration
81
+ - [ ] Implement progressive rendering for large images
82
+ - [ ] Add batch processing capabilities
83
+ - [ ] Create comparison slider UI
84
+
85
+ ---
86
+
87
+ ## 🟡 Low Priority (Q3-Q4 2025)
88
+
89
+ ### Cloud Deployment
90
+ **Goal**: Simplify cloud deployment for production use
91
+
92
+ - [ ] **Google Cloud Platform**
93
+ - Vertex AI deployment scripts
94
+ - Container images for Cloud Run
95
+ - Example Terraform configurations
96
+
97
+ - [ ] **AWS**
98
+ - SageMaker deployment templates
99
+ - Lambda@Edge for serverless inference
100
+
101
+ - [ ] **Azure**
102
+ - Azure ML deployment guide
103
+ - Container Apps examples
104
+
105
+ ### Model Improvements
106
+ **Goal**: Enhance colorization quality and capabilities
107
+
108
+ - [ ] **Fine-Tuning Tools**
109
+ - Scripts for domain-specific fine-tuning
110
+ - Transfer learning examples
111
+ - Custom dataset preparation guides
112
+ - **Custom Training Guides**: Documentation for fine-tuning NoGAN on domain-specific footage (e.g., anime, old film)
113
+
114
+ - [ ] **Post-Processing Tools**
115
+ - Advanced deflicker integration (FFmpeg)
116
+ - Temporal smoothing helpers
117
+ - Comparison tools for different render factors
118
+
119
+ - [ ] **New Model Variants**
120
+ - Lightweight mobile-optimized model
121
+ - Ultra-high-resolution model (8K+)
122
+ - Real-time video colorization model
123
+
124
+ ### API & Integration
125
+ **Goal**: Make DeOldify easier to integrate into other applications
126
+
127
+ - [ ] **REST API**
128
+ - FastAPI/Flask-based serving
129
+ - Docker containers with API
130
+ - OpenAPI/Swagger documentation
131
+
132
+ - [ ] **Python Package**
133
+ - Publish to PyPI
134
+ - Simplified installation (`pip install deoldify`)
135
+ - High-level API for common use cases
136
+
137
+ ---
138
+
139
+ ## 🔵 Future Exploration (2026+)
140
+
141
+ ### Advanced Features
142
+ - **Temporal Coherence**: Improved video stability with optical flow
143
+ - **User Guidance**: Interactive colorization with color hints
144
+ - **Style Transfer**: Multiple artistic colorization styles
145
+ - **4K/8K Support**: Native ultra-high-resolution processing
146
+
147
+ ### Research Directions
148
+ - **Diffusion Models**: Explore stable diffusion for colorization
149
+ - **Transformer Architectures**: Evaluate Vision Transformers (ViT)
150
+ - **Few-Shot Learning**: Colorize with minimal reference images
151
+ - **Historical Accuracy**: Training on verified historical color photos
152
+
153
+ ### Community Features
154
+ - **Model Zoo**: User-contributed fine-tuned models
155
+ - **Plugin System**: Extensible architecture for custom filters
156
+ - **Web Service**: Official hosted API (potential paid tier)
157
+
158
+ ---
159
+
160
+ ## 📊 Success Metrics
161
+
162
+ We measure progress through:
163
+
164
+ - **Hardware Coverage**: Percentage of modern GPUs supported (Target: 90%+)
165
+ - **Inference Speed**: FPS for 1080p video colorization (Target: 30+ FPS on modern GPU)
166
+ - **Model Quality**: User satisfaction and comparison to commercial solutions
167
+ - **Adoption**: GitHub stars, PyPI downloads, community contributions
168
+ - **Documentation**: Completeness and clarity based on user feedback
169
+
170
+ ---
171
+
172
+ ## 🤝 How to Contribute
173
+
174
+ We welcome contributions aligned with this roadmap! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
175
+
176
+ **High-Impact Areas**:
177
+ - Testing on different hardware configurations
178
+ - Documentation improvements and translations
179
+ - Performance benchmarking and optimization
180
+ - Bug reports with reproducible examples
181
+
182
+ ---
183
+
184
+ ## 📝 Roadmap Updates
185
+
186
+ This roadmap is reviewed and updated quarterly. Last updated: **December 2025**
187
+
188
+ For detailed technical tasks, see [TODO.md](TODO.md).
189
+ For recent changes, see [CHANGELOG.md](CHANGELOG.md).
SECURITY.md ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ Use this section to tell people about which versions of your project are
6
+ currently being supported with security updates.
7
+
8
+ | Version | Supported |
9
+ | ------- | ------------------ |
10
+ | 1.0.x | :white_check_mark: |
11
+ | < 1.0 | :x: |
12
+
13
+ ## Reporting a Vulnerability
14
+
15
+ Use this section to tell people how to report a vulnerability.
16
+
17
+ Tell them where to go, how often they can expect to get an update on a
18
+ reported vulnerability, what to expect if the vulnerability is accepted or
19
+ declined, etc.
TODO.md ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DeOldify Modernization Roadmap
2
+
3
+ This document tracks the remaining tasks to fully modernize the DeOldify repository, prioritized by user feedback.
4
+
5
+ ## 🔴 Priority 1: Intel GPU Support (A-1)
6
+ *Goal: Ensure robust support for Intel Arc and Data Center GPUs.*
7
+
8
+ - [x] **Verify `device_id.py`**
9
+ - Ensure `DeviceId` enum includes Intel/XPU options if necessary.
10
+ - [x] **Verify Integration**
11
+ - Check if `visualize.py` and other scripts correctly use the `_device.py` manager for Intel hardware.
12
+ - Ensure fallback logic (Intel -> NVIDIA -> CPU) works as intended.
13
+ - [ ] **Intel NPU Support**
14
+ - Investigate and implement NPU detection (OpenVINO/IPEX).
15
+
16
+ ## 🔴 Priority 2: NVIDIA GPU Modernization (A-2)
17
+ *Goal: Leverage latest CUDA and PyTorch features while maintaining reasonable backward compatibility.*
18
+
19
+ - [x] **Verify Optimization**
20
+ - Ensure `torch.backends.cudnn.benchmark` and other optimizations are correctly applied for modern NVIDIA GPUs.
21
+ - Double check `environment.yml` against latest PyTorch/CUDA matrix.
22
+ - [x] **Legacy CUDA Support**
23
+ - Document support for older drivers (last 5 years) where possible, or provide alternative environment files.
24
+
25
+ ## 🟠 Priority 3: Colab Modernization
26
+ *Goal: Fix broken notebooks and improve UX.*
27
+
28
+ - [x] **Fix `requirements-colab.txt`**
29
+ - Remove `fastai==1.0.60` (conflicts with new PyTorch).
30
+ - Add `torch`, `torchvision`, and other modern dependencies.
31
+ - [x] **Update Notebooks**
32
+ - Remove `import fastai`.
33
+ - Use `deoldify.fastai_compat`.
34
+ - [x] **UI Improvements**
35
+ - Drag-and-drop, Gallery, Comparison view.
36
+
37
+ ## 🟡 Priority 4: Documentation & Testing
38
+ *Goal: Comprehensive guides and stability.*
39
+
40
+ - [x] **Detailed Documentation**
41
+ - Create `docs/HARDWARE_GUIDE.md` (Benchmarks & Requirements).
42
+ - Create `docs/DEPLOYMENT_GUIDE.md` (Local serving).
43
+ - [x] **Testing**
44
+ - Create `tests/` directory with unit tests for device selection and compatibility layer.
45
+ - Add CI/CD workflow.
46
+
47
+ ## 🔵 Future Work: Cloud Integration
48
+ - [x] **Migrate Pretrained Weights**
49
+ - Host models on GitHub Releases to ensure longevity.
50
+ - Update all notebooks and docs to point to new URLs.
51
+ - [ ] **Google Cloud Platform (Vertex AI)**
52
+ - Deployment scripts and containers.
USAGE_EXAMPLES.md ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DeOldify Usage Examples
2
+
3
+ This guide provides practical examples for using DeOldify models from Hugging Face.
4
+
5
+ ## Quick Start
6
+
7
+ ### Install Dependencies
8
+
9
+ ```bash
10
+ pip install huggingface_hub torch torchvision Pillow numpy
11
+ ```
12
+
13
+ ### Download a Model
14
+
15
+ ```python
16
+ from huggingface_hub import hf_hub_download
17
+
18
+ # Download the Stable model (recommended for portraits)
19
+ model_path = hf_hub_download(
20
+ repo_id="thookham/DeOldify",
21
+ filename="ColorizeStable_gen.pth"
22
+ )
23
+
24
+ print(f"Model downloaded to: {model_path}")
25
+ ```
26
+
27
+ ## Using PyTorch Models
28
+
29
+ > **Note**: The full DeOldify package is required to load and use the PyTorch models. Clone the repository: `git clone https://github.com/thookham/DeOldify`
30
+
31
+ ### Example: Colorize an Image
32
+
33
+ ```python
34
+ from deoldify import device
35
+ from deoldify.visualize import get_image_colorizer
36
+ from PIL import Image
37
+
38
+ # Initialize colorizer (will download model if needed)
39
+ colorizer = get_image_colorizer(artistic=False) # Use Stable model
40
+
41
+ # Colorize an image
42
+ source_path = "old_photo.jpg"
43
+ result_path = colorizer.plot_transformed_image(
44
+ path=source_path,
45
+ render_factor=35, # Higher = better quality, slower
46
+ compare=True # Show before/after
47
+ )
48
+
49
+ print(f"Colorized image saved to: {result_path}")
50
+ ```
51
+
52
+ ### Example: Batch Processing
53
+
54
+ ```python
55
+ from pathlib import Path
56
+ from deoldify.visualize import get_image_colorizer
57
+
58
+ colorizer = get_image_colorizer(artistic=True) # Use Artistic model
59
+
60
+ input_dir = Path("black_and_white_photos")
61
+ output_dir = Path("colorized")
62
+ output_dir.mkdir(exist_ok=True)
63
+
64
+ for img_path in input_dir.glob("*.jpg"):
65
+ print(f"Processing {img_path.name}...")
66
+ result = colorizer.get_transformed_image(
67
+ path=str(img_path),
68
+ render_factor=30
69
+ )
70
+ result.save(output_dir / img_path.name)
71
+
72
+ print(f"Processed {len(list(input_dir.glob('*.jpg')))} images")
73
+ ```
74
+
75
+ ## Using ONNX Models (Browser)
76
+
77
+ The ONNX models can run directly in web browsers using ONNX Runtime Web.
78
+
79
+ ### Example: HTML Page
80
+
81
+ ```html
82
+ <!DOCTYPE html>
83
+ <html>
84
+ <head>
85
+ <script src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js"></script>
86
+ </head>
87
+ <body>
88
+ <input type="file" id="imageInput" accept="image/*" />
89
+ <canvas id="outputCanvas"></canvas>
90
+
91
+ <script>
92
+ async function loadAndColorize() {
93
+ // Load model from Hugging Face
94
+ const session = await ort.InferenceSession.create(
95
+ "https://huggingface.co/thookham/DeOldify/resolve/main/deoldify-quant.onnx"
96
+ );
97
+
98
+ document.getElementById('imageInput').addEventListener('change', async (e) => {
99
+ const file = e.target.files[0];
100
+ const image = new Image();
101
+ image.src = URL.createObjectURL(file);
102
+
103
+ image.onload = async () => {
104
+ // Preprocessing (resize to 256x256, convert to Float32 tensor)
105
+ const canvas = document.createElement('canvas');
106
+ canvas.width = 256;
107
+ canvas.height = 256;
108
+ const ctx = canvas.getContext('2d');
109
+ ctx.drawImage(image, 0, 0, 256, 256);
110
+
111
+ const imageData = ctx.getImageData(0, 0, 256, 256);
112
+ // ... (preprocessing code)
113
+
114
+ // Run inference
115
+ const tensor = new ort.Tensor('float32', processedData, [1, 3, 256, 256]);
116
+ const results = await session.run({ input: tensor });
117
+
118
+ // Display result
119
+ // ... (postprocessing code)
120
+ };
121
+ });
122
+ }
123
+
124
+ loadAndColorize();
125
+ </script>
126
+ </body>
127
+ </html>
128
+ ```
129
+
130
+ For a complete working example, see the [browser directory](https://github.com/thookham/DeOldify/tree/master/browser) in the GitHub repository.
131
+
132
+ ## Model Selection Guide
133
+
134
+ ### Artistic Model
135
+ - **Best for**: General historical photos, artistic colorization
136
+ - **Pros**: Most vibrant colors, interesting details
137
+ - **Cons**: May require `render_factor` tuning
138
+ - **Files**: `ColorizeArtistic_gen.pth`, `deoldify-art.onnx`
139
+
140
+ ```python
141
+ colorizer = get_image_colorizer(artistic=True)
142
+ ```
143
+
144
+ ### Stable Model
145
+ - **Best for**: Portraits, landscapes
146
+ - **Pros**: More consistent, less artifacts
147
+ - **Cons**: Slightly less colorful than Artistic
148
+ - **Files**: `ColorizeStable_gen.pth`
149
+
150
+ ```python
151
+ colorizer = get_image_colorizer(artistic=False)
152
+ ```
153
+
154
+ ### Video Model
155
+ - **Best for**: Video colorization
156
+ - **Pros**: Flicker-free, temporally consistent
157
+ - **Cons**: Least colorful of the three
158
+ - **Files**: `ColorizeVideo_gen.pth`
159
+
160
+ ```python
161
+ from deoldify.visualize import get_video_colorizer
162
+ video_colorizer = get_video_colorizer()
163
+ ```
164
+
165
+ ## Advanced Usage
166
+
167
+ ### Custom Render Factor
168
+
169
+ The `render_factor` parameter controls quality vs speed:
170
+
171
+ ```python
172
+ # Low quality, fast (good for testing)
173
+ result = colorizer.get_transformed_image(path="photo.jpg", render_factor=10)
174
+
175
+ # High quality, slow (best results)
176
+ result = colorizer.get_transformed_image(path="photo.jpg", render_factor=45)
177
+
178
+ # Recommended range: 20-40
179
+ ```
180
+
181
+ ### Using Critic Weights (Training)
182
+
183
+ If you want to continue training the models:
184
+
185
+ ```python
186
+ from huggingface_hub import hf_hub_download
187
+
188
+ # Download both generator and critic
189
+ gen_path = hf_hub_download(repo_id="thookham/DeOldify", filename="ColorizeArtistic_gen.pth")
190
+ crit_path = hf_hub_download(repo_id="thookham/DeOldify", filename="ColorizeArtistic_crit.pth")
191
+
192
+ # Load for training (see full documentation in GitHub repo)
193
+ ```
194
+
195
+ ## Troubleshooting
196
+
197
+ ### "CUDA out of memory"
198
+ - Reduce `render_factor`
199
+ - Process smaller images
200
+ - Close other GPU applications
201
+
202
+ ### "Module 'deoldify' not found"
203
+ - Install the DeOldify package: Clone the repo and run `pip install -e .`
204
+
205
+ ### Colors look unrealistic
206
+ - Try the Stable model instead of Artistic
207
+ - Adjust `render_factor` (try values between 20-40)
208
+ - Some images may not colorize well due to damage or low quality
209
+
210
+ ## Additional Resources
211
+
212
+ - **GitHub Repository**: https://github.com/thookham/DeOldify
213
+ - **Setup Guides**:
214
+ - [NVIDIA GPU Setup](nvidia_setup.md)
215
+ - [Intel GPU Setup](intel_gpu_setup.md)
216
+ - **Model Weights**: All available in this HF repository
217
+ - **Browser Demo**: See `browser/` folder in GitHub repo
218
+
219
+ ## Citation
220
+
221
+ ```bibtex
222
+ @misc{deoldify,
223
+ author = {Antic, Jason},
224
+ title = {DeOldify},
225
+ year = {2019},
226
+ publisher = {GitHub},
227
+ url = {https://github.com/jantic/DeOldify}
228
+ }
229
+ ```
VideoColorizer.ipynb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:210afc44086ef08697fdad1aeb6bd5fd526ae5b62c481cacf356fed395291b12
3
+ size 6339
VideoColorizerColab.ipynb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:598bf87dac7f678cbefc0da31e7e4c9be1d064d42e69bec39482f5509c755daa
3
+ size 9945
akbartus_tree.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"sha":"43107c240f063d559708abc7639cd9f6d844458e","url":"https://api.github.com/repos/akbartus/DeOldify-on-Browser/git/trees/43107c240f063d559708abc7639cd9f6d844458e","tree":[{"path":"LICENSE","mode":"100644","type":"blob","sha":"6d6cdac91b8f30bc0065d6b52437b578aff18b8b","size":1065,"url":"https://api.github.com/repos/akbartus/DeOldify-on-Browser/git/blobs/6d6cdac91b8f30bc0065d6b52437b578aff18b8b"},{"path":"README.md","mode":"100644","type":"blob","sha":"88035e0eaf1d82b0b21fa5e85b151573164aaee5","size":3246,"url":"https://api.github.com/repos/akbartus/DeOldify-on-Browser/git/blobs/88035e0eaf1d82b0b21fa5e85b151573164aaee5"},{"path":"img","mode":"040000","type":"tree","sha":"d3334306495bd32f52658b5997399a34b89d33d6","url":"https://api.github.com/repos/akbartus/DeOldify-on-Browser/git/trees/d3334306495bd32f52658b5997399a34b89d33d6"},{"path":"img/screenshot.jpg","mode":"100644","type":"blob","sha":"3f5d6c0f9bdc3bd5f8090ecc10d86ad7c4519a5f","size":107506,"url":"https://api.github.com/repos/akbartus/DeOldify-on-Browser/git/blobs/3f5d6c0f9bdc3bd5f8090ecc10d86ad7c4519a5f"},{"path":"original","mode":"040000","type":"tree","sha":"4c8d377f4859a977493cf7174755ebcf73953337","url":"https://api.github.com/repos/akbartus/DeOldify-on-Browser/git/trees/4c8d377f4859a977493cf7174755ebcf73953337"},{"path":"original/index.html","mode":"100644","type":"blob","sha":"da12505e7ff992903c4669556188316e9934f393","size":4281,"url":"https://api.github.com/repos/akbartus/DeOldify-on-Browser/git/blobs/da12505e7ff992903c4669556188316e9934f393"},{"path":"quantized","mode":"040000","type":"tree","sha":"c02b79e9adb2e6204d3724812c0e498e544fc778","url":"https://api.github.com/repos/akbartus/DeOldify-on-Browser/git/trees/c02b79e9adb2e6204d3724812c0e498e544fc778"},{"path":"quantized/index.html","mode":"100644","type":"blob","sha":"35582686f88fbc863208251531c9471e295cc50b","size":5855,"url":"https://api.github.com/repos/akbartus/DeOldify-on-Browser/git/blobs/35582686f88fbc863208251531c9471e295cc50b"}],"truncated":false}
assets.txt ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ColorizeArtistic_crit.pth
2
+ ColorizeArtistic_gen.pth
3
+ ColorizeArtistic_PretrainOnly_crit.pth
4
+ ColorizeArtistic_PretrainOnly_gen.pth
5
+ ColorizeStable_crit.pth
6
+ ColorizeStable_gen.pth
7
+ ColorizeStable_PretrainOnly_crit.pth
8
+ ColorizeStable_PretrainOnly_gen.pth.000
9
+ ColorizeStable_PretrainOnly_gen.pth.001
10
+ ColorizeVideo_crit.pth
11
+ ColorizeVideo_gen.pth
12
+ ColorizeVideo_PretrainOnly_crit.pth
13
+ ColorizeVideo_PretrainOnly_gen.pth.000
14
+ ColorizeVideo_PretrainOnly_gen.pth.001
15
+ deoldify-art.onnx
16
+ deoldify-quant.onnx
browser/README.md ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DeOldify Browser Integration
2
+
3
+ This directory contains a browser-based implementation of DeOldify using ONNX Runtime Web. It allows you to run colorization models directly in your web browser without a backend server (after the model is downloaded).
4
+
5
+ ## ⚠️ Important: How to Run
6
+
7
+ Due to browser security policies (CORS), **you cannot simply double-click the HTML files** to run them. You must serve them via a local HTTP server.
8
+
9
+ ### Quick Start (Windows/Linux/Mac)
10
+
11
+ If you have Python installed (which is likely if you're using DeOldify), simply run:
12
+
13
+ ```bash
14
+ # Run this command in your terminal within this directory
15
+ python -m http.server 8000
16
+ ```
17
+
18
+ Then open your browser and visit:
19
+ * [http://localhost:8000](http://localhost:8000)
20
+
21
+ ### Using the Helper Script (Windows)
22
+
23
+ We've provided a PowerShell script to make this easy:
24
+
25
+ 1. Right-click `serve.ps1` and select "Run with PowerShell"
26
+ 2. Or run it from the terminal: `.\serve.ps1`
27
+
28
+ ## Available Models
29
+
30
+ * **Artistic Model**: High quality, vibrant colors. Larger download (~243 MB).
31
+ * **Quantized Model**: Faster, smaller download (~61 MB), slightly lower quality.
32
+
33
+ ## Troubleshooting
34
+
35
+ **"Failed to fetch" or CORS Errors:**
36
+ If you see an error about CORS or "Failed to fetch" in the status log, it means you are likely trying to open the file directly (`file:///...`). Please use the HTTP server method described above.
37
+
38
+ **Memory Issues:**
39
+ The artistic model requires a significant amount of RAM. If the tab crashes, try closing other tabs or using the Quantized model.
browser/artistic.html ADDED
@@ -0,0 +1,247 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>DeOldify Artistic (Browser)</title>
8
+ <script src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js"></script>
9
+ <style>
10
+ body {
11
+ font-family: sans-serif;
12
+ max-width: 800px;
13
+ margin: 0 auto;
14
+ padding: 20px;
15
+ }
16
+
17
+ h1 {
18
+ text-align: center;
19
+ }
20
+
21
+ .container {
22
+ display: flex;
23
+ flex-direction: column;
24
+ align-items: center;
25
+ gap: 20px;
26
+ }
27
+
28
+ canvas {
29
+ border: 1px solid #ccc;
30
+ max-width: 100%;
31
+ }
32
+
33
+ .controls {
34
+ margin-bottom: 20px;
35
+ }
36
+
37
+ #status {
38
+ font-weight: bold;
39
+ margin-top: 10px;
40
+ }
41
+ </style>
42
+ </head>
43
+
44
+ <body>
45
+ <h1>DeOldify Artistic Model</h1>
46
+ <div class="container">
47
+ <div class="controls">
48
+ <input type="file" id="imageInput" accept="image/*" />
49
+ </div>
50
+ <div id="status">Select an image to start...</div>
51
+ <canvas id="outputCanvas"></canvas>
52
+ </div>
53
+
54
+ <script>
55
+ const MODEL_URL = "https://huggingface.co/thookham/DeOldify-on-Browser/resolve/main/deoldify-art.onnx";
56
+ let session = null;
57
+
58
+ const preprocess = (input_imageData, width, height) => {
59
+ const floatArr = new Float32Array(width * height * 3);
60
+ let j = 0;
61
+ for (let i = 0; i < input_imageData.data.length; i += 4) {
62
+ // Normalize to 0-1 range as expected by DeOldify
63
+ floatArr[j] = input_imageData.data[i] / 255.0; // red
64
+ floatArr[j + 1] = input_imageData.data[i + 1] / 255.0; // green
65
+ floatArr[j + 2] = input_imageData.data[i + 2] / 255.0; // blue
66
+ j += 3;
67
+ }
68
+ return floatArr;
69
+ };
70
+
71
+ const postprocess = (tensor) => {
72
+ const channels = tensor.dims[1];
73
+ const height = tensor.dims[2];
74
+ const width = tensor.dims[3];
75
+ const imageData = new ImageData(width, height);
76
+ const data = imageData.data;
77
+ const tensorData = new Float32Array(tensor.data);
78
+
79
+ for (let h = 0; h < height; h++) {
80
+ for (let w = 0; w < width; w++) {
81
+ let rgb = [];
82
+ for (let c = 0; c < channels; c++) {
83
+ const tensorIndex = (c * height + h) * width + w;
84
+ const value = tensorData[tensorIndex];
85
+ // Denormalize: multiply by 255 and clamp
86
+ let val = value * 255.0;
87
+ if (val < 0) val = 0;
88
+ if (val > 255) val = 255;
89
+ rgb.push(Math.round(val));
90
+ }
91
+ data[(h * width + w) * 4] = rgb[0];
92
+ data[(h * width + w) * 4 + 1] = rgb[1];
93
+ data[(h * width + w) * 4 + 2] = rgb[2];
94
+ data[(h * width + w) * 4 + 3] = 255;
95
+ }
96
+ }
97
+ return imageData;
98
+ };
99
+
100
+ async function init() {
101
+ const status = document.getElementById('status');
102
+ status.innerText = "Checking cache...";
103
+ try {
104
+ let buffer;
105
+ const cacheName = 'deoldify-models-v1';
106
+
107
+ // Try to load from cache first
108
+ try {
109
+ const cache = await caches.open(cacheName);
110
+ const cachedResponse = await cache.match(MODEL_URL);
111
+
112
+ if (cachedResponse) {
113
+ status.innerText = "Loading model from cache...";
114
+ const blob = await cachedResponse.blob();
115
+ buffer = await blob.arrayBuffer();
116
+ }
117
+ } catch (e) {
118
+ console.warn("Cache API not supported or failed:", e);
119
+ }
120
+
121
+ // If not in cache, download it
122
+ if (!buffer) {
123
+ status.innerText = "Downloading model from Hugging Face... 0%";
124
+ const response = await fetch(MODEL_URL);
125
+ if (!response.ok) throw new Error(`Failed to fetch model: ${response.statusText}`);
126
+
127
+ const contentLength = response.headers.get('content-length');
128
+ const total = contentLength ? parseInt(contentLength, 10) : 0;
129
+ let loaded = 0;
130
+
131
+ const reader = response.body.getReader();
132
+ const chunks = [];
133
+
134
+ while (true) {
135
+ const { done, value } = await reader.read();
136
+ if (done) break;
137
+ chunks.push(value);
138
+ loaded += value.length;
139
+ if (total) {
140
+ const progress = Math.round((loaded / total) * 100);
141
+ status.innerText = `Downloading model from Hugging Face... ${progress}%`;
142
+ } else {
143
+ status.innerText = `Downloading model from Hugging Face... ${(loaded / 1024 / 1024).toFixed(1)} MB`;
144
+ }
145
+ }
146
+
147
+ const blob = new Blob(chunks);
148
+ buffer = await blob.arrayBuffer();
149
+
150
+ // Save to cache for next time
151
+ try {
152
+ const cache = await caches.open(cacheName);
153
+ await cache.put(MODEL_URL, new Response(blob));
154
+ console.log("Model saved to cache");
155
+ } catch (e) {
156
+ console.warn("Failed to save to cache:", e);
157
+ }
158
+ }
159
+
160
+ status.innerText = "Initializing session...";
161
+ session = await ort.InferenceSession.create(buffer);
162
+
163
+ status.innerText = "Model loaded! Select an image.";
164
+ console.log("Session created:", session);
165
+ } catch (e) {
166
+ status.innerText = "Error loading model: " + e.message;
167
+ console.error(e);
168
+ if (e.message.includes("Failed to fetch")) {
169
+ status.innerHTML += "<br><br>⚠️ <b>CORS Error Detected</b>: If you are running this file directly (file://), you must use a local server.<br>Run <code>python -m http.server 8000</code> in the terminal and visit <code>http://localhost:8000/artistic.html</code>";
170
+ }
171
+ }
172
+ }
173
+
174
+ document.getElementById('imageInput').addEventListener('change', async function (e) {
175
+ if (!session) {
176
+ await init();
177
+ }
178
+
179
+ const file = e.target.files[0];
180
+ if (!file) return;
181
+
182
+ // Validate image type
183
+ if (!file.type.startsWith('image/')) {
184
+ alert('Please select a valid image file.');
185
+ return;
186
+ }
187
+
188
+ const image = new Image();
189
+ const objectUrl = URL.createObjectURL(file);
190
+ image.src = objectUrl;
191
+
192
+ image.onload = async function () {
193
+ document.getElementById('status').innerText = "Processing...";
194
+
195
+ // Pre-processing canvas (256x256)
196
+ let canvas = document.createElement("canvas");
197
+ const size = 256;
198
+ canvas.width = size;
199
+ canvas.height = size;
200
+ let ctx = canvas.getContext("2d");
201
+ ctx.drawImage(image, 0, 0, size, size);
202
+
203
+ const input_img = ctx.getImageData(0, 0, size, size);
204
+ const test = preprocess(input_img, size, size);
205
+ const input = new ort.Tensor(new Float32Array(test), [1, 3, size, size]);
206
+
207
+ try {
208
+ const result = await session.run({ "input": input });
209
+ // Handle potential output name differences
210
+ const output = result["output"] || result["out"] || Object.values(result)[0];
211
+
212
+ if (!output) throw new Error("No output tensor found in model result");
213
+
214
+ const imgdata = postprocess(output);
215
+
216
+ // Render to output canvas
217
+ const outCanvas = document.getElementById('outputCanvas');
218
+ outCanvas.width = image.width;
219
+ outCanvas.height = image.height;
220
+ const outCtx = outCanvas.getContext('2d');
221
+
222
+ // Draw 256x256 result to temp canvas
223
+ const tempCanvas = document.createElement('canvas');
224
+ tempCanvas.width = size;
225
+ tempCanvas.height = size;
226
+ tempCanvas.getContext('2d').putImageData(imgdata, 0, 0);
227
+
228
+ // Resize to original
229
+ outCtx.drawImage(tempCanvas, 0, 0, image.width, image.height);
230
+
231
+ document.getElementById('status').innerText = "Done!";
232
+ } catch (err) {
233
+ document.getElementById('status').innerText = "Error processing: " + err.message;
234
+ console.error(err);
235
+ } finally {
236
+ // Clean up memory
237
+ URL.revokeObjectURL(objectUrl);
238
+ }
239
+ };
240
+ });
241
+
242
+ // Start loading immediately
243
+ init();
244
+ </script>
245
+ </body>
246
+
247
+ </html>
browser/index.html ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>DeOldify Browser Integration</title>
8
+ <style>
9
+ body {
10
+ font-family: sans-serif;
11
+ max-width: 600px;
12
+ margin: 0 auto;
13
+ padding: 40px;
14
+ text-align: center;
15
+ }
16
+
17
+ h1 {
18
+ margin-bottom: 30px;
19
+ }
20
+
21
+ .card {
22
+ border: 1px solid #ddd;
23
+ border-radius: 8px;
24
+ padding: 20px;
25
+ margin-bottom: 20px;
26
+ transition: transform 0.2s;
27
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
28
+ }
29
+
30
+ .card:hover {
31
+ transform: translateY(-2px);
32
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
33
+ }
34
+
35
+ a {
36
+ text-decoration: none;
37
+ color: inherit;
38
+ display: block;
39
+ }
40
+
41
+ h2 {
42
+ margin-top: 0;
43
+ color: #007bff;
44
+ }
45
+
46
+ p {
47
+ color: #666;
48
+ }
49
+ </style>
50
+ </head>
51
+
52
+ <body>
53
+ <h1>DeOldify Browser Integration</h1>
54
+ <p>Run DeOldify directly in your browser using ONNX models hosted on GitHub.</p>
55
+
56
+ <a href="artistic.html">
57
+ <div class="card">
58
+ <h2>Artistic Model</h2>
59
+ <p>High quality, vibrant colors. (243 MB download)</p>
60
+ </div>
61
+ </a>
62
+
63
+ <a href="quantized.html">
64
+ <div class="card">
65
+ <h2>Quantized Model</h2>
66
+ <p>Faster, lightweight. (61 MB download)</p>
67
+ </div>
68
+ </a>
69
+ </body>
70
+
71
+ </html>
browser/quantized.html ADDED
@@ -0,0 +1,248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>DeOldify Quantized (Browser)</title>
8
+ <script src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js"></script>
9
+ <style>
10
+ body {
11
+ font-family: sans-serif;
12
+ max-width: 800px;
13
+ margin: 0 auto;
14
+ padding: 20px;
15
+ }
16
+
17
+ h1 {
18
+ text-align: center;
19
+ }
20
+
21
+ .container {
22
+ display: flex;
23
+ flex-direction: column;
24
+ align-items: center;
25
+ gap: 20px;
26
+ }
27
+
28
+ canvas {
29
+ border: 1px solid #ccc;
30
+ max-width: 100%;
31
+ }
32
+
33
+ .controls {
34
+ margin-bottom: 20px;
35
+ }
36
+
37
+ #status {
38
+ font-weight: bold;
39
+ margin-top: 10px;
40
+ }
41
+ </style>
42
+ </head>
43
+
44
+ <body>
45
+ <h1>DeOldify Quantized Model</h1>
46
+ <p style="text-align: center;">Faster, smaller download (61MB), slightly lower quality.</p>
47
+ <div class="container">
48
+ <div class="controls">
49
+ <input type="file" id="imageInput" accept="image/*" />
50
+ </div>
51
+ <div id="status">Select an image to start...</div>
52
+ <canvas id="outputCanvas"></canvas>
53
+ </div>
54
+
55
+ <script>
56
+ const MODEL_URL = "https://huggingface.co/thookham/DeOldify-on-Browser/resolve/main/deoldify-quant.onnx";
57
+ let session = null;
58
+
59
+ const preprocess = (input_imageData, width, height) => {
60
+ const floatArr = new Float32Array(width * height * 3);
61
+ let j = 0;
62
+ for (let i = 0; i < input_imageData.data.length; i += 4) {
63
+ // Normalize to 0-1 range as expected by DeOldify
64
+ floatArr[j] = input_imageData.data[i] / 255.0; // red
65
+ floatArr[j + 1] = input_imageData.data[i + 1] / 255.0; // green
66
+ floatArr[j + 2] = input_imageData.data[i + 2] / 255.0; // blue
67
+ j += 3;
68
+ }
69
+ return floatArr;
70
+ };
71
+
72
+ const postprocess = (tensor) => {
73
+ const channels = tensor.dims[1];
74
+ const height = tensor.dims[2];
75
+ const width = tensor.dims[3];
76
+ const imageData = new ImageData(width, height);
77
+ const data = imageData.data;
78
+ const tensorData = new Float32Array(tensor.data);
79
+
80
+ for (let h = 0; h < height; h++) {
81
+ for (let w = 0; w < width; w++) {
82
+ let rgb = [];
83
+ for (let c = 0; c < channels; c++) {
84
+ const tensorIndex = (c * height + h) * width + w;
85
+ const value = tensorData[tensorIndex];
86
+ // Denormalize: multiply by 255 and clamp
87
+ let val = value * 255.0;
88
+ if (val < 0) val = 0;
89
+ if (val > 255) val = 255;
90
+ rgb.push(Math.round(val));
91
+ }
92
+ data[(h * width + w) * 4] = rgb[0];
93
+ data[(h * width + w) * 4 + 1] = rgb[1];
94
+ data[(h * width + w) * 4 + 2] = rgb[2];
95
+ data[(h * width + w) * 4 + 3] = 255;
96
+ }
97
+ }
98
+ return imageData;
99
+ };
100
+
101
+ async function init() {
102
+ const status = document.getElementById('status');
103
+ status.innerText = "Checking cache...";
104
+ try {
105
+ let buffer;
106
+ const cacheName = 'deoldify-models-v1';
107
+
108
+ // Try to load from cache first
109
+ try {
110
+ const cache = await caches.open(cacheName);
111
+ const cachedResponse = await cache.match(MODEL_URL);
112
+
113
+ if (cachedResponse) {
114
+ status.innerText = "Loading model from cache...";
115
+ const blob = await cachedResponse.blob();
116
+ buffer = await blob.arrayBuffer();
117
+ }
118
+ } catch (e) {
119
+ console.warn("Cache API not supported or failed:", e);
120
+ }
121
+
122
+ // If not in cache, download it
123
+ if (!buffer) {
124
+ status.innerText = "Downloading model from Hugging Face... 0%";
125
+ const response = await fetch(MODEL_URL);
126
+ if (!response.ok) throw new Error(`Failed to fetch model: ${response.statusText}`);
127
+
128
+ const contentLength = response.headers.get('content-length');
129
+ const total = contentLength ? parseInt(contentLength, 10) : 0;
130
+ let loaded = 0;
131
+
132
+ const reader = response.body.getReader();
133
+ const chunks = [];
134
+
135
+ while (true) {
136
+ const { done, value } = await reader.read();
137
+ if (done) break;
138
+ chunks.push(value);
139
+ loaded += value.length;
140
+ if (total) {
141
+ const progress = Math.round((loaded / total) * 100);
142
+ status.innerText = `Downloading model from Hugging Face... ${progress}%`;
143
+ } else {
144
+ status.innerText = `Downloading model from Hugging Face... ${(loaded / 1024 / 1024).toFixed(1)} MB`;
145
+ }
146
+ }
147
+
148
+ const blob = new Blob(chunks);
149
+ buffer = await blob.arrayBuffer();
150
+
151
+ // Save to cache for next time
152
+ try {
153
+ const cache = await caches.open(cacheName);
154
+ await cache.put(MODEL_URL, new Response(blob));
155
+ console.log("Model saved to cache");
156
+ } catch (e) {
157
+ console.warn("Failed to save to cache:", e);
158
+ }
159
+ }
160
+
161
+ status.innerText = "Initializing session...";
162
+ session = await ort.InferenceSession.create(buffer);
163
+
164
+ status.innerText = "Model loaded! Select an image.";
165
+ console.log("Session created:", session);
166
+ } catch (e) {
167
+ status.innerText = "Error loading model: " + e.message;
168
+ console.error(e);
169
+ if (e.message.includes("Failed to fetch")) {
170
+ status.innerHTML += "<br><br>⚠️ <b>CORS Error Detected</b>: If you are running this file directly (file://), you must use a local server.<br>Run <code>python -m http.server 8000</code> in the terminal and visit <code>http://localhost:8000/quantized.html</code>";
171
+ }
172
+ }
173
+ }
174
+
175
+ document.getElementById('imageInput').addEventListener('change', async function (e) {
176
+ if (!session) {
177
+ await init();
178
+ }
179
+
180
+ const file = e.target.files[0];
181
+ if (!file) return;
182
+
183
+ // Validate image type
184
+ if (!file.type.startsWith('image/')) {
185
+ alert('Please select a valid image file.');
186
+ return;
187
+ }
188
+
189
+ const image = new Image();
190
+ const objectUrl = URL.createObjectURL(file);
191
+ image.src = objectUrl;
192
+
193
+ image.onload = async function () {
194
+ document.getElementById('status').innerText = "Processing...";
195
+
196
+ // Pre-processing canvas (256x256)
197
+ let canvas = document.createElement("canvas");
198
+ const size = 256;
199
+ canvas.width = size;
200
+ canvas.height = size;
201
+ let ctx = canvas.getContext("2d");
202
+ ctx.drawImage(image, 0, 0, size, size);
203
+
204
+ const input_img = ctx.getImageData(0, 0, size, size);
205
+ const test = preprocess(input_img, size, size);
206
+ const input = new ort.Tensor(new Float32Array(test), [1, 3, size, size]);
207
+
208
+ try {
209
+ const result = await session.run({ "input": input });
210
+ // Handle potential output name differences
211
+ const output = result["output"] || result["out"] || Object.values(result)[0];
212
+
213
+ if (!output) throw new Error("No output tensor found in model result");
214
+
215
+ const imgdata = postprocess(output);
216
+
217
+ // Render to output canvas
218
+ const outCanvas = document.getElementById('outputCanvas');
219
+ outCanvas.width = image.width;
220
+ outCanvas.height = image.height;
221
+ const outCtx = outCanvas.getContext('2d');
222
+
223
+ // Draw 256x256 result to temp canvas
224
+ const tempCanvas = document.createElement('canvas');
225
+ tempCanvas.width = size;
226
+ tempCanvas.height = size;
227
+ tempCanvas.getContext('2d').putImageData(imgdata, 0, 0);
228
+
229
+ // Resize to original
230
+ outCtx.drawImage(tempCanvas, 0, 0, image.width, image.height);
231
+
232
+ document.getElementById('status').innerText = "Done!";
233
+ } catch (err) {
234
+ document.getElementById('status').innerText = "Error processing: " + err.message;
235
+ console.error(err);
236
+ } finally {
237
+ // Clean up memory
238
+ URL.revokeObjectURL(objectUrl);
239
+ }
240
+ };
241
+ });
242
+
243
+ // Start loading immediately
244
+ init();
245
+ </script>
246
+ </body>
247
+
248
+ </html>
browser/serve.ps1 ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Simple script to serve the DeOldify project root and open the browser
2
+ Write-Host "Starting local server for DeOldify Browser..." -ForegroundColor Cyan
3
+ Write-Host "Press Ctrl+C to stop the server." -ForegroundColor Yellow
4
+
5
+ # Get the root directory (parent of the script's directory)
6
+ $scriptPath = $MyInvocation.MyCommand.Path
7
+ $browserDir = Split-Path $scriptPath
8
+ $rootDir = Split-Path $browserDir
9
+
10
+ # Change to root directory
11
+ Set-Location $rootDir
12
+ Write-Host "Serving from: $rootDir" -ForegroundColor Gray
13
+
14
+ # Start the server in the background
15
+ $process = Start-Process -FilePath "python" -ArgumentList "-m http.server 8000" -PassThru
16
+
17
+ # Wait a moment for it to start
18
+ Start-Sleep -Seconds 2
19
+
20
+ # Open the browser to the artistic page
21
+ Start-Process "http://localhost:8000/browser/artistic.html"
22
+
23
+ # Wait for the user to close the script
24
+ Read-Host "Server is running. Press Enter to stop server and exit..."
25
+
26
+ # Stop the server
27
+ Stop-Process -Id $process.Id
check_remote_models.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ import json
3
+ import base64
4
+ import re
5
+
6
+ def check_repo_file(repo, path):
7
+ cmd = ["gh", "api", f"repos/{repo}/contents/{path}", "--jq", ".content"]
8
+ try:
9
+ result = subprocess.run(cmd, capture_output=True, text=True, check=True)
10
+ content_b64 = result.stdout.strip()
11
+ content = base64.b64decode(content_b64).decode('utf-8')
12
+
13
+ print(f"--- Checking {repo}/{path} ---")
14
+ # Search for .onnx or .pth links
15
+ urls = re.findall(r'https?://[^\s"\'<>]+(?:\.onnx|\.pth)', content)
16
+ for url in urls:
17
+ print(f"Found URL: {url}")
18
+
19
+ except subprocess.CalledProcessError as e:
20
+ print(f"Error fetching {path}: {e}")
21
+ except Exception as e:
22
+ print(f"Error processing {path}: {e}")
23
+
24
+ repos = ["thookham/DeOldify-on-Browser", "akbartus/DeOldify-on-Browser"]
25
+ files = ["original/index.html", "quantized/index.html"]
26
+
27
+ for repo in repos:
28
+ for file in files:
29
+ check_repo_file(repo, file)
check_remote_models_v2.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ import json
3
+ import base64
4
+ import re
5
+
6
+ def check_repo_file(repo, path):
7
+ cmd = ["gh", "api", f"repos/{repo}/contents/{path}", "--jq", ".content"]
8
+ try:
9
+ result = subprocess.run(cmd, capture_output=True, text=True, check=True)
10
+ content_b64 = result.stdout.strip()
11
+ content = base64.b64decode(content_b64).decode('utf-8')
12
+
13
+ urls = re.findall(r'https?://[^\s"\'<>]+(?:\.onnx|\.pth)', content)
14
+ return urls
15
+
16
+ except Exception as e:
17
+ return []
18
+
19
+ repos = ["thookham/DeOldify-on-Browser"]
20
+ files = ["original/index.html", "quantized/index.html"]
21
+
22
+ all_urls = []
23
+ for repo in repos:
24
+ for file in files:
25
+ urls = check_repo_file(repo, file)
26
+ all_urls.extend(urls)
27
+
28
+ with open("found_urls.txt", "w") as f:
29
+ for url in all_urls:
30
+ f.write(url + "\n")
compare_models.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import hashlib
2
+ import requests
3
+ import os
4
+
5
+ def get_file_hash(filepath):
6
+ sha256_hash = hashlib.sha256()
7
+ with open(filepath, "rb") as f:
8
+ for byte_block in iter(lambda: f.read(4096), b""):
9
+ sha256_hash.update(byte_block)
10
+ return sha256_hash.hexdigest()
11
+
12
+ def download_file(url, filename):
13
+ print(f"Downloading {url}...")
14
+ r = requests.get(url, stream=True)
15
+ with open(filename, 'wb') as f:
16
+ for chunk in r.iter_content(chunk_size=8192):
17
+ f.write(chunk)
18
+ return filename
19
+
20
+ external_urls = {
21
+ "glitch_art.onnx": "https://huggingface.co/thookham/DeOldify-on-Browser/resolve/main/deoldify-art.onnx",
22
+ "glitch_quant.onnx": "https://huggingface.co/thookham/DeOldify-on-Browser/resolve/main/deoldify-quant.onnx"
23
+ }
24
+
25
+ # Local files
26
+ local_files = {
27
+ "local_art.onnx": "models/deoldify-art.onnx",
28
+ "local_quant.onnx": "models/deoldify-quant.onnx"
29
+ }
30
+
31
+ print("--- Local File Hashes ---")
32
+ for name, path in local_files.items():
33
+ if os.path.exists(path):
34
+ print(f"{name}: {get_file_hash(path)}")
35
+ else:
36
+ print(f"{name}: File not found")
37
+
38
+ print("\n--- External File Hashes ---")
39
+ for name, url in external_urls.items():
40
+ try:
41
+ download_file(url, name)
42
+ print(f"{name}: {get_file_hash(name)}")
43
+ except Exception as e:
44
+ print(f"Error downloading {name}: {e}")
deoldify/__init__.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ import logging
3
+ logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))
4
+ logging.getLogger().setLevel(logging.INFO)
5
+
6
+ from deoldify._device import _Device
7
+
8
+ device = _Device()
deoldify/_device.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ from enum import Enum
4
+ from .device_id import DeviceId
5
+ import logging
6
+
7
+ #NOTE: This must be called first before any torch imports in order to work properly!
8
+
9
+ class DeviceException(Exception):
10
+ pass
11
+
12
+ class _Device:
13
+ def __init__(self):
14
+ self._current_device = DeviceId.CPU
15
+ self._backend = 'cpu'
16
+ self._init_device()
17
+
18
+ def _init_device(self):
19
+ # Check for Intel Extension for PyTorch
20
+ try:
21
+ import intel_extension_for_pytorch as ipex
22
+ if torch.xpu.is_available():
23
+ self._backend = 'xpu'
24
+ return
25
+ except ImportError:
26
+ pass
27
+
28
+ # Check for CUDA
29
+ if torch.cuda.is_available():
30
+ self._backend = 'cuda'
31
+ return
32
+
33
+ self._backend = 'cpu'
34
+
35
+ def is_gpu(self):
36
+ ''' Returns `True` if the current device is GPU (CUDA or XPU), `False` otherwise. '''
37
+ return self.current() is not DeviceId.CPU
38
+
39
+ def current(self):
40
+ return self._current_device
41
+
42
+ def set(self, device:DeviceId):
43
+ if device == DeviceId.CPU:
44
+ os.environ['CUDA_VISIBLE_DEVICES']=''
45
+ self._current_device = DeviceId.CPU
46
+ else:
47
+ # Handle GPU selection
48
+ if self._backend == 'cuda':
49
+ os.environ['CUDA_VISIBLE_DEVICES']=str(device.value)
50
+ torch.backends.cudnn.benchmark=True
51
+ elif self._backend == 'xpu':
52
+ # For XPU, we might need different env vars or just rely on index
53
+ # Currently just setting the device ID
54
+ pass
55
+
56
+ self._current_device = device
57
+
58
+ return device
59
+
60
+ def get_torch_device(self):
61
+ if self._current_device == DeviceId.CPU:
62
+ return torch.device('cpu')
63
+
64
+ if self._backend == 'cuda':
65
+ return torch.device('cuda')
66
+ elif self._backend == 'xpu':
67
+ return torch.device('xpu')
68
+
69
+ return torch.device('cpu')
deoldify/augs.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import random
2
+
3
+ from fastai.vision.image import TfmPixel
4
+
5
+ # Contributed by Rani Horev. Thank you!
6
+ def _noisify(
7
+ x, pct_pixels_min: float = 0.001, pct_pixels_max: float = 0.4, noise_range: int = 30
8
+ ):
9
+ if noise_range > 255 or noise_range < 0:
10
+ raise Exception("noise_range must be between 0 and 255, inclusively.")
11
+
12
+ h, w = x.shape[1:]
13
+ img_size = h * w
14
+ mult = 10000.0
15
+ pct_pixels = (
16
+ random.randrange(int(pct_pixels_min * mult), int(pct_pixels_max * mult)) / mult
17
+ )
18
+ noise_count = int(img_size * pct_pixels)
19
+
20
+ for ii in range(noise_count):
21
+ yy = random.randrange(h)
22
+ xx = random.randrange(w)
23
+ noise = random.randrange(-noise_range, noise_range) / 255.0
24
+ x[:, yy, xx].add_(noise)
25
+
26
+ return x
27
+
28
+
29
+ noisify = TfmPixel(_noisify)
deoldify/critics.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastai.basic_train import Learner
2
+ from fastai.core import *
3
+ from fastai.layers import NormType, conv_layer
4
+ from fastai.torch_core import *
5
+ from fastai.vision import *
6
+ from fastai.vision.data import ImageDataBunch
7
+ from fastai.vision.gan import AdaptiveLoss, accuracy_thresh_expand
8
+
9
+ _conv_args = dict(leaky=0.2, norm_type=NormType.Spectral)
10
+
11
+
12
+ def _conv(ni: int, nf: int, ks: int = 3, stride: int = 1, **kwargs):
13
+ return conv_layer(ni, nf, ks=ks, stride=stride, **_conv_args, **kwargs)
14
+
15
+
16
+ def custom_gan_critic(
17
+ n_channels: int = 3, nf: int = 256, n_blocks: int = 3, p: int = 0.15
18
+ ):
19
+ "Critic to train a `GAN`."
20
+ layers = [_conv(n_channels, nf, ks=4, stride=2), nn.Dropout2d(p / 2)]
21
+ for i in range(n_blocks):
22
+ layers += [
23
+ _conv(nf, nf, ks=3, stride=1),
24
+ nn.Dropout2d(p),
25
+ _conv(nf, nf * 2, ks=4, stride=2, self_attention=(i == 0)),
26
+ ]
27
+ nf *= 2
28
+ layers += [
29
+ _conv(nf, nf, ks=3, stride=1),
30
+ _conv(nf, 1, ks=4, bias=False, padding=0, use_activ=False),
31
+ Flatten(),
32
+ ]
33
+ return nn.Sequential(*layers)
34
+
35
+
36
+ def colorize_crit_learner(
37
+ data: ImageDataBunch,
38
+ loss_critic=AdaptiveLoss(nn.BCEWithLogitsLoss()),
39
+ nf: int = 256,
40
+ ) -> Learner:
41
+ return Learner(
42
+ data,
43
+ custom_gan_critic(nf=nf),
44
+ metrics=accuracy_thresh_expand,
45
+ loss_func=loss_critic,
46
+ wd=1e-3,
47
+ )
deoldify/dataset.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .fastai_compat import *
2
+
3
+ # Training data loading logic is currently disabled due to FastAI 1.x deprecation.
4
+ # To restore training support, this module needs to be rewritten using pure PyTorch Datasets/DataLoaders.
5
+
6
+ def get_colorize_data(
7
+ sz: int,
8
+ bs: int,
9
+ crappy_path: Path,
10
+ good_path: Path,
11
+ random_seed: int = None,
12
+ keep_pct: float = 1.0,
13
+ num_workers: int = 8,
14
+ stats: tuple = None,
15
+ xtra_tfms=[],
16
+ ):
17
+ raise NotImplementedError("Training data loading not supported in this version.")
18
+
19
+ def get_dummy_databunch():
20
+ return DataBunch()
deoldify/device_id.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from enum import IntEnum
2
+
3
+ class DeviceId(IntEnum):
4
+ GPU0 = 0,
5
+ GPU1 = 1,
6
+ GPU2 = 2,
7
+ GPU3 = 3,
8
+ GPU4 = 4,
9
+ GPU5 = 5,
10
+ GPU6 = 6,
11
+ GPU7 = 7,
12
+ XPU = 98,
13
+ CPU = 99
deoldify/fastai_compat.py ADDED
@@ -0,0 +1,268 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ return p
2
+
3
+ import torchvision.models as models
4
+
5
+ class NormType(Enum):
6
+ Batch = 1
7
+ BatchZero = 2
8
+ Weight = 3
9
+ Spectral = 4
10
+ Instance = 5
11
+ InstanceZero = 6
12
+ Pixel = 7
13
+
14
+ SplitFuncOrIdxList = Optional[Union[Callable, List[int]]]
15
+
16
+ def to_device(m, device):
17
+ return m.to(device)
18
+
19
+ def apply_init(m, init_func):
20
+ if hasattr(m, 'apply'):
21
+ m.apply(lambda x: init_func(x.weight) if hasattr(x, 'weight') and hasattr(x.weight, 'data') else None)
22
+
23
+ ImageDataBunch = DataBunch
24
+
25
+
26
+ def camel2snake(name):
27
+ import re
28
+ _camel_re1 = re.compile('(.)([A-Z][a-z]+)')
29
+ _camel_re2 = re.compile('([a-z0-9])([A-Z])')
30
+ return _camel_re2.sub(r'\1_\2', _camel_re1.sub(r'\1_\2', name)).lower()
31
+
32
+ class SequentialEx(nn.Module):
33
+ "Like `nn.Sequential`, but with ModuleList semantics, and can handle `MergeLayer`."
34
+ def __init__(self, *layers):
35
+ super().__init__()
36
+ self.layers = nn.ModuleList(layers)
37
+
38
+ def forward(self, x):
39
+ res = x
40
+ for l in self.layers:
41
+ res.orig = x
42
+ nres = l(res)
43
+ # We have to remove res.orig to avoid hanging references and therefore memory leaks
44
+ res.orig = None
45
+ res = nres
46
+ return res
47
+
48
+ def __getitem__(self, i): return self.layers[i]
49
+ def append(self, l): return self.layers.append(l)
50
+ def extend(self, l): return self.layers.extend(l)
51
+ def insert(self, i, l): return self.layers.insert(i, l)
52
+
53
+ class MergeLayer(nn.Module):
54
+ "Merge a shortcut with the result of the module by adding them or concatenating them if `dense=True`."
55
+ def __init__(self, dense:bool=False):
56
+ super().__init__()
57
+ self.dense = dense
58
+
59
+ def forward(self, x):
60
+ return torch.cat([x, x.orig], dim=1) if self.dense else (x+x.orig)
61
+
62
+ class SigmoidRange(nn.Module):
63
+ "Sigmoid module with range `(low, x_max)`"
64
+ def __init__(self, low, high):
65
+ super().__init__()
66
+ self.low, self.high = low, high
67
+
68
+ def forward(self, x):
69
+ return torch.sigmoid(x) * (self.high - self.low) + self.low
70
+
71
+ def conv_layer(ni:int, nf:int, ks:int=3, stride:int=1, padding:int=None, bias:bool=None, is_1d:bool=False,
72
+ norm_type:Optional[str]=None, use_activ:bool=True, leaky:float=None,
73
+ transpose:bool=False, init:Callable=nn.init.kaiming_normal_, self_attention:bool=False):
74
+ "Create a sequence of convolutional (`ni` to `nf`), ReLU (if `use_activ`) and batchnorm (if `bn`) layers."
75
+ if padding is None: padding = (ks-1)//2 if not transpose else 0
76
+ bn = norm_type in ('Batch', 'BatchZero')
77
+ if bias is None: bias = not bn
78
+ conv_func = nn.ConvTranspose2d if transpose else nn.Conv1d if is_1d else nn.Conv2d
79
+ conv = conv_func(ni, nf, kernel_size=ks, bias=bias, stride=stride, padding=padding)
80
+
81
+ if init: init(conv.weight)
82
+
83
+ if norm_type == 'Weight': conv = weight_norm(conv)
84
+ elif norm_type == 'Spectral': conv = spectral_norm(conv)
85
+
86
+ layers = [conv]
87
+ if use_activ: layers.append(relu(leaky=leaky))
88
+ if bn: layers.append((nn.BatchNorm1d if is_1d else nn.BatchNorm2d)(nf))
89
+ if self_attention: layers.append(SelfAttention(nf))
90
+ return nn.Sequential(*layers)
91
+
92
+ def relu(leaky:float=None):
93
+ return nn.LeakyReLU(ifnone(leaky,0.1), inplace=True) if leaky is not None else nn.ReLU(inplace=True)
94
+
95
+ def batchnorm_2d(nf:int, norm_type:str='Batch'):
96
+ return nn.BatchNorm2d(nf)
97
+
98
+ class SelfAttention(nn.Module):
99
+ "Self attention layer for nd."
100
+ def __init__(self, n_channels:int):
101
+ super().__init__()
102
+ self.query = conv1d(n_channels, n_channels//8)
103
+ self.key = conv1d(n_channels, n_channels//8)
104
+ self.value = conv1d(n_channels, n_channels)
105
+ self.gamma = nn.Parameter(tensor([0.]))
106
+
107
+ def forward(self, x):
108
+ #Notation from https://arxiv.org/abs/1805.08318
109
+ size = x.size()
110
+ x = x.view(*size[:2],-1)
111
+ f,g,h = self.query(x),self.key(x),self.value(x)
112
+ beta = F.softmax(torch.bmm(f.transpose(1,2), g), dim=1)
113
+ o = self.gamma * torch.bmm(h, beta) + x
114
+ return o.view(*size)
115
+
116
+ def conv1d(ni:int, no:int, ks:int=1, stride:int=1, padding:int=0, bias:bool=False):
117
+ "Create and initialize a `nn.Conv1d` layer with spectral normalization."
118
+ conv = nn.Conv1d(ni, no, ks, stride=stride, padding=padding, bias=bias)
119
+ nn.init.kaiming_normal_(conv.weight)
120
+ if bias: conv.bias.data.zero_()
121
+ return spectral_norm(conv)
122
+
123
+ def res_block(nf, dense:bool=False, norm_type:str='Batch', bottle:bool=False, **kwargs):
124
+ "Resnet block of `nf` features."
125
+ norm2 = norm_type
126
+ if not dense and (norm_type=='Batch'): norm2 = 'BatchZero'
127
+ nf_inner = nf//2 if bottle else nf
128
+ return SequentialEx(conv_layer(nf, nf_inner, norm_type=norm_type, **kwargs),
129
+ conv_layer(nf_inner, nf, norm_type=norm2, **kwargs),
130
+ MergeLayer(dense))
131
+
132
+ # --- Hooks & Model Sizes ---
133
+
134
+ class Hook():
135
+ "Create a hook on `m` with `hook_func`."
136
+ def __init__(self, m:nn.Module, hook_func:Callable, is_forward:bool=True, detach:bool=True):
137
+ self.hook_func,self.detach,self.stored = hook_func,detach,None
138
+ f = m.register_forward_hook if is_forward else m.register_backward_hook
139
+ self.hook = f(self.hook_fn)
140
+ self.removed = False
141
+
142
+ def hook_fn(self, module:nn.Module, input:Tensor, output:Tensor):
143
+ if self.detach:
144
+ input = (o.detach() for o in input) if isinstance(input, tuple) else input.detach()
145
+ output = (o.detach() for o in output) if isinstance(output, tuple) else output.detach()
146
+ self.stored = self.hook_func(module, input, output)
147
+
148
+ def remove(self):
149
+ if not self.removed:
150
+ self.hook.remove()
151
+ self.removed = True
152
+
153
+ def __enter__(self, *args): return self
154
+ def __exit__(self, *args): self.remove()
155
+
156
+ class Hooks():
157
+ "Create several hooks on the modules in `ms` with `hook_func`."
158
+ def __init__(self, ms:List[nn.Module], hook_func:Callable, is_forward:bool=True, detach:bool=True):
159
+ self.hooks = [Hook(m, hook_func, is_forward, detach) for m in ms]
160
+
161
+ def __getitem__(self,i:int)->Hook: return self.hooks[i]
162
+ def __len__(self)->int: return len(self.hooks)
163
+ def __iter__(self): return iter(self.hooks)
164
+ @property
165
+ def stored(self): return [o.stored for o in self]
166
+
167
+ def remove(self):
168
+ for h in self.hooks: h.remove()
169
+
170
+ def __enter__(self, *args): return self
171
+ def __exit__(self, *args): self.remove()
172
+
173
+ def _hook_inner(m,i,o): return o if isinstance(o,Tensor) else o if isinstance(o,list) else list(o)
174
+
175
+ def hook_outputs(modules:List[nn.Module], detach:bool=True, grad:bool=False)->Hooks:
176
+ "Return `Hooks` that store activations of all `modules` in `self.stored`"
177
+ return Hooks(modules, _hook_inner, detach=detach, is_forward=not grad)
178
+
179
+ def dummy_eval(m:nn.Module, size:Tuple=(64,64)):
180
+ "Evaluate `m` on a dummy input of a certain `size`"
181
+ ch_in = in_channels(m)
182
+ x = torch.randn(1,ch_in,*size)
183
+ if next(m.parameters()).is_cuda: x = x.cuda()
184
+ return m.eval()(x)
185
+
186
+ def model_sizes(m:nn.Module, size:Tuple=(64,64)):
187
+ "Pass a dummy input through the model `m` to get the various sizes of activations."
188
+ with hook_outputs(m) as hooks:
189
+ dummy_eval(m, size)
190
+ return [o.stored.shape for o in hooks]
191
+
192
+ def in_channels(m:nn.Module) -> int:
193
+ "Return the shape of the first weight layer in `m`."
194
+ for l in m.modules():
195
+ if isinstance(l, (nn.Conv1d, nn.Conv2d, nn.Conv3d)):
196
+ return l.in_channels
197
+ raise Exception('No weight layer')
198
+
199
+ # --- Model Creation ---
200
+
201
+ def create_body(arch:Callable, pretrained:bool=True, cut:Optional[Union[int, Callable]]=None):
202
+ "Cut off the head of a typically pretrained `arch`."
203
+ model = arch(pretrained=pretrained)
204
+ # Most torchvision models have 'fc' or 'classifier' as head
205
+ # ResNet specific cut
206
+ if cut is None:
207
+ ll = list(enumerate(model.children()))
208
+ cut = next(i for i,o in reversed(ll) if has_pool_type(o))
209
+
210
+ return nn.Sequential(*list(model.children())[:cut])
211
+
212
+ def has_pool_type(m):
213
+ if isinstance(m, (nn.AdaptiveAvgPool2d, nn.AdaptiveMaxPool2d, nn.AvgPool2d, nn.MaxPool2d)): return True
214
+ return False
215
+
216
+ def cnn_config(arch):
217
+ "Get the metadata for `arch`."
218
+ # Simplified config for ResNets
219
+ return {'split': lambda m: (m[0][6], m[1])} # Split at layer 6 for ResNet
220
+
221
+ # --- Learner Shim ---
222
+
223
+ class Learner:
224
+ "Minimal Learner shim for inference."
225
+ def __init__(self, data, model, path=None):
226
+ self.data = data
227
+ self.model = model
228
+ self.path = path
229
+
230
+ # Use deoldify.device to get the correct device (CUDA/XPU/CPU)
231
+ from deoldify import device as device_settings
232
+ self.device = device_settings.get_torch_device()
233
+
234
+ self.model.to(self.device)
235
+
236
+ def load(self, name):
237
+ # Load state dict
238
+ if self.path:
239
+ path = self.path / 'models' / f'{name}.pth'
240
+ else:
241
+ path = f'models/{name}.pth'
242
+
243
+ # Handle map_location
244
+ state = torch.load(path, map_location=self.device)
245
+ if 'model' in state: state = state['model']
246
+ self.model.load_state_dict(state, strict=True)
247
+
248
+ def split(self, split_on):
249
+ pass # Not needed for inference
250
+
251
+ def freeze(self):
252
+ for p in self.model.parameters(): p.requires_grad = False
253
+
254
+ class DataBunch:
255
+ "Minimal DataBunch shim."
256
+ def __init__(self, c=3, device=None):
257
+ self.c = c
258
+ if device:
259
+ self.device = device
260
+ else:
261
+ from deoldify import device as device_settings
262
+ self.device = device_settings.get_torch_device()
263
+
264
+ def get_dummy_databunch():
265
+ return DataBunch()
266
+
267
+ def tensor(x, *args, **kwargs):
268
+ return torch.tensor(x, *args, **kwargs)