hysts HF Staff commited on
Commit
af5f89c
·
1 Parent(s): a729611
.pre-commit-config.yaml CHANGED
@@ -1,6 +1,6 @@
1
  repos:
2
  - repo: https://github.com/pre-commit/pre-commit-hooks
3
- rev: v4.5.0
4
  hooks:
5
  - id: check-executables-have-shebangs
6
  - id: check-json
@@ -13,48 +13,21 @@ repos:
13
  args: ["--fix=lf"]
14
  - id: requirements-txt-fixer
15
  - id: trailing-whitespace
16
- - repo: https://github.com/myint/docformatter
17
- rev: v1.7.5
18
  hooks:
19
- - id: docformatter
20
- args: ["--in-place"]
21
- - repo: https://github.com/pycqa/isort
22
- rev: 5.13.2
23
- hooks:
24
- - id: isort
25
- args: ["--profile", "black"]
26
  - repo: https://github.com/pre-commit/mirrors-mypy
27
- rev: v1.8.0
28
  hooks:
29
  - id: mypy
30
  args: ["--ignore-missing-imports"]
31
  additional_dependencies:
32
  [
33
  "types-python-slugify",
34
- "types-requests",
35
- "types-PyYAML",
36
  "types-pytz",
 
 
37
  ]
38
- - repo: https://github.com/psf/black
39
- rev: 24.2.0
40
- hooks:
41
- - id: black
42
- language_version: python3.10
43
- args: ["--line-length", "119"]
44
- - repo: https://github.com/kynan/nbstripout
45
- rev: 0.7.1
46
- hooks:
47
- - id: nbstripout
48
- args:
49
- [
50
- "--extra-keys",
51
- "metadata.interpreter metadata.kernelspec cell.metadata.pycharm",
52
- ]
53
- - repo: https://github.com/nbQA-dev/nbQA
54
- rev: 1.7.1
55
- hooks:
56
- - id: nbqa-black
57
- - id: nbqa-pyupgrade
58
- args: ["--py37-plus"]
59
- - id: nbqa-isort
60
- args: ["--float-to-top"]
 
1
  repos:
2
  - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v5.0.0
4
  hooks:
5
  - id: check-executables-have-shebangs
6
  - id: check-json
 
13
  args: ["--fix=lf"]
14
  - id: requirements-txt-fixer
15
  - id: trailing-whitespace
16
+ - repo: https://github.com/astral-sh/ruff-pre-commit
17
+ rev: v0.9.9
18
  hooks:
19
+ - id: ruff
20
+ args: ["--fix"]
21
+ - id: ruff-format
 
 
 
 
22
  - repo: https://github.com/pre-commit/mirrors-mypy
23
+ rev: v1.15.0
24
  hooks:
25
  - id: mypy
26
  args: ["--ignore-missing-imports"]
27
  additional_dependencies:
28
  [
29
  "types-python-slugify",
 
 
30
  "types-pytz",
31
+ "types-PyYAML",
32
+ "types-requests",
33
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.python-version ADDED
@@ -0,0 +1 @@
 
 
1
+ 3.10
.vscode/extensions.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "recommendations": [
3
+ "ms-python.python",
4
+ "charliermarsh.ruff",
5
+ "streetsidesoftware.code-spell-checker",
6
+ "tamasfe.even-better-toml"
7
+ ]
8
+ }
.vscode/settings.json CHANGED
@@ -2,29 +2,16 @@
2
  "editor.formatOnSave": true,
3
  "files.insertFinalNewline": false,
4
  "[python]": {
5
- "editor.defaultFormatter": "ms-python.black-formatter",
6
  "editor.formatOnType": true,
7
  "editor.codeActionsOnSave": {
 
8
  "source.organizeImports": "explicit"
9
  }
10
  },
11
  "[jupyter]": {
12
  "files.insertFinalNewline": false
13
  },
14
- "black-formatter.args": [
15
- "--line-length=119"
16
- ],
17
- "isort.args": ["--profile", "black"],
18
- "flake8.args": [
19
- "--max-line-length=119"
20
- ],
21
- "ruff.lint.args": [
22
- "--line-length=119"
23
- ],
24
  "notebook.output.scrolling": true,
25
- "notebook.formatOnCellExecution": true,
26
- "notebook.formatOnSave.enabled": true,
27
- "notebook.codeActionsOnSave": {
28
- "source.organizeImports": "explicit"
29
- }
30
  }
 
2
  "editor.formatOnSave": true,
3
  "files.insertFinalNewline": false,
4
  "[python]": {
5
+ "editor.defaultFormatter": "charliermarsh.ruff",
6
  "editor.formatOnType": true,
7
  "editor.codeActionsOnSave": {
8
+ "source.fixAll.ruff": "explicit",
9
  "source.organizeImports": "explicit"
10
  }
11
  },
12
  "[jupyter]": {
13
  "files.insertFinalNewline": false
14
  },
 
 
 
 
 
 
 
 
 
 
15
  "notebook.output.scrolling": true,
16
+ "notebook.formatOnSave.enabled": true
 
 
 
 
17
  }
README.md CHANGED
@@ -4,7 +4,7 @@ emoji: 🦀
4
  colorFrom: blue
5
  colorTo: pink
6
  sdk: gradio
7
- sdk_version: 4.36.1
8
  app_file: app.py
9
  pinned: false
10
  ---
 
4
  colorFrom: blue
5
  colorTo: pink
6
  sdk: gradio
7
+ sdk_version: 5.20.0
8
  app_file: app.py
9
  pinned: false
10
  ---
app.py CHANGED
@@ -1,6 +1,5 @@
1
  #!/usr/bin/env python
2
 
3
- import functools
4
  import os
5
  import pathlib
6
 
@@ -11,13 +10,15 @@ import huggingface_hub
11
  import numpy as np
12
  import pretrainedmodels
13
  import torch
14
- import torch.nn as nn
15
- import torch.nn.functional as F
16
 
17
  DESCRIPTION = "# [Age Estimation](https://github.com/yu4u/age-estimation-pytorch)"
18
 
19
 
20
- def get_model(model_name="se_resnext50_32x4d", num_classes=101, pretrained="imagenet"):
 
 
21
  model = pretrainedmodels.__dict__[model_name](pretrained=pretrained)
22
  dim_feats = model.last_linear.in_features
23
  model.last_linear = nn.Linear(dim_feats, num_classes)
@@ -25,7 +26,7 @@ def get_model(model_name="se_resnext50_32x4d", num_classes=101, pretrained="imag
25
  return model
26
 
27
 
28
- def load_model(device):
29
  model = get_model(model_name="se_resnext50_32x4d", pretrained=None)
30
  path = huggingface_hub.hf_hub_download("public-data/yu4u-age-estimation-pytorch", "pretrained.pth")
31
  model.load_state_dict(torch.load(path))
@@ -34,26 +35,41 @@ def load_model(device):
34
  return model
35
 
36
 
37
- def load_image(path):
38
  image = cv2.imread(path)
39
  h_orig, w_orig = image.shape[:2]
40
  size = max(h_orig, w_orig)
41
  scale = 640 / size
42
  w, h = int(w_orig * scale), int(h_orig * scale)
43
- image = cv2.resize(image, (w, h))
44
- return image
45
 
46
 
47
- def draw_label(image, point, label, font=cv2.FONT_HERSHEY_SIMPLEX, font_scale=0.8, thickness=1):
 
 
 
 
 
 
 
48
  size = cv2.getTextSize(label, font, font_scale, thickness)[0]
49
  x, y = point
50
  cv2.rectangle(image, (x, y - size[1]), (x + size[0], y), (255, 0, 0), cv2.FILLED)
51
  cv2.putText(image, label, point, font, font_scale, (255, 255, 255), thickness, lineType=cv2.LINE_AA)
52
 
53
 
 
 
 
 
 
54
  @torch.inference_mode()
55
- def predict(image, model, face_detector, device, margin=0.4, input_size=224):
56
- image = cv2.imread(image, cv2.IMREAD_COLOR)[:, :, ::-1].copy()
 
 
 
 
57
  image_h, image_w = image.shape[:2]
58
 
59
  # detect faces using dlib detector
@@ -79,20 +95,14 @@ def predict(image, model, face_detector, device, margin=0.4, input_size=224):
79
  predicted_ages = (outputs * ages).sum(axis=-1)
80
 
81
  # draw results
82
- for age, d in zip(predicted_ages, detected):
83
  draw_label(image, (d.left(), d.top()), f"{int(age)}")
84
  return image
85
 
86
 
87
- device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
88
- model = load_model(device)
89
- face_detector = dlib.get_frontal_face_detector()
90
- fn = functools.partial(predict, model=model, face_detector=face_detector, device=device)
91
-
92
- image_dir = pathlib.Path("sample_images")
93
- examples = [path.as_posix() for path in sorted(image_dir.glob("*.jpg"))]
94
 
95
- with gr.Blocks(css="style.css") as demo:
96
  gr.Markdown(DESCRIPTION)
97
  with gr.Row():
98
  with gr.Column():
@@ -105,11 +115,11 @@ with gr.Blocks(css="style.css") as demo:
105
  examples=examples,
106
  inputs=image,
107
  outputs=result,
108
- fn=fn,
109
  cache_examples=os.getenv("CACHE_EXAMPLES") == "1",
110
  )
111
  run_button.click(
112
- fn=fn,
113
  inputs=image,
114
  outputs=result,
115
  api_name="predict",
 
1
  #!/usr/bin/env python
2
 
 
3
  import os
4
  import pathlib
5
 
 
10
  import numpy as np
11
  import pretrainedmodels
12
  import torch
13
+ import torch.nn.functional as F # noqa: N812
14
+ from torch import nn
15
 
16
  DESCRIPTION = "# [Age Estimation](https://github.com/yu4u/age-estimation-pytorch)"
17
 
18
 
19
+ def get_model(
20
+ model_name: str = "se_resnext50_32x4d", num_classes: int = 101, pretrained: str | None = "imagenet"
21
+ ) -> nn.Module:
22
  model = pretrainedmodels.__dict__[model_name](pretrained=pretrained)
23
  dim_feats = model.last_linear.in_features
24
  model.last_linear = nn.Linear(dim_feats, num_classes)
 
26
  return model
27
 
28
 
29
+ def load_model(device: torch.device) -> nn.Module:
30
  model = get_model(model_name="se_resnext50_32x4d", pretrained=None)
31
  path = huggingface_hub.hf_hub_download("public-data/yu4u-age-estimation-pytorch", "pretrained.pth")
32
  model.load_state_dict(torch.load(path))
 
35
  return model
36
 
37
 
38
+ def load_image(path: str) -> np.ndarray:
39
  image = cv2.imread(path)
40
  h_orig, w_orig = image.shape[:2]
41
  size = max(h_orig, w_orig)
42
  scale = 640 / size
43
  w, h = int(w_orig * scale), int(h_orig * scale)
44
+ return cv2.resize(image, (w, h))
 
45
 
46
 
47
+ def draw_label(
48
+ image: np.ndarray,
49
+ point: tuple[int, int],
50
+ label: str,
51
+ font: int = cv2.FONT_HERSHEY_SIMPLEX,
52
+ font_scale: float = 0.8,
53
+ thickness: int = 1,
54
+ ) -> None:
55
  size = cv2.getTextSize(label, font, font_scale, thickness)[0]
56
  x, y = point
57
  cv2.rectangle(image, (x, y - size[1]), (x + size[0], y), (255, 0, 0), cv2.FILLED)
58
  cv2.putText(image, label, point, font, font_scale, (255, 255, 255), thickness, lineType=cv2.LINE_AA)
59
 
60
 
61
+ device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
62
+ model = load_model(device)
63
+ face_detector = dlib.get_frontal_face_detector()
64
+
65
+
66
  @torch.inference_mode()
67
+ def predict(
68
+ image_path: str,
69
+ margin: float = 0.4,
70
+ input_size: int = 224,
71
+ ) -> np.ndarray:
72
+ image = cv2.imread(image_path, cv2.IMREAD_COLOR)[:, :, ::-1].copy()
73
  image_h, image_w = image.shape[:2]
74
 
75
  # detect faces using dlib detector
 
95
  predicted_ages = (outputs * ages).sum(axis=-1)
96
 
97
  # draw results
98
+ for age, d in zip(predicted_ages, detected, strict=True):
99
  draw_label(image, (d.left(), d.top()), f"{int(age)}")
100
  return image
101
 
102
 
103
+ examples = sorted(pathlib.Path("sample_images").glob("*.jpg"))
 
 
 
 
 
 
104
 
105
+ with gr.Blocks(css_paths="style.css") as demo:
106
  gr.Markdown(DESCRIPTION)
107
  with gr.Row():
108
  with gr.Column():
 
115
  examples=examples,
116
  inputs=image,
117
  outputs=result,
118
+ fn=predict,
119
  cache_examples=os.getenv("CACHE_EXAMPLES") == "1",
120
  )
121
  run_button.click(
122
+ fn=predict,
123
  inputs=image,
124
  outputs=result,
125
  api_name="predict",
pyproject.toml ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "age-estimation-appa-real"
3
+ version = "0.1.0"
4
+ description = ""
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ dependencies = [
8
+ "dlib>=19.24.6",
9
+ "gradio>=5.20.0",
10
+ "hf-transfer>=0.1.9",
11
+ "opencv-python-headless>=4.11.0.86",
12
+ "pretrainedmodels>=0.7.4",
13
+ "torch==2.4.0",
14
+ "torchvision>=0.19.0",
15
+ ]
16
+
17
+ [tool.ruff]
18
+ line-length = 119
19
+
20
+ [tool.ruff.lint]
21
+ select = ["ALL"]
22
+ ignore = [
23
+ "COM812", # missing-trailing-comma
24
+ "D203", # one-blank-line-before-class
25
+ "D213", # multi-line-summary-second-line
26
+ "E501", # line-too-long
27
+ "SIM117", # multiple-with-statements
28
+ ]
29
+ extend-ignore = [
30
+ "D100", # undocumented-public-module
31
+ "D101", # undocumented-public-class
32
+ "D102", # undocumented-public-method
33
+ "D103", # undocumented-public-function
34
+ "D104", # undocumented-public-package
35
+ "D105", # undocumented-magic-method
36
+ "D107", # undocumented-public-init
37
+ "EM101", # raw-string-in-exception
38
+ "FBT001", # boolean-type-hint-positional-argument
39
+ "FBT002", # boolean-default-value-positional-argument
40
+ "PD901", # pandas-df-variable-name
41
+ "PGH003", # blanket-type-ignore
42
+ "PLR0913", # too-many-arguments
43
+ "PLR0915", # too-many-statements
44
+ "TRY003", # raise-vanilla-args
45
+ ]
46
+ unfixable = [
47
+ "F401", # unused-import
48
+ ]
49
+
50
+ [tool.ruff.lint.pydocstyle]
51
+ convention = "google"
52
+
53
+ [tool.ruff.lint.per-file-ignores]
54
+ "*.ipynb" = ["T201", "T203"]
55
+
56
+ [tool.ruff.format]
57
+ docstring-code-format = true
requirements.txt CHANGED
@@ -1,7 +1,222 @@
1
- dlib==19.24.2
2
- gradio==4.36.1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  numpy==1.26.4
4
- opencv-python-headless==4.9.0.80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  pretrainedmodels==0.7.4
6
- torch==2.0.1
7
- torchvision==0.15.2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file was autogenerated by uv via the following command:
2
+ # uv pip compile pyproject.toml -o requirements.txt
3
+ aiofiles==23.2.1
4
+ # via gradio
5
+ annotated-types==0.7.0
6
+ # via pydantic
7
+ anyio==4.8.0
8
+ # via
9
+ # gradio
10
+ # httpx
11
+ # starlette
12
+ certifi==2025.1.31
13
+ # via
14
+ # httpcore
15
+ # httpx
16
+ # requests
17
+ charset-normalizer==3.4.1
18
+ # via requests
19
+ click==8.1.8
20
+ # via
21
+ # typer
22
+ # uvicorn
23
+ dlib==19.24.6
24
+ # via age-estimation-appa-real (pyproject.toml)
25
+ exceptiongroup==1.2.2
26
+ # via anyio
27
+ fastapi==0.115.11
28
+ # via gradio
29
+ ffmpy==0.5.0
30
+ # via gradio
31
+ filelock==3.17.0
32
+ # via
33
+ # huggingface-hub
34
+ # torch
35
+ # triton
36
+ fsspec==2025.2.0
37
+ # via
38
+ # gradio-client
39
+ # huggingface-hub
40
+ # torch
41
+ gradio==5.20.0
42
+ # via age-estimation-appa-real (pyproject.toml)
43
+ gradio-client==1.7.2
44
+ # via gradio
45
+ groovy==0.1.2
46
+ # via gradio
47
+ h11==0.14.0
48
+ # via
49
+ # httpcore
50
+ # uvicorn
51
+ hf-transfer==0.1.9
52
+ # via age-estimation-appa-real (pyproject.toml)
53
+ httpcore==1.0.7
54
+ # via httpx
55
+ httpx==0.28.1
56
+ # via
57
+ # gradio
58
+ # gradio-client
59
+ # safehttpx
60
+ huggingface-hub==0.29.2
61
+ # via
62
+ # gradio
63
+ # gradio-client
64
+ idna==3.10
65
+ # via
66
+ # anyio
67
+ # httpx
68
+ # requests
69
+ jinja2==3.1.6
70
+ # via
71
+ # gradio
72
+ # torch
73
+ markdown-it-py==3.0.0
74
+ # via rich
75
+ markupsafe==2.1.5
76
+ # via
77
+ # gradio
78
+ # jinja2
79
+ mdurl==0.1.2
80
+ # via markdown-it-py
81
+ mpmath==1.3.0
82
+ # via sympy
83
+ munch==4.0.0
84
+ # via pretrainedmodels
85
+ networkx==3.4.2
86
+ # via torch
87
  numpy==1.26.4
88
+ # via
89
+ # gradio
90
+ # opencv-python-headless
91
+ # pandas
92
+ # torchvision
93
+ nvidia-cublas-cu12==12.1.3.1
94
+ # via
95
+ # nvidia-cudnn-cu12
96
+ # nvidia-cusolver-cu12
97
+ # torch
98
+ nvidia-cuda-cupti-cu12==12.1.105
99
+ # via torch
100
+ nvidia-cuda-nvrtc-cu12==12.1.105
101
+ # via torch
102
+ nvidia-cuda-runtime-cu12==12.1.105
103
+ # via torch
104
+ nvidia-cudnn-cu12==9.1.0.70
105
+ # via torch
106
+ nvidia-cufft-cu12==11.0.2.54
107
+ # via torch
108
+ nvidia-curand-cu12==10.3.2.106
109
+ # via torch
110
+ nvidia-cusolver-cu12==11.4.5.107
111
+ # via torch
112
+ nvidia-cusparse-cu12==12.1.0.106
113
+ # via
114
+ # nvidia-cusolver-cu12
115
+ # torch
116
+ nvidia-nccl-cu12==2.20.5
117
+ # via torch
118
+ nvidia-nvjitlink-cu12==12.8.61
119
+ # via
120
+ # nvidia-cusolver-cu12
121
+ # nvidia-cusparse-cu12
122
+ nvidia-nvtx-cu12==12.1.105
123
+ # via torch
124
+ opencv-python-headless==4.11.0.86
125
+ # via age-estimation-appa-real (pyproject.toml)
126
+ orjson==3.10.15
127
+ # via gradio
128
+ packaging==24.2
129
+ # via
130
+ # gradio
131
+ # gradio-client
132
+ # huggingface-hub
133
+ pandas==2.2.3
134
+ # via gradio
135
+ pillow==11.1.0
136
+ # via
137
+ # gradio
138
+ # torchvision
139
  pretrainedmodels==0.7.4
140
+ # via age-estimation-appa-real (pyproject.toml)
141
+ pydantic==2.10.6
142
+ # via
143
+ # fastapi
144
+ # gradio
145
+ pydantic-core==2.27.2
146
+ # via pydantic
147
+ pydub==0.25.1
148
+ # via gradio
149
+ pygments==2.19.1
150
+ # via rich
151
+ python-dateutil==2.9.0.post0
152
+ # via pandas
153
+ python-multipart==0.0.20
154
+ # via gradio
155
+ pytz==2025.1
156
+ # via pandas
157
+ pyyaml==6.0.2
158
+ # via
159
+ # gradio
160
+ # huggingface-hub
161
+ requests==2.32.3
162
+ # via huggingface-hub
163
+ rich==13.9.4
164
+ # via typer
165
+ ruff==0.9.9
166
+ # via gradio
167
+ safehttpx==0.1.6
168
+ # via gradio
169
+ semantic-version==2.10.0
170
+ # via gradio
171
+ shellingham==1.5.4
172
+ # via typer
173
+ six==1.17.0
174
+ # via python-dateutil
175
+ sniffio==1.3.1
176
+ # via anyio
177
+ starlette==0.46.0
178
+ # via
179
+ # fastapi
180
+ # gradio
181
+ sympy==1.13.3
182
+ # via torch
183
+ tomlkit==0.13.2
184
+ # via gradio
185
+ torch==2.4.0
186
+ # via
187
+ # age-estimation-appa-real (pyproject.toml)
188
+ # pretrainedmodels
189
+ # torchvision
190
+ torchvision==0.19.0
191
+ # via
192
+ # age-estimation-appa-real (pyproject.toml)
193
+ # pretrainedmodels
194
+ tqdm==4.67.1
195
+ # via
196
+ # huggingface-hub
197
+ # pretrainedmodels
198
+ triton==3.0.0
199
+ # via torch
200
+ typer==0.15.2
201
+ # via gradio
202
+ typing-extensions==4.12.2
203
+ # via
204
+ # anyio
205
+ # fastapi
206
+ # gradio
207
+ # gradio-client
208
+ # huggingface-hub
209
+ # pydantic
210
+ # pydantic-core
211
+ # rich
212
+ # torch
213
+ # typer
214
+ # uvicorn
215
+ tzdata==2025.1
216
+ # via pandas
217
+ urllib3==2.3.0
218
+ # via requests
219
+ uvicorn==0.34.0
220
+ # via gradio
221
+ websockets==15.0.1
222
+ # via gradio-client
uv.lock ADDED
The diff for this file is too large to render. See raw diff