Prince-1 commited on
Commit
e793c54
Β·
verified Β·
1 Parent(s): 0f83679

Updated the Project

Browse files
.claude/settings.local.json ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "WebSearch",
5
+ "WebFetch(domain:www.sciencedirect.com)",
6
+ "WebFetch(domain:link.springer.com)",
7
+ "WebFetch(domain:pmc.ncbi.nlm.nih.gov)",
8
+ "WebFetch(domain:sefiks.com)",
9
+ "WebFetch(domain:lookscompare.com)",
10
+ "WebFetch(domain:idp.springer.com)",
11
+ "WebFetch(domain:github.com)",
12
+ "WebFetch(domain:arxiv.org)",
13
+ "Bash(gh api *)",
14
+ "WebFetch(domain:rigr.ai)",
15
+ "WebFetch(domain:www.kinfacew.com)",
16
+ "WebFetch(domain:pubmed.ncbi.nlm.nih.gov)",
17
+ "WebFetch(domain:www.media.io)",
18
+ "WebFetch(domain:www.ncbi.nlm.nih.gov)",
19
+ "WebFetch(domain:raw.githubusercontent.com)"
20
+ ]
21
+ }
22
+ }
.gitattributes CHANGED
@@ -1,35 +1,35 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,222 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
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
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ *.lcov
51
+ .hypothesis/
52
+ .pytest_cache/
53
+ cover/
54
+
55
+ # Translations
56
+ *.mo
57
+ *.pot
58
+
59
+ # Django stuff:
60
+ *.log
61
+ local_settings.py
62
+ db.sqlite3
63
+ db.sqlite3-journal
64
+
65
+ # Flask stuff:
66
+ instance/
67
+ .webassets-cache
68
+
69
+ # Scrapy stuff:
70
+ .scrapy
71
+
72
+ # Sphinx documentation
73
+ docs/_build/
74
+
75
+ # PyBuilder
76
+ .pybuilder/
77
+ target/
78
+
79
+ # Jupyter Notebook
80
+ .ipynb_checkpoints
81
+
82
+ # IPython
83
+ profile_default/
84
+ ipython_config.py
85
+
86
+ # pyenv
87
+ # For a library or package, you might want to ignore these files since the code is
88
+ # intended to run in multiple environments; otherwise, check them in:
89
+ # .python-version
90
+
91
+ # pipenv
92
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
93
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
94
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
95
+ # install all needed dependencies.
96
+ # Pipfile.lock
97
+
98
+ # UV
99
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
100
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
101
+ # commonly ignored for libraries.
102
+ # uv.lock
103
+
104
+ # poetry
105
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
106
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
107
+ # commonly ignored for libraries.
108
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
109
+ # poetry.lock
110
+ # poetry.toml
111
+
112
+ # pdm
113
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
114
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
115
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
116
+ # pdm.lock
117
+ # pdm.toml
118
+ .pdm-python
119
+ .pdm-build/
120
+
121
+ # pixi
122
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
123
+ # pixi.lock
124
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
125
+ # in the .venv directory. It is recommended not to include this directory in version control.
126
+ .pixi/*
127
+ !.pixi/config.toml
128
+
129
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
130
+ __pypackages__/
131
+
132
+ # Celery stuff
133
+ celerybeat-schedule*
134
+ celerybeat.pid
135
+
136
+ # Redis
137
+ *.rdb
138
+ *.aof
139
+ *.pid
140
+
141
+ # RabbitMQ
142
+ mnesia/
143
+ rabbitmq/
144
+ rabbitmq-data/
145
+
146
+ # ActiveMQ
147
+ activemq-data/
148
+
149
+ # SageMath parsed files
150
+ *.sage.py
151
+
152
+ # Environments
153
+ .env
154
+ .envrc
155
+ .venv
156
+ env/
157
+ venv/
158
+ ENV/
159
+ env.bak/
160
+ venv.bak/
161
+
162
+ # Spyder project settings
163
+ .spyderproject
164
+ .spyproject
165
+
166
+ # Rope project settings
167
+ .ropeproject
168
+
169
+ # mkdocs documentation
170
+ /site
171
+
172
+ # mypy
173
+ .mypy_cache/
174
+ .dmypy.json
175
+ dmypy.json
176
+
177
+ # Pyre type checker
178
+ .pyre/
179
+
180
+ # pytype static type analyzer
181
+ .pytype/
182
+
183
+ # Cython debug symbols
184
+ cython_debug/
185
+
186
+ # PyCharm
187
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
188
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
189
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
190
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
191
+ # .idea/
192
+
193
+ # Abstra
194
+ # Abstra is an AI-powered process automation framework.
195
+ # Ignore directories containing user credentials, local state, and settings.
196
+ # Learn more at https://abstra.io/docs
197
+ .abstra/
198
+
199
+ # Visual Studio Code
200
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
201
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
202
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
203
+ # you could uncomment the following to ignore the entire vscode folder
204
+ # .vscode/
205
+ # Temporary file for partial code execution
206
+ tempCodeRunnerFile.py
207
+
208
+ # Ruff stuff:
209
+ .ruff_cache/
210
+
211
+ # PyPI configuration file
212
+ .pypirc
213
+
214
+ # Marimo
215
+ marimo/_static/
216
+ marimo/_lsp/
217
+ __marimo__/
218
+
219
+ # Streamlit
220
+ .streamlit/secrets.toml
221
+ .claude
222
+ .superpowers
.superpowers/brainstorm/1147-1782279753/content/backend-choice.html ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <h2>Choose your ML backend</h2>
2
+ <p class="subtitle">Select one β€” shown as a horizontal toggle at the top of the app</p>
3
+
4
+ <div class="mockup">
5
+ <div class="mockup-header">MoreCloseToWhom β€” App Preview</div>
6
+ <div class="mockup-body">
7
+
8
+ <!-- Top selector bar -->
9
+ <div style="display:flex;gap:0;border:1px solid #2a3a5a;border-radius:8px;overflow:hidden;margin-bottom:20px">
10
+ <div class="backend-opt selected-opt" data-choice="deepface" onclick="toggleSelect(this)" style="flex:1;padding:10px 8px;text-align:center;background:#0f3460;cursor:pointer;border-right:1px solid #2a3a5a">
11
+ <div style="font-size:13px;color:#7ec8e3;font-weight:bold">🧠 DeepFace</div>
12
+ <div style="font-size:9px;color:#aaa;margin-top:2px">Easy Β· pip install deepface</div>
13
+ <div style="font-size:9px;color:#888;margin-top:1px">Age MAE ~10yr</div>
14
+ </div>
15
+ <div class="backend-opt" onclick="toggleSelect(this)" style="flex:1;padding:10px 8px;text-align:center;background:#16213e;cursor:pointer;border-right:1px solid #2a3a5a">
16
+ <div style="font-size:13px;color:#c8d8e8;font-weight:bold">⚑ InsightFace</div>
17
+ <div style="font-size:9px;color:#aaa;margin-top:2px">Faster Β· better accuracy</div>
18
+ <div style="font-size:9px;color:#888;margin-top:1px">Age MAE ~7.5yr</div>
19
+ </div>
20
+ <div class="backend-opt" onclick="toggleSelect(this)" style="flex:1;padding:10px 8px;text-align:center;background:#16213e;cursor:pointer">
21
+ <div style="font-size:13px;color:#c8d8e8;font-weight:bold">πŸ€— HF Model</div>
22
+ <div style="font-size:9px;color:#aaa;margin-top:2px">HF-native Β· custom model</div>
23
+ <div style="font-size:9px;color:#888;margin-top:1px">Manual setup</div>
24
+ </div>
25
+ </div>
26
+
27
+ <!-- Upload row: Father | Child (center) | Mother -->
28
+ <div style="display:flex;gap:16px;align-items:flex-end;margin-bottom:16px">
29
+ <div style="flex:1;background:#16213e;border:1px dashed #4a4a7a;border-radius:8px;padding:14px;text-align:center">
30
+ <div style="font-size:24px;margin-bottom:4px">πŸ‘¨</div>
31
+ <div style="font-size:10px;color:#7ec8e3;font-weight:bold;margin-bottom:4px">FATHER</div>
32
+ <div style="background:#0d1b2a;border-radius:4px;padding:5px;font-size:9px;color:#555">Drop photo here</div>
33
+ </div>
34
+ <div style="flex:1.3;background:#1a2a1a;border:2px solid #3a7a3a;border-radius:10px;padding:18px;text-align:center">
35
+ <div style="font-size:30px;margin-bottom:4px">πŸ§’</div>
36
+ <div style="font-size:10px;color:#7ec8e3;font-weight:bold;margin-bottom:4px">CHILD</div>
37
+ <div style="background:#0d1b0d;border-radius:4px;padding:5px;font-size:9px;color:#555">Drop photo here</div>
38
+ </div>
39
+ <div style="flex:1;background:#16213e;border:1px dashed #4a4a7a;border-radius:8px;padding:14px;text-align:center">
40
+ <div style="font-size:24px;margin-bottom:4px">πŸ‘©</div>
41
+ <div style="font-size:10px;color:#c8a0d8;font-weight:bold;margin-bottom:4px">MOTHER</div>
42
+ <div style="background:#0d1b2a;border-radius:4px;padding:5px;font-size:9px;color:#555">Drop photo here</div>
43
+ </div>
44
+ </div>
45
+
46
+ <div style="text-align:center;margin-bottom:16px">
47
+ <div style="display:inline-block;background:#1a6b3a;border-radius:6px;padding:8px 28px;font-size:12px;color:#fff">β–Ά Analyze Resemblance</div>
48
+ </div>
49
+
50
+ <div style="background:#16213e;border-radius:8px;padding:12px">
51
+ <div style="font-size:11px;color:#7ec8e3;font-weight:bold;margin-bottom:8px">Results</div>
52
+ <div style="display:flex;gap:14px">
53
+ <div style="flex:1">
54
+ <div style="font-size:9px;color:#aaa;margin-bottom:3px">πŸ‘¨ Father resemblance</div>
55
+ <div style="background:#0d1b2a;border-radius:3px;height:7px;margin-bottom:2px">
56
+ <div style="background:#3a8fd4;width:84%;height:7px;border-radius:3px"></div>
57
+ </div>
58
+ <div style="font-size:10px;color:#3a8fd4;font-weight:bold">84%</div>
59
+ </div>
60
+ <div style="flex:1">
61
+ <div style="font-size:9px;color:#aaa;margin-bottom:3px">πŸ‘© Mother resemblance</div>
62
+ <div style="background:#0d1b2a;border-radius:3px;height:7px;margin-bottom:2px">
63
+ <div style="background:#a060c0;width:71%;height:7px;border-radius:3px"></div>
64
+ </div>
65
+ <div style="font-size:10px;color:#a060c0;font-weight:bold">71%</div>
66
+ </div>
67
+ <div style="flex:1;text-align:center">
68
+ <div style="font-size:9px;color:#aaa;margin-bottom:3px">πŸ§’ Estimated age</div>
69
+ <div style="font-size:20px;color:#fff;font-weight:bold">8</div>
70
+ <div style="font-size:9px;color:#888">years old</div>
71
+ </div>
72
+ </div>
73
+ <div style="margin-top:10px;background:#1a3a1a;border-radius:6px;padding:7px;text-align:center;font-size:11px;color:#7ec8e3">
74
+ βœ… Child resembles <strong>Father</strong> more closely
75
+ </div>
76
+ </div>
77
+
78
+ </div>
79
+ </div>
80
+
81
+ <p class="subtitle" style="margin-top:16px">Click a backend tab above to select it, or just tell me in the terminal.</p>
.superpowers/brainstorm/1147-1782279753/content/layout-v2.html ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <h2>Layout A β€” confirmed</h2>
2
+ <p class="subtitle">Father and Mother on the sides, Child centered. Results appear below after analysis.</p>
3
+
4
+ <div class="mockup">
5
+ <div class="mockup-header">MoreCloseToWhom β€” App Preview</div>
6
+ <div class="mockup-body">
7
+ <div style="text-align:center;margin-bottom:18px">
8
+ <div style="font-size:20px;font-weight:bold;color:#e0e0e0">More Close To Whom?</div>
9
+ <div style="font-size:12px;color:#888;margin-top:4px">Upload photos of father, mother, and child to find out</div>
10
+ </div>
11
+
12
+ <!-- Upload row: Father | Child (center) | Mother -->
13
+ <div style="display:flex;gap:16px;align-items:flex-end;margin-bottom:20px">
14
+ <!-- Father -->
15
+ <div style="flex:1;background:#16213e;border:1px dashed #4a4a7a;border-radius:8px;padding:16px;text-align:center">
16
+ <div style="font-size:28px;margin-bottom:6px">πŸ‘¨</div>
17
+ <div style="font-size:11px;color:#7ec8e3;font-weight:bold;margin-bottom:4px">FATHER</div>
18
+ <div style="background:#0d1b2a;border-radius:4px;padding:6px;font-size:10px;color:#555">Drop photo here</div>
19
+ </div>
20
+
21
+ <!-- Child β€” larger/central -->
22
+ <div style="flex:1.3;background:#1a2a1a;border:2px solid #3a7a3a;border-radius:10px;padding:20px;text-align:center;position:relative">
23
+ <div style="position:absolute;top:-10px;left:50%;transform:translateX(-50%);background:#2a5a2a;border-radius:10px;padding:2px 10px;font-size:9px;color:#7ec8e3">CHILD</div>
24
+ <div style="font-size:36px;margin-bottom:6px">πŸ§’</div>
25
+ <div style="font-size:11px;color:#7ec8e3;font-weight:bold;margin-bottom:4px">CHILD</div>
26
+ <div style="background:#0d1b0d;border-radius:4px;padding:6px;font-size:10px;color:#555">Drop photo here</div>
27
+ </div>
28
+
29
+ <!-- Mother -->
30
+ <div style="flex:1;background:#16213e;border:1px dashed #4a4a7a;border-radius:8px;padding:16px;text-align:center">
31
+ <div style="font-size:28px;margin-bottom:6px">πŸ‘©</div>
32
+ <div style="font-size:11px;color:#c8a0d8;font-weight:bold;margin-bottom:4px">MOTHER</div>
33
+ <div style="background:#0d1b2a;border-radius:4px;padding:6px;font-size:10px;color:#555">Drop photo here</div>
34
+ </div>
35
+ </div>
36
+
37
+ <!-- Analyze button -->
38
+ <div style="text-align:center;margin-bottom:20px">
39
+ <div style="display:inline-block;background:#1a6b3a;border-radius:6px;padding:10px 32px;font-size:13px;color:#fff;cursor:pointer">β–Ά Analyze Resemblance</div>
40
+ </div>
41
+
42
+ <!-- Results -->
43
+ <div style="background:#16213e;border-radius:8px;padding:14px">
44
+ <div style="font-size:12px;color:#7ec8e3;font-weight:bold;margin-bottom:10px">Results</div>
45
+ <div style="display:flex;gap:16px">
46
+ <div style="flex:1">
47
+ <div style="font-size:10px;color:#aaa;margin-bottom:4px">πŸ‘¨ Father resemblance</div>
48
+ <div style="background:#0d1b2a;border-radius:3px;height:8px;margin-bottom:3px">
49
+ <div style="background:#3a8fd4;width:84%;height:8px;border-radius:3px"></div>
50
+ </div>
51
+ <div style="font-size:11px;color:#3a8fd4;font-weight:bold">84%</div>
52
+ </div>
53
+ <div style="flex:1">
54
+ <div style="font-size:10px;color:#aaa;margin-bottom:4px">πŸ‘© Mother resemblance</div>
55
+ <div style="background:#0d1b2a;border-radius:3px;height:8px;margin-bottom:3px">
56
+ <div style="background:#a060c0;width:71%;height:8px;border-radius:3px"></div>
57
+ </div>
58
+ <div style="font-size:11px;color:#a060c0;font-weight:bold">71%</div>
59
+ </div>
60
+ <div style="flex:1;text-align:center">
61
+ <div style="font-size:10px;color:#aaa;margin-bottom:4px">πŸ§’ Estimated age</div>
62
+ <div style="font-size:24px;color:#fff;font-weight:bold">8</div>
63
+ <div style="font-size:10px;color:#888">years old</div>
64
+ </div>
65
+ </div>
66
+ <div style="margin-top:12px;background:#1a3a1a;border-radius:6px;padding:8px;text-align:center;font-size:12px;color:#7ec8e3">
67
+ βœ… Child resembles <strong>Father</strong> more closely
68
+ </div>
69
+ </div>
70
+ </div>
71
+ </div>
.superpowers/brainstorm/1147-1782279753/content/layout.html ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <h2>How should the app be laid out?</h2>
2
+ <p class="subtitle">All three options upload Father, Mother, and Child photos and display resemblance + age results. The difference is in layout and flow.</p>
3
+
4
+ <div class="cards">
5
+ <div class="card" data-choice="a" onclick="toggleSelect(this)">
6
+ <div class="card-image">
7
+ <div style="background:#1a1a2e;padding:16px;border-radius:8px;font-family:monospace;font-size:12px;color:#e0e0e0">
8
+ <div style="display:flex;gap:8px;margin-bottom:12px">
9
+ <div style="flex:1;background:#16213e;border:1px dashed #4a4a7a;border-radius:6px;padding:10px;text-align:center;color:#888;font-size:11px">
10
+ πŸ“· Father<br><span style="font-size:9px;color:#555">Upload photo</span>
11
+ </div>
12
+ <div style="flex:1;background:#16213e;border:1px dashed #4a4a7a;border-radius:6px;padding:10px;text-align:center;color:#888;font-size:11px">
13
+ πŸ“· Mother<br><span style="font-size:9px;color:#555">Upload photo</span>
14
+ </div>
15
+ <div style="flex:1;background:#16213e;border:1px dashed #4a4a7a;border-radius:6px;padding:10px;text-align:center;color:#888;font-size:11px">
16
+ πŸ“· Child<br><span style="font-size:9px;color:#555">Upload photo</span>
17
+ </div>
18
+ </div>
19
+ <div style="background:#0f3460;border-radius:4px;padding:6px;text-align:center;margin-bottom:10px;font-size:11px">β–Ά Analyze</div>
20
+ <div style="background:#16213e;border-radius:6px;padding:10px">
21
+ <div style="color:#7ec8e3;font-size:11px;margin-bottom:4px">Results</div>
22
+ <div style="display:flex;justify-content:space-between;font-size:10px;color:#aaa">
23
+ <span>πŸ‘¨ Father match: 84%</span>
24
+ <span>πŸ‘© Mother match: 71%</span>
25
+ </div>
26
+ <div style="font-size:10px;color:#aaa;margin-top:4px">πŸ§’ Estimated age: 8 years</div>
27
+ </div>
28
+ </div>
29
+ </div>
30
+ <div class="card-body">
31
+ <h3>A β€” All-in-one panel</h3>
32
+ <p>Upload all 3 photos side-by-side, click Analyze, results appear below. Clean and fast.</p>
33
+ </div>
34
+ </div>
35
+
36
+ <div class="card" data-choice="b" onclick="toggleSelect(this)">
37
+ <div class="card-image">
38
+ <div style="background:#1a1a2e;padding:16px;border-radius:8px;font-family:monospace;font-size:12px;color:#e0e0e0">
39
+ <div style="display:flex;gap:10px">
40
+ <div style="flex:1">
41
+ <div style="color:#888;font-size:10px;margin-bottom:6px">INPUTS</div>
42
+ <div style="background:#16213e;border:1px dashed #4a4a7a;border-radius:4px;padding:8px;text-align:center;font-size:10px;color:#888;margin-bottom:4px">πŸ“· Father</div>
43
+ <div style="background:#16213e;border:1px dashed #4a4a7a;border-radius:4px;padding:8px;text-align:center;font-size:10px;color:#888;margin-bottom:4px">πŸ“· Mother</div>
44
+ <div style="background:#16213e;border:1px dashed #4a4a7a;border-radius:4px;padding:8px;text-align:center;font-size:10px;color:#888;margin-bottom:10px">πŸ“· Child</div>
45
+ <div style="background:#0f3460;border-radius:4px;padding:5px;text-align:center;font-size:10px">β–Ά Analyze</div>
46
+ </div>
47
+ <div style="flex:1">
48
+ <div style="color:#888;font-size:10px;margin-bottom:6px">RESULTS</div>
49
+ <div style="background:#16213e;border-radius:4px;padding:8px;margin-bottom:6px">
50
+ <div style="font-size:10px;color:#7ec8e3">Resemblance</div>
51
+ <div style="background:#0f3460;height:6px;border-radius:3px;margin:4px 0;width:84%"></div>
52
+ <div style="font-size:9px;color:#aaa">Father 84% β–²</div>
53
+ <div style="background:#3d1a4f;height:6px;border-radius:3px;margin:4px 0;width:71%"></div>
54
+ <div style="font-size:9px;color:#aaa">Mother 71%</div>
55
+ </div>
56
+ <div style="background:#16213e;border-radius:4px;padding:8px">
57
+ <div style="font-size:10px;color:#7ec8e3">Age estimate</div>
58
+ <div style="font-size:18px;text-align:center;color:#fff;margin-top:4px">8 yrs</div>
59
+ </div>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ </div>
64
+ <div class="card-body">
65
+ <h3>B β€” Split panel (inputs left, results right)</h3>
66
+ <p>Two-column layout: uploads on the left, results with bar charts on the right. More visual detail.</p>
67
+ </div>
68
+ </div>
69
+
70
+ <div class="card" data-choice="c" onclick="toggleSelect(this)">
71
+ <div class="card-image">
72
+ <div style="background:#1a1a2e;padding:16px;border-radius:8px;font-family:monospace;font-size:12px;color:#e0e0e0">
73
+ <div style="display:flex;gap:6px;margin-bottom:8px;justify-content:center">
74
+ <div style="background:#16213e;border:2px solid #0f3460;border-radius:50%;width:40px;height:40px;display:flex;align-items:center;justify-content:center;font-size:16px">πŸ‘¨</div>
75
+ <div style="background:#16213e;border:1px dashed #4a4a7a;border-radius:50%;width:40px;height:40px;display:flex;align-items:center;justify-content:center;font-size:16px">πŸ§’</div>
76
+ <div style="background:#16213e;border:2px solid #4a0f3c;border-radius:50%;width:40px;height:40px;display:flex;align-items:center;justify-content:center;font-size:16px">πŸ‘©</div>
77
+ </div>
78
+ <div style="display:flex;align-items:center;justify-content:center;gap:8px;margin-bottom:8px;font-size:9px;color:#aaa">
79
+ <span>Father</span><span style="color:#0f3460">──84%──</span><span>Child</span><span style="color:#4a0f3c">──71%──</span><span>Mother</span>
80
+ </div>
81
+ <div style="background:#16213e;border-radius:4px;padding:8px;text-align:center">
82
+ <div style="font-size:11px;color:#7ec8e3">Closer to: πŸ‘¨ Father</div>
83
+ <div style="font-size:10px;color:#888;margin-top:4px">Child age: ~8 years</div>
84
+ </div>
85
+ </div>
86
+ </div>
87
+ <div class="card-body">
88
+ <h3>C β€” Visual family tree style</h3>
89
+ <p>Photos displayed as nodes in a family tree with connection lines showing similarity scores. More playful and engaging.</p>
90
+ </div>
91
+ </div>
92
+ </div>
.superpowers/brainstorm/1147-1782279753/content/waiting.html ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ <div style="display:flex;align-items:center;justify-content:center;min-height:60vh">
2
+ <p class="subtitle">Continuing in terminal...</p>
3
+ </div>
.superpowers/brainstorm/1147-1782279753/state/server-info ADDED
@@ -0,0 +1 @@
 
 
1
+ {"type":"server-started","port":52079,"host":"127.0.0.1","url_host":"localhost","url":"http://localhost:52079","screen_dir":"D:\\Projects\\MoreCloseToWhom\\.superpowers\\brainstorm\\1147-1782279753\\content","state_dir":"D:\\Projects\\MoreCloseToWhom\\.superpowers\\brainstorm\\1147-1782279753\\state"}
Dockerfile CHANGED
@@ -1,20 +1,20 @@
1
- FROM python:3.13.5-slim
2
-
3
- WORKDIR /app
4
-
5
- RUN apt-get update && apt-get install -y \
6
- build-essential \
7
- curl \
8
- git \
9
- && rm -rf /var/lib/apt/lists/*
10
-
11
- COPY requirements.txt ./
12
- COPY src/ ./src/
13
-
14
- RUN pip3 install -r requirements.txt
15
-
16
- EXPOSE 8501
17
-
18
- HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health
19
-
20
  ENTRYPOINT ["streamlit", "run", "src/streamlit_app.py", "--server.port=8501", "--server.address=0.0.0.0"]
 
1
+ FROM python:3.13.5-slim
2
+
3
+ WORKDIR /app
4
+
5
+ RUN apt-get update && apt-get install -y \
6
+ build-essential \
7
+ curl \
8
+ git \
9
+ && rm -rf /var/lib/apt/lists/*
10
+
11
+ COPY requirements.txt ./
12
+ COPY src/ ./src/
13
+
14
+ RUN pip3 install -r requirements.txt
15
+
16
+ EXPOSE 8501
17
+
18
+ HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health
19
+
20
  ENTRYPOINT ["streamlit", "run", "src/streamlit_app.py", "--server.port=8501", "--server.address=0.0.0.0"]
README.md CHANGED
@@ -1,19 +1,19 @@
1
- ---
2
- title: ParentCloseTesting
3
- emoji: πŸš€
4
- colorFrom: red
5
- colorTo: red
6
- sdk: docker
7
- app_port: 8501
8
- tags:
9
- - streamlit
10
- pinned: false
11
- short_description: Streamlit template space
12
- ---
13
-
14
- # Welcome to Streamlit!
15
-
16
- Edit `/src/streamlit_app.py` to customize this app to your heart's desire. :heart:
17
-
18
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
19
- forums](https://discuss.streamlit.io).
 
1
+ ---
2
+ title: ParentCloseTesting
3
+ emoji: πŸš€
4
+ colorFrom: red
5
+ colorTo: red
6
+ sdk: docker
7
+ app_port: 8501
8
+ tags:
9
+ - streamlit
10
+ pinned: false
11
+ short_description: Streamlit template space
12
+ ---
13
+
14
+ # Welcome to Streamlit!
15
+
16
+ Edit `/src/streamlit_app.py` to customize this app to your heart's desire. :heart:
17
+
18
+ If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
19
+ forums](https://discuss.streamlit.io).
requirements.txt CHANGED
@@ -1,3 +1,19 @@
1
- altair
2
- pandas
3
- streamlit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ streamlit
2
+
3
+ # DeepFace backend
4
+ deepface
5
+ tf-keras
6
+
7
+ # InsightFace backend
8
+ insightface
9
+ onnxruntime
10
+
11
+ # HF Model backend
12
+ transformers
13
+ torch
14
+ torchvision
15
+
16
+ # Shared
17
+ Pillow
18
+ numpy
19
+ opencv-python-headless
src/backends/__init__.py ADDED
File without changes
src/backends/deepface_backend.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ from deepface import DeepFace
3
+
4
+ _MODEL = "VGG-Face"
5
+
6
+
7
+ def _cosine_sim(a, b):
8
+ a, b = np.array(a, dtype=float), np.array(b, dtype=float)
9
+ return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)))
10
+
11
+
12
+ def _to_pct(sim):
13
+ return round(max(0.0, min(1.0, (sim + 1) / 2)) * 100, 1)
14
+
15
+
16
+ def analyze(father_path, mother_path, child_path):
17
+ child_info = DeepFace.analyze(
18
+ child_path, actions=["age"], enforce_detection=False, silent=True
19
+ )
20
+ age = int(child_info[0]["age"])
21
+
22
+ child_emb = DeepFace.represent(
23
+ child_path, model_name=_MODEL, enforce_detection=False
24
+ )[0]["embedding"]
25
+ father_emb = DeepFace.represent(
26
+ father_path, model_name=_MODEL, enforce_detection=False
27
+ )[0]["embedding"]
28
+ mother_emb = DeepFace.represent(
29
+ mother_path, model_name=_MODEL, enforce_detection=False
30
+ )[0]["embedding"]
31
+
32
+ return {
33
+ "age": age,
34
+ "father_score": _to_pct(_cosine_sim(child_emb, father_emb)),
35
+ "mother_score": _to_pct(_cosine_sim(child_emb, mother_emb)),
36
+ }
src/backends/hf_backend.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import torch
3
+ from PIL import Image
4
+ from transformers import CLIPModel, CLIPProcessor, ViTFeatureExtractor, ViTForImageClassification
5
+
6
+ _clip_model = None
7
+ _clip_processor = None
8
+ _age_model = None
9
+ _age_extractor = None
10
+
11
+ # nateraw/vit-age-classifier outputs probabilities over these age range buckets
12
+ _AGE_LABELS = ["0-2", "3-9", "10-19", "20-29", "30-39", "40-49", "50-59", "60-69", "70+"]
13
+ _AGE_MIDPOINTS = [1, 6, 14, 24, 34, 44, 54, 64, 74]
14
+
15
+
16
+ def _get_clip():
17
+ global _clip_model, _clip_processor
18
+ if _clip_model is None:
19
+ _clip_model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
20
+ _clip_processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")
21
+ return _clip_model, _clip_processor
22
+
23
+
24
+ def _get_age_model():
25
+ global _age_model, _age_extractor
26
+ if _age_model is None:
27
+ _age_model = ViTForImageClassification.from_pretrained("nateraw/vit-age-classifier")
28
+ _age_extractor = ViTFeatureExtractor.from_pretrained("nateraw/vit-age-classifier")
29
+ return _age_model, _age_extractor
30
+
31
+
32
+ def _embed(image_path):
33
+ model, processor = _get_clip()
34
+ image = Image.open(image_path).convert("RGB")
35
+ inputs = processor(images=image, return_tensors="pt")
36
+ with torch.no_grad():
37
+ features = model.get_image_features(**inputs)
38
+ features = features / features.norm(dim=-1, keepdim=True)
39
+ return features[0].numpy()
40
+
41
+
42
+ def _estimate_age(image_path):
43
+ model, extractor = _get_age_model()
44
+ image = Image.open(image_path).convert("RGB")
45
+ inputs = extractor(images=image, return_tensors="pt")
46
+ with torch.no_grad():
47
+ outputs = model(**inputs)
48
+ probs = torch.softmax(outputs.logits, dim=-1)[0].numpy()
49
+ return int(round(float(np.dot(probs, _AGE_MIDPOINTS))))
50
+
51
+
52
+ def _to_pct(sim):
53
+ # CLIP features are already L2-normalized so dot product == cosine similarity (-1 to 1)
54
+ return round(max(0.0, min(1.0, (float(sim) + 1) / 2)) * 100, 1)
55
+
56
+
57
+ def analyze(father_path, mother_path, child_path):
58
+ child_emb = _embed(child_path)
59
+ father_emb = _embed(father_path)
60
+ mother_emb = _embed(mother_path)
61
+
62
+ return {
63
+ "age": _estimate_age(child_path),
64
+ "father_score": _to_pct(np.dot(child_emb, father_emb)),
65
+ "mother_score": _to_pct(np.dot(child_emb, mother_emb)),
66
+ }
src/backends/insightface_backend.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import cv2
3
+ from insightface.app import FaceAnalysis
4
+
5
+ _app = None
6
+
7
+
8
+ def _get_app():
9
+ global _app
10
+ if _app is None:
11
+ _app = FaceAnalysis(providers=["CPUExecutionProvider"])
12
+ _app.prepare(ctx_id=0, det_size=(640, 640))
13
+ return _app
14
+
15
+
16
+ def _cosine_sim(a, b):
17
+ a, b = np.array(a, dtype=float), np.array(b, dtype=float)
18
+ return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)))
19
+
20
+
21
+ def _to_pct(sim):
22
+ return round(max(0.0, min(1.0, (sim + 1) / 2)) * 100, 1)
23
+
24
+
25
+ def _get_face(app, path):
26
+ img = cv2.imread(path)
27
+ if img is None:
28
+ raise ValueError(f"Could not read image: {path}")
29
+ img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
30
+ faces = app.get(img_rgb)
31
+ if not faces:
32
+ raise ValueError(f"No face detected in image: {path}")
33
+ return faces[0]
34
+
35
+
36
+ def analyze(father_path, mother_path, child_path):
37
+ app = _get_app()
38
+
39
+ child_face = _get_face(app, child_path)
40
+ father_face = _get_face(app, father_path)
41
+ mother_face = _get_face(app, mother_path)
42
+
43
+ return {
44
+ "age": int(child_face.age),
45
+ "father_score": _to_pct(_cosine_sim(child_face.embedding, father_face.embedding)),
46
+ "mother_score": _to_pct(_cosine_sim(child_face.embedding, mother_face.embedding)),
47
+ }
src/streamlit_app.py CHANGED
@@ -1,40 +1,110 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
 
4
  import streamlit as st
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ import os
3
+ import tempfile
4
+
5
  import streamlit as st
6
 
7
+ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
8
+
9
+ st.set_page_config(
10
+ page_title="More Close To Whom?",
11
+ page_icon="πŸ‘¨β€πŸ‘©β€πŸ‘§",
12
+ layout="wide",
13
+ )
14
+
15
+ st.title("πŸ‘¨β€πŸ‘©β€πŸ‘§ More Close To Whom?")
16
+ st.caption("Upload photos of father, mother, and child to discover who the child resembles more")
17
+
18
+ # Backend selector
19
+ backend_choice = st.radio(
20
+ "ML Backend",
21
+ ["🧠 DeepFace", "⚑ InsightFace", "πŸ€— HF Model"],
22
+ horizontal=True,
23
+ help="Select the AI model to use for face analysis",
24
+ )
25
+
26
+ st.divider()
27
+
28
+ # Upload row: Father | Child (center, wider) | Mother
29
+ col_f, col_c, col_m = st.columns([1, 1.3, 1])
30
+
31
+ with col_f:
32
+ st.markdown("#### πŸ‘¨ Father")
33
+ father_file = st.file_uploader(
34
+ "", type=["jpg", "jpeg", "png"], key="father", label_visibility="collapsed"
35
+ )
36
+ if father_file:
37
+ st.image(father_file, use_container_width=True)
38
+
39
+ with col_c:
40
+ st.markdown("#### πŸ§’ Child")
41
+ child_file = st.file_uploader(
42
+ "", type=["jpg", "jpeg", "png"], key="child", label_visibility="collapsed"
43
+ )
44
+ if child_file:
45
+ st.image(child_file, use_container_width=True)
46
+
47
+ with col_m:
48
+ st.markdown("#### πŸ‘© Mother")
49
+ mother_file = st.file_uploader(
50
+ "", type=["jpg", "jpeg", "png"], key="mother", label_visibility="collapsed"
51
+ )
52
+ if mother_file:
53
+ st.image(mother_file, use_container_width=True)
54
+
55
+ st.divider()
56
+
57
+ all_uploaded = all([father_file, child_file, mother_file])
58
+
59
+ if st.button("β–Ά Analyze Resemblance", type="primary", disabled=not all_uploaded):
60
+ with st.spinner("Analyzing faces β€” this may take a moment on first run..."):
61
+ with tempfile.TemporaryDirectory() as tmpdir:
62
+ def save(uploaded, name):
63
+ path = os.path.join(tmpdir, name)
64
+ with open(path, "wb") as f:
65
+ f.write(uploaded.getvalue())
66
+ return path
67
+
68
+ father_path = save(father_file, "father.jpg")
69
+ mother_path = save(mother_file, "mother.jpg")
70
+ child_path = save(child_file, "child.jpg")
71
+
72
+ try:
73
+ if "DeepFace" in backend_choice:
74
+ from backends.deepface_backend import analyze
75
+ elif "InsightFace" in backend_choice:
76
+ from backends.insightface_backend import analyze
77
+ else:
78
+ from backends.hf_backend import analyze
79
+
80
+ result = analyze(father_path, mother_path, child_path)
81
+
82
+ st.success("Analysis complete!")
83
+
84
+ r1, r2, r3 = st.columns(3)
85
+ with r1:
86
+ st.metric("πŸ‘¨ Father resemblance", f"{result['father_score']}%")
87
+ st.progress(result["father_score"] / 100)
88
+ with r2:
89
+ st.metric("πŸ‘© Mother resemblance", f"{result['mother_score']}%")
90
+ st.progress(result["mother_score"] / 100)
91
+ with r3:
92
+ st.metric("πŸ§’ Estimated child age", f"{result['age']} yrs")
93
+
94
+ st.divider()
95
+
96
+ diff = abs(result["father_score"] - result["mother_score"])
97
+ if diff < 2:
98
+ st.info("βš–οΈ Child resembles both parents almost equally!")
99
+ elif result["father_score"] >= result["mother_score"]:
100
+ st.success(f"βœ… Child looks more like **Father πŸ‘¨** ({diff:.1f}% difference)")
101
+ else:
102
+ st.success(f"βœ… Child looks more like **Mother πŸ‘©** ({diff:.1f}% difference)")
103
+
104
+ except ValueError as e:
105
+ st.error(f"⚠️ {e}")
106
+ except Exception as e:
107
+ st.error(f"❌ Analysis failed: {e}")
108
+
109
+ elif not all_uploaded:
110
+ st.info("πŸ‘† Please upload photos of all three family members to begin")