Esempio n. 1
0
def test_relation():
    s1 = shape.SHAPE_IMPLS['square'](color_='red', x=30, y=30)
    # S2 is below - higher coordinates
    s2 = shape.SHAPE_IMPLS['square'](color_='blue', x=40, y=40)

    assert s1.left(s2)
    assert not s1.left(s1)
    assert not s1.right(s2)
    assert not s2.right(s2)

    assert s1.above(s2)
    assert s2.below(s1)
    assert not s1.below(s2)
    assert not s2.above(s1)

    # left
    cfg = config.SpatialConfig((('red', 'square'), ('blue', 'square')), 0, 0)
    assert config.has_relation(s1, s2, cfg.relation, cfg.dir)
    assert not config.has_relation(s2, s1, cfg.relation, cfg.dir)

    # right
    cfg = config.SpatialConfig((('red', 'square'), ('blue', 'square')), 0, 1)
    assert config.has_relation(s2, s1, cfg.relation, cfg.dir)
    assert not config.has_relation(s1, s2, cfg.relation, cfg.dir)

    # below
    cfg = config.SpatialConfig((('red', 'square'), ('blue', 'square')), 1, 0)
    assert config.has_relation(s2, s1, cfg.relation, cfg.dir)
    assert not config.has_relation(s1, s2, cfg.relation, cfg.dir)

    # above
    cfg = config.SpatialConfig((('red', 'square'), ('blue', 'square')), 1, 1)
    assert config.has_relation(s1, s2, cfg.relation, cfg.dir)
    assert not config.has_relation(s2, s1, cfg.relation, cfg.dir)
Esempio n. 2
0
def test_relation_lang():
    cfg = config.SpatialConfig((('red', 'square'), ('blue', 'square')), 0, 0)
    assert lang.fmt_config(cfg) == 'red square left blue square'

    cfg = config.SpatialConfig((('red', 'square'), ('blue', 'square')), 0, 1)
    assert lang.fmt_config(cfg) == 'red square right blue square'

    cfg = config.SpatialConfig((('red', 'square'), ('blue', 'square')), 1, 0)
    assert lang.fmt_config(cfg) == 'red square below blue square'

    cfg = config.SpatialConfig((('red', 'square'), ('blue', 'square')), 1, 1)
    assert lang.fmt_config(cfg) == 'red square above blue square'
Esempio n. 3
0
def test_matches_shapes():
    cfg = config.SpatialConfig((('red', None), ('blue', 'square')), 0, 0)

    s1 = shape.SHAPE_IMPLS['square'](color_='red')
    assert cfg.matches_shapes(s1) == [0]

    s2 = shape.SHAPE_IMPLS['square'](color_='blue')
    assert cfg.matches_shapes(s2) == [1]

    cfg = config.SpatialConfig((('red', None), (None, 'square')), 0, 0)

    s1 = shape.SHAPE_IMPLS['square'](color_='red')
    assert cfg.matches_shapes(s1) == [0, 1]

    s2 = shape.SHAPE_IMPLS['square'](color_='blue')
    assert cfg.matches_shapes(s2) == [1]

    s2 = shape.SHAPE_IMPLS['triangle'](color_='blue')
    assert cfg.matches_shapes(s2) == []
Esempio n. 4
0
 def random_config_spatial(self):
     # 0 -> only shape specified
     # 1 -> only color specified
     # 2 -> only both specified
     shape_1_spec = config.ShapeSpec(random.randint(3))
     shape_2_spec = config.ShapeSpec(random.randint(3))
     shape_1 = self.random_shape_from_spec(shape_1_spec)
     shape_2 = self.random_shape_from_spec(shape_2_spec)
     if shape_1 == shape_2:
         return self.random_config_spatial()
     relation = random.randint(2)
     relation_dir = random.randint(2)
     return config.SpatialConfig((shape_1, shape_2), relation, relation_dir)
Esempio n. 5
0
def test_does_not_validate_1():
    cfg = config.SpatialConfig((('red', 'square'), ('blue', 'square')), 0, 0)
    s1 = shape.SHAPE_IMPLS['square'](color_='red', x=30, y=30)
    s2 = shape.SHAPE_IMPLS['square'](color_='blue', x=40, y=30)

    s3 = shape.SHAPE_IMPLS['triangle'](color_='blue')

    assert not cfg.does_not_validate([s1], s2)
    assert not cfg.does_not_validate([s2], s1)

    assert not cfg.does_not_validate([s1, s2], s1)
    assert not cfg.does_not_validate([s1, s2], s2)

    assert cfg.does_not_validate([s1, s2], s3)
    assert not cfg.does_not_validate([s1, s3], s2)
    assert not cfg.does_not_validate([s2, s3, s1], s1)
Esempio n. 6
0
def test_matching():
    cfg = config.SpatialConfig((('red', 'square'), ('blue', 'square')), 0, 0)
    s1 = shape.SHAPE_IMPLS['square'](color_='red', x=30, y=30)
    s2 = shape.SHAPE_IMPLS['square'](color_='blue', x=40, y=30)
    assert config.matches(cfg.shapes[0], s1)
    assert config.matches(cfg.shapes[1], s2)
    assert not config.matches(cfg.shapes[1], s1)
    assert not config.matches(cfg.shapes[0], s2)

    assert config.matches((None, None), s1)
    assert config.matches((None, None), s2)

    assert config.matches(('red', None), s1)
    assert not config.matches(('red', None), s2)

    assert config.matches((None, 'square'), s1)
    assert config.matches((None, 'square'), s2)
Esempio n. 7
0
    def invalidate_spatial(self, cfg):
        # Invalidate by randomly choosing one property to change:
        ((shape_1_color, shape_1_shape),
         (shape_2_color, shape_2_shape)), relation, relation_dir = cfg
        properties = []
        if shape_1_color is not None:
            properties.append(config.ConfigProps.SHAPE_1_COLOR)
        if shape_1_shape is not None:
            properties.append(config.ConfigProps.SHAPE_1_SHAPE)
        if shape_2_color is not None:
            properties.append(config.ConfigProps.SHAPE_2_COLOR)
        if shape_2_shape is not None:
            properties.append(config.ConfigProps.SHAPE_2_SHAPE)
        sp = len(properties)
        # Invalidate relations half of the time
        for _ in range(sp):
            properties.append(config.ConfigProps.RELATION_DIR)
        # Randomly select property to invalidate
        # TODO: Support for invalidating multiple properties
        invalid_prop = random.choice(properties)

        if invalid_prop == config.ConfigProps.SHAPE_1_COLOR:
            inv_cfg = ((self.new_color(shape_1_color), shape_1_shape),
                       (shape_2_color, shape_2_shape)), relation, relation_dir
        elif invalid_prop == config.ConfigProps.SHAPE_1_SHAPE:
            inv_cfg = ((shape_1_color, self.new_shape(shape_1_shape)),
                       (shape_2_color, shape_2_shape)), relation, relation_dir
        elif invalid_prop == config.ConfigProps.SHAPE_2_COLOR:
            inv_cfg = ((shape_1_color, shape_1_shape),
                       (self.new_color(shape_2_color),
                        shape_2_shape)), relation, relation_dir
        elif invalid_prop == config.ConfigProps.SHAPE_2_SHAPE:
            inv_cfg = ((shape_1_color, shape_1_shape),
                       (shape_2_color,
                        self.new_shape(shape_2_shape))), relation, relation_dir
        elif invalid_prop == config.ConfigProps.RELATION_DIR:
            inv_cfg = ((shape_1_color, shape_1_shape),
                       (shape_2_color,
                        shape_2_shape)), relation, 1 - relation_dir
        else:
            raise RuntimeError
        return config.SpatialConfig(*inv_cfg)
Esempio n. 8
0
def test_does_not_validate_3():
    # i.e. above
    cfg = config.SpatialConfig((('green', None), (None, 'triangle')), 1, 1)
    s1 = shape.SHAPE_IMPLS['ellipse'](color_='green', x=0, y=20)
    s2 = shape.SHAPE_IMPLS['triangle'](color_='white', x=0, y=30)

    assert not cfg.does_not_validate([s2], s1)
    assert not cfg.does_not_validate([s1], s2)

    assert not cfg.does_not_validate([s1, s2], s1)
    assert not cfg.does_not_validate([s1, s2], s2)

    s3 = shape.SHAPE_IMPLS['triangle'](color_='red', x=0, y=31)
    assert not cfg.does_not_validate([s1, s2], s3)
    s4 = shape.SHAPE_IMPLS['triangle'](color_='red', x=0, y=18)
    assert cfg.does_not_validate([s1, s2], s4)

    s5 = shape.SHAPE_IMPLS['square'](color_='green', x=0, y=25)
    assert not cfg.does_not_validate([s1, s2], s5)
    s6 = shape.SHAPE_IMPLS['circle'](color_='green', x=0, y=35)
    assert cfg.does_not_validate([s1, s2], s6)
Esempio n. 9
0
def test_does_not_validate_2():
    cfg = config.SpatialConfig((('red', None), ('blue', None)), 0, 0)
    s1 = shape.SHAPE_IMPLS['square'](color_='red')
    s1.x = 30
    s1.y = 30
    s2 = shape.SHAPE_IMPLS['square'](color_='blue')
    s2.x = 40
    s2.y = 30

    assert not cfg.does_not_validate([s1], s2)

    assert not cfg.does_not_validate([s1], s2)
    assert not cfg.does_not_validate([s2], s1)

    s3 = shape.SHAPE_IMPLS['triangle'](color_='red', x=10, y=10)
    assert not cfg.does_not_validate([s1, s2], s3)

    s4 = shape.SHAPE_IMPLS['triangle'](color_='red', x=39, y=10)
    assert not cfg.does_not_validate([s1, s2], s4)

    s5 = shape.SHAPE_IMPLS['triangle'](color_='red', x=41, y=10)
    assert cfg.does_not_validate([s1, s2], s5)
Esempio n. 10
0
    def generate_spatial(self, cfg, label, n_caps_per_image):
        """
        Generate a single spatial relation according to the config,
        invalidating it if the label is 0.
        """
        cfg_attempts = 0
        while cfg_attempts < c.MAX_INVALIDATE_ATTEMPTS:
            new_cfg = cfg if label else self.invalidate_spatial(cfg)
            (ss1, ss2), relation, relation_dir = new_cfg
            s2 = self.add_shape_from_spec(ss2, relation, relation_dir)

            # Place second shape
            attempts = 0
            while attempts < c.MAX_PLACEMENT_ATTEMPTS:
                s1 = self.add_shape_rel(ss1, s2, relation, relation_dir)
                if not s2.intersects(s1):
                    break
                attempts += 1
            else:
                raise RuntimeError(
                    "Could not place shape onto image without intersection")

            if label:  # Positive example
                break
            elif cfg.does_not_validate([s1], s2):
                break
            else:
                # print(f"Shapes {[s1, s2]} for invalid config '{str(new_cfg)}' validates the original config '{str(cfg)}' (attempt {cfg_attempts})")
                assert True

            cfg_attempts += 1

        # Place distractor shapes
        shapes = [s1, s2]
        n_dist = self.sample_n_distractor()
        for _ in range(n_dist):
            attempts = 0
            while attempts < c.MAX_DISTRACTOR_PLACEMENT_ATTEMPTS:
                dss = self.sample_distractor(existing_shapes=shapes)
                ds = self.add_shape(dss)
                # No intersections
                if not any(ds.intersects(s) for s in shapes):
                    if label:
                        shapes.append(ds)
                        break
                    else:
                        # If this is a *negative* example, we should not have
                        # the relation expressed by the original config
                        if cfg.does_not_validate(shapes, ds):
                            shapes.append(ds)
                            break
                        else:
                            #  print(f"Adding new shape {ds} to existing shapes {shapes} validates the original config {str(cfg)} (attempt {attempts})")
                            assert True
                attempts += 1
            else:
                raise RuntimeError("Could not place distractor onto "
                                   "image without intersection")

        distractor_configs_to_cap = []
        non_target_pairs = [(i, j) for i in range(len(shapes))
                            for j in range(len(shapes)) if i != j]
        cfgs_to_cap = np.random.permutation(np.arange(len(non_target_pairs)))
        rel_to_cap_idx = np.random.randint(0, 2, (len(non_target_pairs), ))
        successes = 0
        i = 0
        flipped = False
        while successes < n_caps_per_image:
            if i == len(non_target_pairs):
                if not flipped:
                    flipped = True
                    i = 0
                    rel_to_cap_idx = 1 - rel_to_cap_idx  # change rel to cap and retry
                else:
                    raise RuntimeError(
                        'Not distinct pairs to make captions about')
            shape_1_to_cap = shapes[non_target_pairs[cfgs_to_cap[i]][0]]
            shape_2_to_cap = shapes[non_target_pairs[cfgs_to_cap[i]][1]]
            rel_to_cap = rel_to_cap_idx[i]

            i += 1

            if rel_to_cap == 0:
                if shape_1_to_cap.x >= shape_2_to_cap.x + c.BUFFER:
                    rel_dir_to_cap = 1
                elif shape_1_to_cap.x <= shape_2_to_cap.x - c.BUFFER:
                    rel_dir_to_cap = 0
                else:
                    continue
            else:
                if shape_1_to_cap.y <= shape_2_to_cap.y - c.BUFFER:
                    rel_dir_to_cap = 1
                elif shape_1_to_cap.y >= shape_2_to_cap.y + c.BUFFER:
                    rel_dir_to_cap = 0
                else:
                    continue

            spec_1 = np.random.randint(0, 3)
            if spec_1 == 0:
                shape_1_to_cap = (shape_1_to_cap.color, shape_1_to_cap.name)
            elif spec_1 == 1:
                shape_1_to_cap = (shape_1_to_cap.color, None)
            else:
                shape_1_to_cap = (None, shape_1_to_cap.name)

            spec_2 = np.random.randint(0, 3)
            if spec_2 == 0:
                shape_2_to_cap = (shape_2_to_cap.color, shape_2_to_cap.name)
            elif spec_2 == 1:
                shape_2_to_cap = (shape_2_to_cap.color, None)
            else:
                shape_2_to_cap = (None, shape_2_to_cap.name)

            distractor_configs_to_cap.append(
                config.SpatialConfig((shape_1_to_cap, shape_2_to_cap),
                                     rel_to_cap, rel_dir_to_cap))
            successes += 1

        return new_cfg, shapes, distractor_configs_to_cap