File size: 1,991 Bytes
49ce4bd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
from __future__ import annotations

import re

MAX_WORDS = 12

SCENE_PATTERNS = [
    ("variation", r"\bvari(?:ation|ations|ant|ants|ous)\b"),
    ("set of", r"\bsets?\s+of\b"),
    ("collection", r"\bcollections?\b"),
    ("assorted", r"\bassorted\b"),
    ("multiple", r"\bmultiple\b"),
    ("pair of", r"\bpairs?\s+of\b"),
    ("group of", r"\bgroups?\s+of\b"),
    ("scene", r"\bscenes?\b"),
    ("elements", r"\belements?\b"),
    ("featuring", r"\bfeaturing\b"),
    ("different", r"\bdifferent\b"),
]

MODIFIERS = {
    "black", "white", "red", "blue", "green", "yellow", "orange", "purple",
    "pink", "brown", "gray", "grey", "gold", "golden", "silver", "bronze",
    "copper", "beige", "tan", "teal", "cyan", "magenta", "maroon", "navy",
    "ivory", "cream", "turquoise", "lavender", "olive", "crimson", "scarlet",
    "dark", "light", "pale", "bright", "deep", "pastel", "neon", "striped",
    "wooden", "wood", "metal", "metallic", "plastic", "stone", "glass",
    "steel", "iron", "brick", "concrete", "leather", "fabric", "marble",
}

_WORD = re.compile(r"[a-z][a-z'-]*")
_AND = re.compile(r"\band\b")

def _joins_noun_phrases(text):
    parts = _AND.split(text)
    if len(parts) < 2:
        return False
    for left, right in zip(parts[:-1], parts[1:]):
        if "," in left:
            return True
        lw = _WORD.findall(left)
        rw = _WORD.findall(right)
        if not lw or not rw:
            return True
        if lw[-1] in MODIFIERS and rw[0] in MODIFIERS:
            continue
        return True
    return False

def reject_reason(caption):
    if not caption or not caption.strip():
        return "empty"
    text = caption.lower()
    if len(caption.split()) > MAX_WORDS:
        return "too long"
    for name, pattern in SCENE_PATTERNS:
        if re.search(pattern, text):
            return name
    if _joins_noun_phrases(text):
        return "and"
    return None

def is_single_object(caption):
    return reject_reason(caption) is None