def evaluate_mrz():
    """
    A script for evaluating the current MRZ recognition pipeline by applying it to a list of files in a directory and reporting how well it went.
    """
    parser = argparse.ArgumentParser(description='Run the MRZ OCR recognition algorithm on the sample test data, reporting the quality summary.')
    parser.add_argument('-j', '--jobs', default=1, type=int, help='Number of parallel jobs to run')
    parser.add_argument('-dd', '--data-dir', default=pkg_resources.resource_filename('passporteye.mrz', 'testdata'),
                        help='Read files from this directory instead of the package test files')
    parser.add_argument('-sd', '--success-dir', default=None,
                        help='Copy files with successful (nonzero score) extraction results to this directory')
    parser.add_argument('-fd', '--fail-dir', default=None,
                        help='Copy files with unsuccessful (zero score) extraction resutls to this directory')
    parser.add_argument('-rd', '--roi-dir', default=None,
                        help='Extract ROIs to this directory')
    parser.add_argument('-l', '--limit', default=-1, type=int, help='Only process the first <limit> files in the directory.')
    parser.add_argument('--legacy', action='store_true',
                        help='Use the "legacy" Tesseract OCR engine (--oem 0). Despite the name, it most often results in better '
                        'results. It is not the default option, because it will only work if '
                        'your Tesseract installation includes the legacy *.traineddata files. You can download them at '
                        'https://github.com/tesseract-ocr/tesseract/wiki/Data-Files#data-files-for-version-400-november-29-2016')
    args = parser.parse_args()
    files = sorted(glob.glob(os.path.join(args.data_dir, '*.*')))
    if args.limit >= 0:
        files = files[0:args.limit]

    logging.basicConfig(level=logging.INFO)
    log = logging.getLogger("evaluate_mrz")

    tic = time.time()
    pool = multiprocessing.Pool(args.jobs)
    log.info("Preparing computation for %d files from %s", len(files), args.data_dir)
    log.info("Running %d workers", args.jobs)
    results = []
    save_roi = args.roi_dir is not None
    for d in [args.success_dir, args.fail_dir, args.roi_dir]:
        if d is not None and not os.path.isdir(d):
            os.mkdir(d)

    def valid_score(mrz_):
        return 0 if mrz_ is None else mrz_.valid_score

    def score_change_type(filename, mrz_):
        try:
            new_score = valid_score(mrz_)
            old_score = int(os.path.basename(filename).split('_')[0])
            schange = new_score - old_score
            return '=' if schange == 0 else ('>' if schange > 0 else '<')
        except Exception:
            return '?'

    method_stats = Counter()

    extra_params = '--oem 0' if args.legacy else ''
    for result in pool.imap_unordered(process_file, [(f, save_roi, extra_params) for f in files]):
        filename, mrz_, walltime = result
        results.append(result)
        log.info("Processed %s in %0.2fs (score %d) [%s]", os.path.basename(filename), walltime, valid_score(mrz_), score_change_type(filename, mrz_))
        log.debug("\t%s", mrz_)

        vs = valid_score(mrz_)
        if args.success_dir is not None and vs > 0:
            shutil.copyfile(filename, os.path.join(args.success_dir, '%d_%s' % (vs, os.path.basename(filename))))
        if args.fail_dir is not None and vs == 0:
            shutil.copyfile(filename, os.path.join(args.fail_dir, '%d_%s' % (vs, os.path.basename(filename))))
        if args.roi_dir is not None and mrz_ is not None and 'roi' in mrz_.aux:
            roi_fn = '%d_roi_%s.png' % (vs, os.path.basename(filename))
            io.imsave(os.path.join(args.roi_dir, roi_fn), mrz_.aux['roi'])

        if vs > 0 and 'method' in mrz_.aux:
            method_stats[mrz_.aux['method']] += 1

    num_files = len(results)
    score_changes = [score_change_type(fn, mrz_) for fn, mrz_, wt in results]
    scores = [valid_score(mrz_) for fn, mrz_, wt in results]
    num_perfect = scores.count(100)
    num_invalid = scores.count(0)
    total_score = sum(scores)
    total_computation_walltime = sum([wt for fn, mrz_, wt in results])
    total_walltime = time.time() - tic
    log.info("Completed")
    print("Walltime:          %0.2fs" % total_walltime)
    print("Compute walltime:  %0.2fs" % total_computation_walltime)
    print("Processed files:   %d" % num_files)
    print("Perfect parses:    %d" % num_perfect)
    print("Invalid parses:    %d" % num_invalid)
    print("Improved parses:   %d" % len([x for x in score_changes if x == '>']))
    print("Worsened parses:   %d" % len([x for x in score_changes if x == '<']))
    print("Total score:       %d" % total_score)
    print("Mean score:        %0.2f" % (float(total_score)/num_files))
    print("Mean compute time: %0.2fs" % (total_computation_walltime/num_files))
    print("Methods used:")
    for stat in method_stats.most_common():
        print("  %s: %d" % stat)
A script for evaluating the current MRZ recognition pipeline by applying it to a list of files in a directory and reporting how well it went.