コード例 #1
0
 def test_default_matrix_not_available_and_non_specified(self):
     with pytest.raises(SystemExit):
         parse_quantisation_matrix_argument(
             None,
             WaveletFilters.le_gall_5_3,
             WaveletFilters.le_gall_5_3,
             100,
             0,
         )
コード例 #2
0
 def test_bad_custom_matrix(self, argument):
     with pytest.raises(SystemExit):
         parse_quantisation_matrix_argument(
             argument.split(),
             WaveletFilters.le_gall_5_3,
             WaveletFilters.le_gall_5_3,
             0,
             1,
         )
コード例 #3
0
 def test_use_default_matrix(self):
     assert parse_quantisation_matrix_argument(
         None,
         WaveletFilters.le_gall_5_3,
         WaveletFilters.le_gall_5_3,
         4,
         0,
     ) == QUANTISATION_MATRICES[(
         WaveletFilters.le_gall_5_3,
         WaveletFilters.le_gall_5_3,
         4,
         0,
     )]
コード例 #4
0
 def test_custom_matrix_supplied(self):
     assert parse_quantisation_matrix_argument(
         "0 L 10 1 H 20".split(),
         WaveletFilters.le_gall_5_3,
         WaveletFilters.le_gall_5_3,
         0,
         1,
     ) == {
         0: {
             "L": 10
         },
         1: {
             "H": 20
         },
     }
コード例 #5
0
def main(args=None):
    args = parse_args(args)
    
    # Load precomputed signal bounds
    static_filter_analysis = json.load(args.static_filter_analysis)
    
    quantisation_matrix = parse_quantisation_matrix_argument(
        args.custom_quantisation_matrix,
        static_filter_analysis["wavelet_index"],
        static_filter_analysis["wavelet_index_ho"],
        static_filter_analysis["dwt_depth"],
        static_filter_analysis["dwt_depth_ho"],
    )
    
    analysis_signal_bounds = deserialise_signal_bounds(
        static_filter_analysis["analysis_signal_bounds"]
    )
    synthesis_signal_bounds = deserialise_signal_bounds(
        static_filter_analysis["synthesis_signal_bounds"]
    )
    
    (
        concrete_analysis_signal_bounds,
        concrete_synthesis_signal_bounds,
    ) = evaluate_filter_bounds(
        static_filter_analysis["wavelet_index"],
        static_filter_analysis["wavelet_index_ho"],
        static_filter_analysis["dwt_depth"],
        static_filter_analysis["dwt_depth_ho"],
        analysis_signal_bounds,
        synthesis_signal_bounds,
        args.picture_bit_width,
    )
    
    print(quantisation_index_bound(
        concrete_analysis_signal_bounds,
        quantisation_matrix,
    ))
    
    return 0
コード例 #6
0
                    default=sys.stdout,
                    type=FileType("w"),
                    help="""
        Filename to write the signal range information CSV to. Defaults to
        stdout.
    """)

args = parser.parse_args()

if args.wavelet_index_ho is None:
    args.wavelet_index_ho = args.wavelet_index

args.quant_matrix = parse_quantisation_matrix_argument(
    args.quant_matrix,
    args.wavelet_index,
    args.wavelet_index_ho,
    args.dwt_depth,
    args.dwt_depth_ho,
)

################################################################################
# Read the picture
################################################################################

state = dict(
    wavelet_index=args.wavelet_index,
    wavelet_index_ho=args.wavelet_index_ho,
    dwt_depth=args.dwt_depth,
    dwt_depth_ho=args.dwt_depth_ho,
    quant_matrix=args.quant_matrix,
)
コード例 #7
0
    assert static_filter_analysis["dwt_depth_ho"] == optimised_json[
        "dwt_depth_ho"]

    args.picture_bit_width = optimised_json["picture_bit_width"]

    quantisation_matrix = deserialise_quantisation_matrix(
        optimised_json["quantisation_matrix"])

    synthesis_test_signals = deserialise_test_signals(
        OptimisedTestSignalSpecification,
        optimised_json["optimised_synthesis_test_signals"])
else:
    quantisation_matrix = parse_quantisation_matrix_argument(
        args.custom_quantisation_matrix,
        static_filter_analysis["wavelet_index"],
        static_filter_analysis["wavelet_index_ho"],
        static_filter_analysis["dwt_depth"],
        static_filter_analysis["dwt_depth_ho"],
    )

# Compute signal bounds for all specified bit widths
#
# analysis_bounds_dicts = [{(level, array_name, x, y): (lower_bound, upper_bound), ...}, ...]
# synthesis_bounds_dicts = same as above
concrete_analysis_bounds, concrete_synthesis_bounds = evaluate_filter_bounds(
    static_filter_analysis["wavelet_index"],
    static_filter_analysis["wavelet_index_ho"],
    static_filter_analysis["dwt_depth"],
    static_filter_analysis["dwt_depth_ho"],
    analysis_signal_bounds,
    synthesis_signal_bounds,
コード例 #8
0
ファイル: vc2_bundle.py プロジェクト: bbc/vc2_bit_widths
def parse_args(args=None):
    parser = ArgumentParser(description="""
        Create, or query a compressed bundle containing a set of static filter
        analyses (from vc2-static-filter-analysis) and optimised synthesis test
        patterns (from vc2-optimise-synthesis-test-patterns).
    """)
    
    subparsers = parser.add_subparsers()
    
    parser.add_argument(
        "--verbose", "-v", default=0, action="count",
        help="""
            Show more detailed status information during execution.
        """,
    )
    
    parser.set_defaults(action=None)
    
    create_parser = subparsers.add_parser(
        "create",
        help="""
            Create a bundle file.
        """,
    )
    create_parser.set_defaults(action="create")
    
    create_parser.add_argument(
        "bundle_file",
        type=FileType("wb"),
        help="""
            Filename for the bundle file to create/overwrite.
        """,
    )
    
    create_parser.add_argument(
        "--static-filter-analysis", "-s",
        type=FileType("rb"),
        nargs="+", metavar="JSON_FILE",
        action="append", default=[],
        help="""
            Filenames of the JSON files containing static filter analyses
            produced by vc2-static-filter-analysis.
        """,
    )
    create_parser.add_argument(
        "--optimised-synthesis-test-patterns", "-o",
        type=FileType("rb"),
        nargs="+", metavar="JSON_FILE",
        action="append", default=[],
        help="""
            Filenames of the JSON files containing optimised synthesis test
            patterns produced by vc2-optimise-synthesis-test-patterns.
        """,
    )
    
    ls_parser = subparsers.add_parser(
        "list",
        help="""
            List the contents of a bundle file.
        """,
    )
    ls_parser.set_defaults(action="list")
    
    ls_parser.add_argument(
        "bundle_file",
        type=FileType("rb"),
        help="""
            Filename for the bundle file to list.
        """,
    )
    
    extract_sfa_parser = subparsers.add_parser(
        "extract-static-filter-analysis",
        help="""
            Extract a static filter analysis from the bundle.
        """,
    )
    extract_sfa_parser.set_defaults(action="extract-static-filter-analysis")
    
    extract_ostp_parser = subparsers.add_parser(
        "extract-optimised-synthesis-test-patterns",
        help="""
            Extract a set of optimised synthesis test patterns from the bundle.
        """,
    )
    extract_ostp_parser.set_defaults(action="extract-optimised-synthesis-test-patterns")
    
    # Arguments shared by both extract subcommands
    for sub_parser in [extract_sfa_parser, extract_ostp_parser]:
        sub_parser.add_argument(
            "bundle_file",
            type=FileType("rb"),
            help="""
                Filename for the bundle file to query.
            """,
        )
        sub_parser.add_argument(
            "--output", "-o",
            type=FileType("w"), default=sys.stdout,
            help="""
                Filename for the extracted JSON file. Defaults to stdout.
            """,
        )
        sub_parser.add_argument(
            "--wavelet-index", "-w",
            type=wavelet_index_or_name, required=True,
            help="""
                The VC-2 wavelet index for the wavelet transform. One of: {}.
            """.format(", ".join(
                "{} or {}".format(int(index), index.name)
                for index in WaveletFilters
            )),
        )
        sub_parser.add_argument(
            "--wavelet-index-ho", "-W",
            type=wavelet_index_or_name,
            help="""
                The VC-2 wavelet index for the horizontal parts of the wavelet
                transform. If not specified, assumed to be the same as
                --wavelet-index/-w.
            """,
        )
        sub_parser.add_argument(
            "--dwt-depth", "-d",
            type=int, default=0,
            help="""
                The VC-2 transform depth. Defaults to 0 if not specified.
            """
        )
        sub_parser.add_argument(
            "--dwt-depth-ho", "-D",
            type=int, default=0,
            help="""
                The VC-2 horizontal-only transform depth. Defaults to 0 if not
                specified.
            """
        )
    
    # Add optimised synthesis test pattern specific arguments
    extract_ostp_parser.add_argument(
        "--picture-bit-width", "-b",
        type=int, required=True,
        help="""
            The number of bits in the picture signal.
        """,
    )
    extract_ostp_parser.add_argument(
        "--custom-quantisation-matrix", "-q",
        nargs="+",
        help="""
            Use a custom quantisation matrix for the search. Optional except
            for filters without a default quantisation matrix defined. Should
            be specified as a series 3-argument tuples giving the level,
            orientation and quantisation matrix value for every entry in the
            quantisation matrix.
        """,
    )
    
    args = parser.parse_args(args)
    
    if args.action is None:
        parser.error("Expected a command.")
    
    # Flatten create arguments
    if args.action == "create":
        args.static_filter_analysis = [
            entry
            for lst in args.static_filter_analysis
            for entry in lst
        ]
        args.optimised_synthesis_test_patterns = [
            entry
            for lst in args.optimised_synthesis_test_patterns
            for entry in lst
        ]
    
    
    # Auto-fill horizontal only wavelet
    if args.action in (
        "extract-static-filter-analysis",
        "extract-optimised-synthesis-test-patterns",
    ):
        if args.wavelet_index_ho is None:
            args.wavelet_index_ho = args.wavelet_index
    
    if args.action == "extract-optimised-synthesis-test-patterns":
        args.quantisation_matrix = parse_quantisation_matrix_argument(
            args.custom_quantisation_matrix,
            args.wavelet_index,
            args.wavelet_index_ho,
            args.dwt_depth,
            args.dwt_depth_ho,
        )
    
    return args
コード例 #9
0
def load_filter_analysis(
    static_filter_analysis_file,
    optimised_synthesis_patterns_file,
    quantisation_matrix_argument,
    picture_bit_width,
):
    """
    Load a static filter analysis and optionally a set of optimised synthesis
    test patterns, returning all of the loaded data.
    
    Parameters
    ==========
    static_filter_analysis_file : :py:class:`file`
        An open file ready to read the static filter analysis data from a JSON
        file.
    optimised_synthesis_patterns_file : :py:class:`file` or None
        An open file ready to read a set of optimised synthesis test patterns
        for a JSON file. If None, synthesis test patterns will be read from the
        ``static_filter_analysis_file`` instead.
    quantisation_matrix_argument : [str, ...] or None
        The --custom-quantisation-matrix argument which will be parsed (if
        optimised_synthesis_patterns_file is not provided)
    picture_bit_width : int or None
        The --picture-bit-width argument which will be used if no
        optimised_synthesis_test_patterns file is provided.
    
    Returns
    =======
    wavelet_index : int
    wavelet_index_ho : int
    dwt_depth : int
    dwt_depth_ho : int
    quantisation_matrix : {level: {orient: value, ...}, ...}
    picture_bit_width : int
    max_quantisation_index : int
    concrete_analysis_bounds : {(level, array_name, x, y): (lo, hi), ...}
    concrete_synthesis_bounds : {(level, array_name, x, y): (lo, hi), ...}
    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`, ...}
    """
    # Load precomputed signal bounds
    static_filter_analysis = json.load(static_filter_analysis_file)
    analysis_signal_bounds = deserialise_signal_bounds(
        static_filter_analysis["analysis_signal_bounds"]
    )
    synthesis_signal_bounds = deserialise_signal_bounds(
        static_filter_analysis["synthesis_signal_bounds"]
    )
    
    # Load precomputed test patterns
    analysis_test_patterns = deserialise_test_pattern_specifications(
        TestPatternSpecification,
        static_filter_analysis["analysis_test_patterns"]
    )
    synthesis_test_patterns = deserialise_test_pattern_specifications(
        TestPatternSpecification,
        static_filter_analysis["synthesis_test_patterns"]
    )
    
    # Load optimised synthesis signal
    if optimised_synthesis_patterns_file is not None:
        optimised_json = json.load(optimised_synthesis_patterns_file)
        
        assert static_filter_analysis["wavelet_index"] == optimised_json["wavelet_index"]
        assert static_filter_analysis["wavelet_index_ho"] == optimised_json["wavelet_index_ho"]
        assert static_filter_analysis["dwt_depth"] == optimised_json["dwt_depth"]
        assert static_filter_analysis["dwt_depth_ho"] == optimised_json["dwt_depth_ho"]
        
        picture_bit_width = optimised_json["picture_bit_width"]
        
        quantisation_matrix = deserialise_quantisation_matrix(
            optimised_json["quantisation_matrix"]
        )
        
        synthesis_test_patterns = deserialise_test_pattern_specifications(
            OptimisedTestPatternSpecification,
            optimised_json["optimised_synthesis_test_patterns"]
        )
    else:
        quantisation_matrix = parse_quantisation_matrix_argument(
            quantisation_matrix_argument,
            static_filter_analysis["wavelet_index"],
            static_filter_analysis["wavelet_index_ho"],
            static_filter_analysis["dwt_depth"],
            static_filter_analysis["dwt_depth_ho"],
        )
    
    # Compute signal bounds for all specified bit widths
    #
    # analysis_bounds_dicts = [{(level, array_name, x, y): (lower_bound, upper_bound), ...}, ...]
    # synthesis_bounds_dicts = same as above
    concrete_analysis_bounds, concrete_synthesis_bounds = evaluate_filter_bounds(
        static_filter_analysis["wavelet_index"],
        static_filter_analysis["wavelet_index_ho"],
        static_filter_analysis["dwt_depth"],
        static_filter_analysis["dwt_depth_ho"],
        analysis_signal_bounds,
        synthesis_signal_bounds,
        picture_bit_width,
    )
    
    # Find the maximum quantisation index for each bit width
    max_quantisation_index = quantisation_index_bound(
        concrete_analysis_bounds,
        quantisation_matrix,
    )
    
    return (
        static_filter_analysis["wavelet_index"],
        static_filter_analysis["wavelet_index_ho"],
        static_filter_analysis["dwt_depth"],
        static_filter_analysis["dwt_depth_ho"],
        quantisation_matrix,
        picture_bit_width,
        max_quantisation_index,
        concrete_analysis_bounds,
        concrete_synthesis_bounds,
        analysis_test_patterns,
        synthesis_test_patterns,
    )
コード例 #10
0
def main(args=None):
    args = parse_args(args)

    if args.verbose:
        logging.basicConfig(level=logging.INFO)

    static_filter_analysis = json.load(args.static_filter_analysis)

    quantisation_matrix = parse_quantisation_matrix_argument(
        args.custom_quantisation_matrix,
        static_filter_analysis["wavelet_index"],
        static_filter_analysis["wavelet_index_ho"],
        static_filter_analysis["dwt_depth"],
        static_filter_analysis["dwt_depth_ho"],
    )

    analysis_signal_bounds = deserialise_signal_bounds(
        static_filter_analysis["analysis_signal_bounds"])
    synthesis_signal_bounds = deserialise_signal_bounds(
        static_filter_analysis["synthesis_signal_bounds"])
    synthesis_test_patterns = deserialise_test_pattern_specifications(
        TestPatternSpecification,
        static_filter_analysis["synthesis_test_patterns"])

    (
        concrete_analysis_signal_bounds,
        concrete_synthesis_signal_bounds,
    ) = evaluate_filter_bounds(
        static_filter_analysis["wavelet_index"],
        static_filter_analysis["wavelet_index_ho"],
        static_filter_analysis["dwt_depth"],
        static_filter_analysis["dwt_depth_ho"],
        analysis_signal_bounds,
        synthesis_signal_bounds,
        args.picture_bit_width,
    )

    max_quantisation_index = quantisation_index_bound(
        concrete_analysis_signal_bounds,
        quantisation_matrix,
    )

    random_state = np.random.RandomState(args.seed)

    optimised_synthesis_test_patterns = optimise_synthesis_test_patterns(
        wavelet_index=static_filter_analysis["wavelet_index"],
        wavelet_index_ho=static_filter_analysis["wavelet_index_ho"],
        dwt_depth=static_filter_analysis["dwt_depth"],
        dwt_depth_ho=static_filter_analysis["dwt_depth_ho"],
        quantisation_matrix=quantisation_matrix,
        picture_bit_width=args.picture_bit_width,
        synthesis_test_patterns=synthesis_test_patterns,
        max_quantisation_index=max_quantisation_index,
        random_state=random_state,
        number_of_searches=args.number_of_searches,
        terminate_early=args.terminate_early,
        added_corruption_rate=args.added_corruption_rate,
        removed_corruption_rate=args.removed_corruption_rate,
        base_iterations=args.base_iterations,
        added_iterations_per_improvement=args.added_iterations_per_improvement,
    )

    out = {
        "wavelet_index":
        static_filter_analysis["wavelet_index"],
        "wavelet_index_ho":
        static_filter_analysis["wavelet_index_ho"],
        "dwt_depth":
        static_filter_analysis["dwt_depth"],
        "dwt_depth_ho":
        static_filter_analysis["dwt_depth_ho"],
        "picture_bit_width":
        args.picture_bit_width,
        "quantisation_matrix":
        serialise_quantisation_matrix(quantisation_matrix, ),
        "optimised_synthesis_test_patterns":
        serialise_test_pattern_specifications(
            OptimisedTestPatternSpecification,
            optimised_synthesis_test_patterns,
        )
    }

    json.dump(out, args.output)
    args.output.write("\n")

    return 0