Exemplo n.º 1
0
def synthesis_filter_bounds(expression):
    """
    Find the lower- and upper-bound reachable in a
    :py:class:`~vc2_bit_widths.linexp.LinExp` describing a synthesis filter.
    
    The filter expression must contain only affine error symbols
    (:py:class:`~vc2_bit_widths.linexp.AAError`) and symbols of the form ``((_,
    level, orient), x, y)`` representing transform coefficients.
    
    Parameters
    ==========
    expression : :py:class:`~vc2_bit_widths.linexp.LinExp`
    
    Returns
    =======
    (lower_bound, upper_bound) : :py:class:`~vc2_bit_widths.linexp.LinExp`
        Lower and upper bounds for the signal level in terms of the symbols of
        the form ``LinExp("signal_LEVEL_ORIENT_min")`` and
        ``LinExp("signal_LEVEL_ORIENT_max")``, representing the minimum and
        maximum signal levels for transform coefficients in level ``LEVEL`` and
        orientation ``ORIENT`` respectively.
    """
    # Replace all transform coefficients with affine error terms scaled to
    # appropriate ranges
    expression = LinExp(expression)

    lower_bound = affine_lower_bound(
        expression.subs({
            sym:
            ("coeff_{}_{}_min" if coeff > 0 else "coeff_{}_{}_max").format(
                sym[0][1],
                sym[0][2],
            )
            for sym, coeff in expression
            if sym is not None and not isinstance(sym, AAError)
        }))

    upper_bound = affine_upper_bound(
        expression.subs({
            sym:
            ("coeff_{}_{}_min" if coeff < 0 else "coeff_{}_{}_max").format(
                sym[0][1],
                sym[0][2],
            )
            for sym, coeff in expression
            if sym is not None and not isinstance(sym, AAError)
        }))

    return (lower_bound, upper_bound)
Exemplo n.º 2
0
def analysis_filter_bounds(expression):
    """
    Find the lower- and upper-bound reachable in a
    :py:class:`~vc2_bit_widths.linexp.LinExp` describing an analysis filter.
    
    The filter expression must consist of only affine error symbols
    (:py:class:`~vc2_bit_widths.linexp.AAError`) and symbols of the form ``(_,
    x, y)`` representing pixel values in an input picture.
    
    Parameters
    ==========
    expression : :py:class:`~vc2_bit_widths.linexp.LinExp`
    
    Returns
    =======
    lower_bound : :py:class:`~vc2_bit_widths.linexp.LinExp`
    upper_bound : :py:class:`~vc2_bit_widths.linexp.LinExp`
        Algebraic expressions for the lower and upper bounds for the signal
        level. These expressions are given in terms of the symbols
        ``LinExp("signal_min")`` and ``LinExp("signal_max")``, which represent
        the minimum and maximum picture signal levels respectively.
    """
    signal_min = LinExp("signal_min")
    signal_max = LinExp("signal_max")

    expression = LinExp(expression)

    lower_bound = affine_lower_bound(
        expression.subs({
            sym: signal_min if coeff > 0 else signal_max
            for sym, coeff in expression
            if sym is not None and not isinstance(sym, AAError)
        }))

    upper_bound = affine_upper_bound(
        expression.subs({
            sym: signal_min if coeff < 0 else signal_max
            for sym, coeff in expression
            if sym is not None and not isinstance(sym, AAError)
        }))

    return (lower_bound, upper_bound)
Exemplo n.º 3
0
def test_integration():
    # A simple integration test which computes signal bounds for a small
    # transform operation

    filter_params = LIFTING_FILTERS[WaveletFilters.haar_with_shift]
    dwt_depth = 1
    dwt_depth_ho = 1

    input_picture_array = SymbolArray(2)
    analysis_coeff_arrays, analysis_intermediate_values = analysis_transform(
        filter_params,
        filter_params,
        dwt_depth,
        dwt_depth_ho,
        input_picture_array,
    )

    input_coeff_arrays = make_symbol_coeff_arrays(dwt_depth, dwt_depth_ho)
    synthesis_output, synthesis_intermediate_values = synthesis_transform(
        filter_params,
        filter_params,
        dwt_depth,
        dwt_depth_ho,
        input_coeff_arrays,
    )

    signal_min = LinExp("signal_min")
    signal_max = LinExp("signal_max")

    example_range = {signal_min: -512, signal_max: 511}

    # Input signal bounds should be as specified
    assert analysis_filter_bounds(
        analysis_intermediate_values[(2, "Input")][0, 0], ) == (signal_min,
                                                                signal_max)

    # Output of final analysis filter should require a greater depth (NB: for
    # the Haar transform it is the high-pass bands which gain the largest
    # signal range)
    analysis_output_lower, analysis_output_upper = analysis_filter_bounds(
        analysis_intermediate_values[(1, "H")][0, 0], )
    assert analysis_output_lower.subs(example_range) < signal_min.subs(
        example_range)
    assert analysis_output_upper.subs(example_range) > signal_max.subs(
        example_range)

    example_coeff_range = {
        "coeff_{}_{}_{}".format(level, orient, minmax):
        maximum_dequantised_magnitude(
            int(round(value.subs(example_range).constant)))
        for level, orients in analysis_coeff_arrays.items()
        for orient, expr in orients.items()
        for minmax, value in zip(["min", "max"], analysis_filter_bounds(expr))
    }

    # Signal range should shrink down by end of synthesis process but should
    # still be larger than the original signal
    final_output_lower, final_output_upper = synthesis_filter_bounds(
        synthesis_output[0, 0])

    assert final_output_upper.subs(
        example_coeff_range) < analysis_output_upper.subs(example_range)
    assert final_output_lower.subs(
        example_coeff_range) > analysis_output_lower.subs(example_range)

    assert final_output_upper.subs(example_coeff_range) > signal_max.subs(
        example_range)
    assert final_output_lower.subs(example_coeff_range) < signal_min.subs(
        example_range)