face-intel / cores /location /language.py
Marwan
Restructure + add reverse face search (PimEyes-style)
f5eeb1c
Raw
History Blame Contribute Delete
5.23 kB
"""Language / script detection → region inference.
Detects the script of OCR'd text and infers candidate countries/regions.
Pure stdlib — uses Unicode code-point ranges.
"""
from __future__ import annotations
from typing import List
def detect_script(text: str) -> str:
"""Detect the dominant script in a text string.
Returns one of: 'latin', 'cyrillic', 'arabic', 'cjk', 'hangul',
'devanagari', 'thai', 'hebrew', 'greek', 'unknown'.
"""
if not text:
return "unknown"
counts: dict[str, int] = {}
for ch in text:
cp = ord(ch)
if 0x0041 <= cp <= 0x024F or 0x1E00 <= cp <= 0x1EFF:
counts["latin"] = counts.get("latin", 0) + 1
elif 0x0400 <= cp <= 0x04FF:
counts["cyrillic"] = counts.get("cyrillic", 0) + 1
elif 0x0600 <= cp <= 0x06FF or 0x0750 <= cp <= 0x077F:
counts["arabic"] = counts.get("arabic", 0) + 1
elif 0x4E00 <= cp <= 0x9FFF or 0x3400 <= cp <= 0x4DBF:
counts["cjk"] = counts.get("cjk", 0) + 1
elif 0xAC00 <= cp <= 0xD7AF:
counts["hangul"] = counts.get("hangul", 0) + 1
elif 0x0900 <= cp <= 0x097F:
counts["devanagari"] = counts.get("devanagari", 0) + 1
elif 0x0E00 <= cp <= 0x0E7F:
counts["thai"] = counts.get("thai", 0) + 1
elif 0x0590 <= cp <= 0x05FF:
counts["hebrew"] = counts.get("hebrew", 0) + 1
elif 0x0370 <= cp <= 0x03FF:
counts["greek"] = counts.get("greek", 0) + 1
if not counts:
return "unknown"
return max(counts, key=counts.get)
def script_to_regions(script: str) -> List[dict]:
"""Map a script to candidate countries/regions with confidence.
Returns a list of {"country": str, "confidence": float}.
"""
mapping = {
"latin": [
{"country": "United States", "confidence": 0.15},
{"country": "United Kingdom", "confidence": 0.15},
{"country": "France", "confidence": 0.1},
{"country": "Germany", "confidence": 0.1},
{"country": "Spain", "confidence": 0.1},
{"country": "Italy", "confidence": 0.1},
{"country": "Brazil", "confidence": 0.1},
{"country": "Mexico", "confidence": 0.1},
],
"cyrillic": [
{"country": "Russia", "confidence": 0.4},
{"country": "Ukraine", "confidence": 0.15},
{"country": "Belarus", "confidence": 0.1},
{"country": "Bulgaria", "confidence": 0.1},
{"country": "Serbia", "confidence": 0.1},
],
"arabic": [
{"country": "Saudi Arabia", "confidence": 0.15},
{"country": "Egypt", "confidence": 0.15},
{"country": "Iraq", "confidence": 0.1},
{"country": "Algeria", "confidence": 0.1},
{"country": "Morocco", "confidence": 0.1},
{"country": "United Arab Emirates", "confidence": 0.1},
],
"cjk": [
{"country": "China", "confidence": 0.5},
{"country": "Taiwan", "confidence": 0.15},
{"country": "Japan", "confidence": 0.1},
],
"hangul": [
{"country": "South Korea", "confidence": 0.7},
{"country": "North Korea", "confidence": 0.1},
],
"devanagari": [
{"country": "India", "confidence": 0.6},
{"country": "Nepal", "confidence": 0.15},
],
"thai": [
{"country": "Thailand", "confidence": 0.85},
],
"hebrew": [
{"country": "Israel", "confidence": 0.8},
],
"greek": [
{"country": "Greece", "confidence": 0.8},
{"country": "Cyprus", "confidence": 0.1},
],
"unknown": [],
}
return mapping.get(script, [])
def text_to_country_hints(text: str) -> List[dict]:
"""Detect country hints from text content (script + keywords).
Returns a list of {"source": "script"|"keyword", "value": str,
"country": str, "confidence": float}.
"""
if not text:
return []
hints: list[dict] = []
# Script-based
script = detect_script(text)
for region in script_to_regions(script):
hints.append({
"source": "script",
"value": script,
"country": region["country"],
"confidence": region["confidence"],
})
# Keyword-based (very minimal — extend as needed)
text_lower = text.lower()
keyword_map = {
"united states": ("United States", 0.6),
"u.s.a": ("United States", 0.5),
"london": ("United Kingdom", 0.7),
"paris": ("France", 0.7),
"berlin": ("Germany", 0.7),
"tokyo": ("Japan", 0.7),
"beijing": ("China", 0.7),
"moscow": ("Russia", 0.7),
"sydney": ("Australia", 0.7),
"cairo": ("Egypt", 0.7),
"mumbai": ("India", 0.7),
}
for keyword, (country, conf) in keyword_map.items():
if keyword in text_lower:
hints.append({
"source": "keyword",
"value": keyword,
"country": country,
"confidence": conf,
})
return hints