예제 #1
0
    def test_offset_picture(self):
        test_patterns = OrderedDict([
            (
                (1, "Output", 0, 0),
                TPS(
                    pattern=TP({
                        (2, 1): +1,
                        (1, 2): -1,
                    }),
                    pattern_translation_multiple=(4, 4),
                    target=(1, 1),
                    target_translation_multiple=(1, 1),
                ),
            ),
        ])

        width, height = 20, 10

        pictures, locations = pack_test_patterns(width, height, test_patterns)

        assert len(pictures) == 1
        assert list(locations) == list(test_patterns)

        # Should have been assigned to the top-left most point possible
        exp_picture = np.zeros((height, width), dtype=np.int8)
        exp_picture[1, 2] = +1
        exp_picture[2, 1] = -1
        assert np.array_equal(pictures[0], exp_picture)

        assert locations[(1, "Output", 0, 0)] == (0, 1, 1)
예제 #2
0
    def test_simple_packing(self):
        test_patterns = OrderedDict([
            (
                (1, "Output", 0, 0),
                TPS(
                    pattern=TP({
                        (2, 1): +1,
                        (1, 2): -1,
                    }),
                    pattern_translation_multiple=(4, 4),
                    target=(1, 1),
                    target_translation_multiple=(1, 1),
                ),
            ),
            (
                (1, "Output", 0, 1),
                TPS(
                    pattern=TP({
                        (2, 1): +1,
                        (1, 2): +1,
                    }),
                    pattern_translation_multiple=(4, 4),
                    target=(1, 1),
                    target_translation_multiple=(1, 1),
                ),
            ),
        ])

        width, height = 20, 10

        pictures, locations = pack_test_patterns(width, height, test_patterns)

        assert len(pictures) == 1
        assert list(locations) == list(test_patterns)

        exp_picture = np.zeros((height, width), dtype=np.int8)
        # First pattern, top left
        exp_picture[1, 2] = +1
        exp_picture[2, 1] = -1
        # Second pattern, just underneath
        exp_picture[5, 2] = +1
        exp_picture[6, 1] = +1
        assert np.array_equal(pictures[0], exp_picture)

        assert locations[(1, "Output", 0, 0)] == (0, 1, 1)
        assert locations[(1, "Output", 0, 1)] == (0, 1, 2)
예제 #3
0
def generate_test_pictures(
    picture_width,
    picture_height,
    picture_bit_width,
    analysis_test_patterns,
    synthesis_test_patterns,
    synthesis_test_pattern_outputs,
):
    """
    Generate a series of test pictures containing the supplied selection of
    test patterns.
    
    Parameters
    ==========
    picture_width : int
    picture_height : int
        The dimensions of the pictures to generate.
    picture_bit_width : int
        The number of bits in the input pictures.
    analysis_test_patterns : {(level, array_name, x, y): :py:class:`~vc2_bit_widths.patterns.TestPatternSpecification`, ...}
    synthesis_test_patterns : {(level, array_name, x, y): :py:class:`~vc2_bit_widths.patterns.TestPatternSpecification`, ...}
        The individual analysis and synthesis test patterns to be combined. A
        maximising and minimising variant of each pattern will be included in
        the output. See :py:func:`static_filter_analysis` and
        :py:func:`optimise_synthesis_test_patterns`.
    synthesis_test_pattern_outputs : {(level, array_name, x, y): ((lower_bound, qi), (upper_bound, qi)), ...}
        The worst-case quantisation indicies for each synthesis test pattern,
        as computed by :py:func:`evaluate_test_pattern_outputs`.
    
    Returns
    =======
    analysis_pictures : [:py:class:`AnalysisPicture`, ...]
    synthesis_pictures : [:py:class:`SynthesisPicture`, ...]
        A series of test pictures containing correctly aligned instances of
        each supplied test pattern.
        
        Pictures are returned with values in the range 0 to
        (2**picture_bit_width)-1, as expected by a VC-2 encoder.
        
        Each analysis picture includes a subset of the test patterns supplied
        (see :py:class:`AnalysisPicture`). The analysis test pictures are
        intended to be passed to an analysis filter as-is.
        
        Each synthesis test picture includes a subset of the test patterns
        supplied, grouped according to the quantisation index to be used.  The
        synthesis test pictures should first be passed through a synthesis
        filter and then the transform coefficients quantised using the
        quantisation index specified (see :py:class:`SynthesisPicture`). The
        quantised transform coefficients should then be passed through the
        synthesis filter.
    """
    input_min, input_max = unsigned_integer_range(picture_bit_width)
    input_mid = (input_max - input_min + 1) // 2

    # For better packing, the test patterns will be packed in size order,
    # largest first.
    analysis_test_patterns = OrderedDict(
        sorted(
            analysis_test_patterns.items(),
            key=lambda kv: len(kv[1].pattern),
            reverse=True,
        ))
    synthesis_test_patterns = OrderedDict(
        sorted(
            synthesis_test_patterns.items(),
            key=lambda kv: len(kv[1].pattern),
            reverse=True,
        ))

    # Pack analysis signals
    logger.info(
        "Packing %d analysis test patterns...",
        len(analysis_test_patterns) * 2,
    )
    analysis_test_patterns_bipolar = OrderedDict((
        (level, array_name, x, y, maximise),
        spec if maximise else invert_test_pattern_specification(spec),
    ) for (level, array_name, x, y), spec in analysis_test_patterns.items()
                                                 for maximise in [True, False])
    pictures, locations = pack_test_patterns(
        picture_width,
        picture_height,
        analysis_test_patterns_bipolar,
    )
    if len(locations) < len(analysis_test_patterns_bipolar):
        logger.warning(
            "%d analysis test patterns were too large to fit in a "
            "%d x %d picture and were omitted.",
            len(analysis_test_patterns_bipolar) - len(locations),
            picture_width,
            picture_height,
        )
    analysis_pictures = [
        AnalysisPicture(
            make_saturated_picture(picture, input_min, input_max, input_mid),
            [],
        ) for picture in pictures
    ]
    for (level, array_name, x, y, maximise), (picture_index, tx,
                                              ty) in locations.items():
        analysis_pictures[picture_index].test_points.append(
            TestPoint(
                level,
                array_name,
                x,
                y,
                maximise,
                tx,
                ty,
            ))
    logger.info(
        "Packed analysis test patterns into %d pictures.",
        len(analysis_pictures),
    )

    # Group synthesis test patterns by required quantisation index
    logger.info(
        "Packing %d synthesis test patterns...",
        len(synthesis_test_patterns) * 2,
    )
    # {quantisation_index: {(level, array_name, x, y, maximise): spec, ...}, ...}
    synthesis_test_patterns_grouped = defaultdict(OrderedDict)
    for (level, array_name, x, y), spec in synthesis_test_patterns.items():
        (_, minimising_qi), (_,
                             maximising_qi) = synthesis_test_pattern_outputs[(
                                 level, array_name, x, y)]

        synthesis_test_patterns_grouped[maximising_qi][(level, array_name, x,
                                                        y, True)] = spec
        synthesis_test_patterns_grouped[minimising_qi][(
            level, array_name, x, y,
            False)] = invert_test_pattern_specification(spec)

    # Pack the synthesis the test patterns, grouped by QI
    synthesis_pictures = []
    num_too_large = 0
    for qi in sorted(synthesis_test_patterns_grouped):
        pictures, locations = pack_test_patterns(
            picture_width,
            picture_height,
            synthesis_test_patterns_grouped[qi],
        )
        num_too_large += len(
            synthesis_test_patterns_grouped[qi]) - len(locations)

        this_synthesis_pictures = [
            SynthesisPicture(
                make_saturated_picture(picture, input_min, input_max,
                                       input_mid),
                qi,
                [],
            ) for picture in pictures
        ]

        for (level, array_name, x, y, maximise), (picture_index, tx,
                                                  ty) in locations.items():
            this_synthesis_pictures[picture_index].test_points.append(
                TestPoint(
                    level,
                    array_name,
                    x,
                    y,
                    maximise,
                    tx,
                    ty,
                ))

        synthesis_pictures += this_synthesis_pictures
    if len(locations) < len(synthesis_test_patterns_grouped[qi]):
        logger.warning(
            "%d synthesis test patterns were too large to fit in a "
            "%d x %d picture and were omitted.",
            num_too_large,
            picture_width,
            picture_height,
        )
    logger.info(
        "Packed synthesis test patterns into %d pictures.",
        len(synthesis_pictures),
    )

    return (
        analysis_pictures,
        synthesis_pictures,
    )
예제 #4
0
    def test_large_test_patterns_skipped(self):
        test_patterns = OrderedDict([
            (
                (1, "Output", 0, 0),
                TPS(
                    pattern=TP({
                        (1, 0): +1,
                        (0, 1): -1,
                    }),
                    pattern_translation_multiple=(1, 1),
                    target=(1, 1),
                    target_translation_multiple=(1, 1),
                ),
            ),
            (
                (1, "Output", 0, 1),
                TPS(
                    pattern=TP({
                        (100, 0): -1,
                        (0, 100): -1,
                    }),
                    pattern_translation_multiple=(1, 1),
                    target=(1, 1),
                    target_translation_multiple=(1, 1),
                ),
            ),
            (
                (1, "Output", 0, 2),
                TPS(
                    pattern=TP({
                        (1, 0): -1,
                        (0, 1): +1,
                    }),
                    pattern_translation_multiple=(1, 1),
                    target=(1, 1),
                    target_translation_multiple=(1, 1),
                ),
            ),
        ])

        width, height = 20, 10

        pictures, locations = pack_test_patterns(width, height, test_patterns)

        assert len(pictures) == 1
        assert list(locations) == [
            (1, "Output", 0, 0),
            (1, "Output", 0, 2),
        ]

        exp_picture = np.zeros((height, width), dtype=np.int8)
        # First pattern, top left
        exp_picture[0, 1] = +1
        exp_picture[1, 0] = -1
        # Third pattern, underneath
        exp_picture[2, 1] = -1
        exp_picture[3, 0] = +1
        assert np.array_equal(pictures[0], exp_picture)

        assert locations[(1, "Output", 0, 0)] == (0, 1, 1)
        assert locations[(1, "Output", 0, 2)] == (0, 1, 3)
예제 #5
0
    def test_overspill_pictures(self):
        # Tests that allocation can overspill onto extra pictures and that
        # later allocations can be inserted onto any available picture.
        #
        #     +------+------+   +-------------+
        #     |      |      |   |      1      |
        #     |  0   |  2   |   +-------------+
        #     |      |      |   |      3      |
        #     +------+------+   +-------------+
        #
        test_patterns = OrderedDict([
            (
                (1, "Output", 0, 0),
                TPS(
                    pattern=TP({
                        (9, 0): -1,
                        (0, 9): -1,
                    }),
                    pattern_translation_multiple=(1, 1),
                    target=(1, 1),
                    target_translation_multiple=(1, 1),
                ),
            ),
            (
                (1, "Output", 0, 1),
                TPS(
                    pattern=TP({
                        (19, 0): +1,
                        (0, 4): -1,
                    }),
                    pattern_translation_multiple=(1, 1),
                    target=(1, 1),
                    target_translation_multiple=(1, 1),
                ),
            ),
            (
                (1, "Output", 0, 2),
                TPS(
                    pattern=TP({
                        (9, 0): +1,
                        (0, 9): +1,
                    }),
                    pattern_translation_multiple=(1, 1),
                    target=(1, 1),
                    target_translation_multiple=(1, 1),
                ),
            ),
            (
                (1, "Output", 0, 3),
                TPS(
                    pattern=TP({
                        (19, 0): -1,
                        (0, 4): +1,
                    }),
                    pattern_translation_multiple=(1, 1),
                    target=(1, 1),
                    target_translation_multiple=(1, 1),
                ),
            ),
        ])

        width, height = 20, 10

        pictures, locations = pack_test_patterns(width, height, test_patterns)

        assert len(pictures) == 2
        assert list(locations) == list(test_patterns)

        exp_picture_0 = np.zeros((height, width), dtype=np.int8)
        exp_picture_1 = np.zeros((height, width), dtype=np.int8)
        # Pattern 0
        exp_picture_0[0, 9] = -1
        exp_picture_0[9, 0] = -1
        # Pattern 1
        exp_picture_1[0, 19] = +1
        exp_picture_1[4, 0] = -1
        # Pattern 2
        exp_picture_0[0, 19] = +1
        exp_picture_0[9, 10] = +1
        # Pattern 3
        exp_picture_1[5, 19] = -1
        exp_picture_1[9, 0] = +1
        assert np.array_equal(pictures[0], exp_picture_0)
        assert np.array_equal(pictures[1], exp_picture_1)

        assert locations[(1, "Output", 0, 0)] == (0, 1, 1)
        assert locations[(1, "Output", 0, 1)] == (1, 1, 1)
        assert locations[(1, "Output", 0, 2)] == (0, 11, 1)
        assert locations[(1, "Output", 0, 3)] == (1, 1, 6)
예제 #6
0
    def test_target_translation(self):
        # The test patterns should be allocated like so:
        #
        #     +--+----+-----+
        #     |0 | 1  |     |
        #     +--+    |     |
        #     |  +----+-+---+
        #     |  | 2    |   |
        #     |  |      |   |
        #     +--+------+---+
        #
        test_patterns = OrderedDict([
            (
                (1, "Output", 0, 0),
                TPS(
                    pattern=TP({
                        (2, 1): +1,
                        (1, 2): -1,
                    }),
                    pattern_translation_multiple=(4, 4),
                    target=(1, 1),
                    target_translation_multiple=(1, 1),
                ),
            ),
            (
                (1, "Output", 0, 1),
                TPS(
                    pattern=TP({
                        (10, 1): +1,
                        (1, 5): +1,
                    }),
                    pattern_translation_multiple=(4, 4),
                    target=(1, 1),
                    target_translation_multiple=(1, 1),
                ),
            ),
            (
                (1, "Output", 0, 2),
                TPS(
                    pattern=TP({
                        (5, 1): -1,
                        (1, 5): -1,
                    }),
                    pattern_translation_multiple=(4, 4),
                    target=(2, 3),
                    target_translation_multiple=(4, 5),
                ),
            ),
        ])

        width, height = 20, 15

        pictures, locations = pack_test_patterns(width, height, test_patterns)

        assert len(pictures) == 1
        assert list(locations) == list(test_patterns)

        exp_picture = np.zeros((height, width), dtype=np.int8)
        # First pattern, top left
        exp_picture[1, 2] = +1
        exp_picture[2, 1] = -1
        # Second pattern, just to the right
        exp_picture[1, 14] = +1
        exp_picture[5, 5] = +1
        # Third pattern, below-right of both
        exp_picture[13, 5] = -1
        exp_picture[9, 9] = -1
        assert np.array_equal(pictures[0], exp_picture)

        assert locations[(1, "Output", 0, 0)] == (0, 1, 1)
        assert locations[(1, "Output", 0, 1)] == (0, 2, 1)
        assert locations[(1, "Output", 0, 2)] == (0, 2 + 4, 3 + (2 * 5))