Exemple #1
0
def count_cropobjects_and_relationships(annot_file):
    cropobjects = parse_cropobject_list(annot_file)
    n_inlinks = 0
    for c in cropobjects:
        if c.inlinks is not None:
            n_inlinks += len(c.inlinks)
    return len(cropobjects), n_inlinks
Exemple #2
0
def main(args):
    logging.info('Starting main...')
    _start_time = time.clock()

    ##########################################################################
    logging.info('Import the CropObject list')
    if not os.path.isfile(args.annot):
        raise ValueError('Annotation file {0} not found!'
                         ''.format(args.annot))
    cropobjects = parse_cropobject_list(args.annot)

    output_cropobjects = add_staff_relationships(
        cropobjects,
        notehead_staffspace_threshold=args.notehead_staffspace_threshold)

    ##########################################################################
    logging.info('Export the combined list.')
    cropobject_string = export_cropobject_list(output_cropobjects)

    if args.export is not None:
        with open(args.export, 'w') as hdl:
            hdl.write(cropobject_string)
    else:
        print(cropobject_string)

    _end_time = time.clock()
    logging.info('add_staff_reationships.py done in {0:.3f} s'
                 ''.format(_end_time - _start_time))
Exemple #3
0
def main(args):
    logging.info('Starting main...')
    _start_time = time.clock()

    # Parse individual CropObject lists.
    cropobject_lists = []
    _n_parsed_cropobjects = 0
    for i, f in enumerate(args.input):
        cs = parse_cropobject_list(f)
        cropobject_lists.append(cs)

        # Logging progress
        _n_parsed_cropobjects += len(cs)
        if i % 10 == 0 and i > 0:
            _time_parsing = time.clock() - _start_time
            _cropobjects_per_second = _n_parsed_cropobjects / _time_parsing
            logging.info('Parsed {0} cropobjects in {1:.2f} s ({2:.2f} objs/s)'
                         ''.format(_n_parsed_cropobjects, _time_parsing,
                                   _cropobjects_per_second))

    # Merge the CropObject lists into one.
    # This is done so that the resulting object graph can be manipulated
    # at once, without objid clashes.
    cropobjects = merge_cropobject_lists(*cropobject_lists)

    edges = export_cropobject_graph(cropobjects)

    _parse_end_time = time.clock()
    logging.info('Parsing took {0:.2f} s'.format(_parse_end_time -
                                                 _start_time))

    ##########################################################################
    # Analysis

    # Here's where the results are stored, for export into various
    # formats. (Currently, we only print them.)
    stats = compute_cropobject_stats(cropobjects, edges=edges)

    ##########################################################################
    # Export
    if args.emit == 'print':
        emit_stats_pprint(stats)
    # More export options:
    #  - json
    #  - latex table

    _end_time = time.clock()
    logging.info('analyze_annotations.py done in {0:.3f} s'
                 ''.format(_end_time - _start_time))
def main(args):
    logging.info('Starting main...')
    _start_time = time.clock()

    # Your code goes here
    ##########################################################################
    logging.info('Import the CropObject list')
    if not os.path.isfile(args.annot):
        raise ValueError('Annotation file {0} not found!'
                         ''.format(args.annot))
    cropobjects = parse_cropobject_list(args.annot)

    ##########################################################################
    staff_cropobjects_dict = {c.objid: c for c in cropobjects
                              if c.clsname in STAFF_CLSNAMES}

    output_cropobjects = []
    for c in cropobjects:
        if c.objid in staff_cropobjects_dict:
            continue
        new_c = copy.deepcopy(c)
        new_c.inlinks = [i for i in c.inlinks
                         if i not in staff_cropobjects_dict]
        new_c.outlinks = [o for o in c.outlinks
                          if o not in staff_cropobjects_dict]
        output_cropobjects.append(new_c)

    ##########################################################################
    logging.info('Export the stripped list.')
    cropobject_string = export_cropobject_list(output_cropobjects)

    if args.export is not None:
        with open(args.export, 'w') as hdl:
            hdl.write(cropobject_string)
    else:
        print(cropobject_string)

    _end_time = time.clock()
    logging.info('strip_staffline_symbols.py done in {0:.3f} s'.format(_end_time - _start_time))
Exemple #5
0
def main(args):
    logging.info('Starting main...')
    _start_time = time.clock()

    # The algorithm:
    #  - build the cost function(s) for a pair of CropObjects
    #  - align the objects, using the cost function

    # First alignment: try just matching a predicted object to the nearest
    # true object.
    # First distance function: proportion of shared pixels.
    # Rule: if two objects don't share a pixel, they cannot be considered related.
    # Object classes do not factor into this so far.

    truth = parse_cropobject_list(args.true)
    prediction = parse_cropobject_list(args.prediction)

    _parse_time = time.clock()
    logging.info(
        'Parsing {0} true and {1} prediction cropobjects took {2:.2f} s'
        ''.format(len(truth), len(prediction), _parse_time - _start_time))

    r, p, f = cropobjects_rpf(truth, prediction)

    _rpf_time = time.clock()
    logging.info('Computing {0} entries of r/p/f matrices took {1:.2f} s'
                 ''.format(
                     len(truth) * len(prediction), _rpf_time - _parse_time))

    alignment_tp = align_cropobjects(truth, prediction, fscore=f)
    alignment_pt = align_cropobjects(prediction, truth, fscore=f.T)

    # Intersect alignments
    _aln_tp_set = frozenset(alignment_tp)
    alignment_tp_symmetric = [
        (t, p) for p, t in alignment_pt
        if (t,
            p) in _aln_tp_set and (truth[t].clsname == prediction[p].clsname)
    ]
    truth_not_aligned = [
        t for p, t in alignment_pt if (t, p) not in alignment_tp_symmetric
    ]
    n_truth_not_aligned = len(truth_not_aligned)
    preds_not_aligned = [
        p for t, p in alignment_tp if (t, p) not in alignment_tp_symmetric
    ]
    n_preds_not_aligned = len(preds_not_aligned)
    n_not_aligned = n_truth_not_aligned + n_preds_not_aligned

    _aln_time = time.clock()
    logging.info('Computing alignment took {0:.2f} s'
                 ''.format(_aln_time - _rpf_time))

    # Now compute agreement: precision and recall on pixels
    # of the aligned CropObjects.

    # We apply strict clsnames only here, after the CropObjects have been
    # aligned to each other using pixel metrics.
    _strict_clsnames = (not args.no_strict_clsnames)
    total_r, total_p, total_f = rpf_given_alignment(
        alignment_tp_symmetric,
        r,
        p,
        n_not_aligned=n_not_aligned,
        strict_clsnames=_strict_clsnames,
        truths=truth,
        predictions=prediction)

    if not args.print_fscore_only:
        print('Truth objs.:\t{0}'.format(len(truth)))
        print('Pred. objs.:\t{0}'.format(len(prediction)))
        print('Aligned objs.:\t{0}'.format(len(alignment_tp_symmetric)))
        print('==============================================')
        print('Recall:\t\t{0:.3f}\nPrecision:\t{1:.3f}\nF-score:\t{2:.3f}'
              ''.format(total_r, total_p, total_f))
        print('')
    else:
        print('{0:.3f}'.format(total_f))
        return

    if args.log_alignment:
        print('==============================================')
        print('Alignments:\n{0}'.format('\n'.join([
            '({0}: {1}) -- ({2}: {3})'.format(truth[t].objid, truth[t].clsname,
                                              prediction[p].objid,
                                              prediction[p].clsname)
            for t, p in alignment_tp_symmetric
        ])))
        print('Truth, not aligned:\n{0}'.format('\n'.join([
            '({0}: {1})'.format(truth[t].objid, truth[t].clsname)
            for t in truth_not_aligned
        ])))
        print('Preds, not aligned:\n{0}'.format('\n'.join([
            '({0}: {1})'.format(prediction[p].objid, prediction[p].clsname)
            for p in preds_not_aligned
        ])))

    ##########################################################################
    # Check if the alignment is a pairing -- find truth objects
    # with more than one prediction aligned to them.
    if args.analyze_alignment:
        t_aln_dict = collections.defaultdict(list)
        for i, j in alignment_tp_symmetric:
            t_aln_dict[i].append(prediction[j])

        multiple_truths = [
            truth[i] for i in t_aln_dict if len(t_aln_dict[i]) > 1
        ]
        multiple_truths_aln_dict = {
            t: t_aln_dict[t]
            for t in t_aln_dict if len(t_aln_dict[t]) > 1
        }

        print('Truth multi-aligned CropObject classes:\n{0}'
              ''.format(
                  pprint.pformat({(truth[t].objid, truth[t].clsname):
                                  [(p.objid, p.clsname) for p in t_aln_dict[t]]
                                  for t in multiple_truths_aln_dict})))

    ##########################################################################
    # Check if the aligned objects have the same classes
    if args.analyze_clsnames:
        different_clsnames_pairs = []
        for i, j in alignment_tp_symmetric:
            if truth[i].clsname != prediction[j].clsname:
                different_clsnames_pairs.append((truth[i], prediction[j]))
        print('Aligned pairs with different clsnames:\n{0}'
              ''.format('\n'.join([
                  '{0}.{1}\t{2}.{3}'
                  ''.format(t.objid, t.clsname, p.objid, p.clsname)
                  for t, p in different_clsnames_pairs
              ])))

    _end_time = time.clock()
    logging.info('analyze_agreement.py done in {0:.3f} s'.format(_end_time -
                                                                 _start_time))
Exemple #6
0
def main(args):
    logging.info('Starting main...')
    _start_time = time.clock()

    # Your code goes here
    if not os.path.isfile(args.annot):
        raise ValueError('Annotation file {0} not found!'
                         ''.format(args.annot))
    cropobjects = parse_cropobject_list(args.annot)

    pitch_inference_engine = PitchInferenceEngine()
    time_inference_engine = OnsetsInferenceEngine(cropobjects=cropobjects)

    logging.info('Running pitch inference.')
    pitches, pitch_names = pitch_inference_engine.infer_pitches(
        cropobjects, with_names=True)
    # durations = inference_engine.durations_beats

    # Logging
    #pitch_names = {objid: midi2pitch_name(midi_code)
    #               for objid, midi_code in pitches.items()}

    # Export
    logging.info('Adding pitch information to <Data> attributes.')
    for c in cropobjects:
        if c.objid in pitches:
            midi_pitch_code = pitches[c.objid]
            pitch_step, pitch_octave = pitch_names[c.objid]
            # beats = durations[c.objid]
            # if len(beats) > 1:
            #     logging.warn('Notehead {0}: multiple possible beats: {1}'
            #                  ''.format(c.uid, beats))
            #     b = beats[0]
            # else:
            #     b = beats[0]
            if c.data is None:
                c.data = dict()
            c.data['midi_pitch_code'] = midi_pitch_code
            c.data['normalized_pitch_step'] = pitch_step
            c.data['pitch_octave'] = pitch_octave

    logging.info('Adding duration info to <Data> attributes.')
    durations = time_inference_engine.durations(cropobjects)
    logging.info('Total durations: {0}'.format(len(durations)))
    for c in cropobjects:
        if c.objid in durations:
            c.data['duration_beats'] = durations[c.objid]

    logging.info('Some durations: {0}'.format(sorted(durations.items())[:10]))

    logging.info('Adding onset info to <Data> attributes.')
    onsets = time_inference_engine.onsets(cropobjects)
    logging.info('Total onsets: {0}'.format(len(onsets)))
    for c in cropobjects:
        if c.objid in onsets:
            c.data['onset_beats'] = onsets[c.objid]

    if args.export is not None:
        with open(args.export, 'w') as hdl:
            hdl.write(export_cropobject_list(cropobjects))
            hdl.write('\n')
    else:
        print(export_cropobject_list(cropobjects))

    if args.midi is not None:
        midi_builder = MIDIBuilder()
        mf = midi_builder.build_midi(pitches, durations, onsets)
        with open(args.midi, 'wb') as hdl:
            mf.writeFile(hdl)

    _end_time = time.clock()
    logging.info('infer_pitches.py done in {0:.3f} s'.format(_end_time -
                                                             _start_time))
Exemple #7
0
def main(args):
    logging.info('Starting main...')
    _start_time = time.clock()

    ########################################################
    # Load gt image.
    logging.info('Loading staffline image.')
    #  - Initialize Dataset. This checks for the root.

    if args.staff_imfile is None:
        cvc_dataset = CVC_MUSCIMA(root=args.root)
        args.staff_imfile = cvc_dataset.imfile(page=args.number,
                                               writer=args.writer,
                                               distortion='ideal',
                                               mode='staff_only')

    # - Load the image.
    gt = (imread(args.staff_imfile, as_grey=True) * 255).astype('uint8')

    # - Cast as binary mask.
    gt[gt > 0] = 1

    ########################################################
    # Locate stafflines in gt image.
    logging.info('Getting staffline connected components.')

    #  - Get connected components in gt image.
    cc, labels, bboxes = compute_connected_components(gt)

    #  - Use vertical dimension of CCs to determine which ones belong together
    #    to form stafflines. (Criterion: row overlap.)
    n_rows, n_cols = gt.shape
    intervals = [[] for _ in range(n_rows)
                 ]  # For each row: which CCs have pxs on that row?
    for label, (t, l, b, r) in list(bboxes.items()):
        if label == 0:
            continue
        # Ignore very short staffline segments that can easily be artifacts
        # and should not affect the vertical range of the staffline anyway.
        if (r - l) < 8:
            continue
        for row in range(t, b):
            intervals[row].append(label)

    logging.info('Grouping staffline connected components into stafflines.')
    staffline_components = [
    ]  # For each staffline, we collect the CCs that it is made of
    _in_staffline = False
    _current_staffline_components = []
    for r_labels in intervals:
        if not _in_staffline:
            # Last row did not contain staffline components.
            if len(r_labels) == 0:
                # No staffline component on current row
                continue
            else:
                _in_staffline = True
                _current_staffline_components += r_labels
        else:
            # Last row contained staffline components.
            if len(r_labels) == 0:
                # Current staffline has no more rows.
                staffline_components.append(set(_current_staffline_components))
                _current_staffline_components = []
                _in_staffline = False
                continue
            else:
                # Current row contains staffline components: the current
                # staffline continues.
                _current_staffline_components += r_labels

    logging.info('No. of stafflines, with component groups: {0}'
                 ''.format(len(staffline_components)))

    # Now: merge the staffline components into one bbox/mask.
    logging.info(
        'Merging staffline components into staffline bboxes and masks.')
    staffline_bboxes = []
    staffline_masks = []
    for sc in sorted(staffline_components,
                     key=lambda c: min([bboxes[cc][0]
                                        for cc in c])):  # Sorted top-down
        st, sl, sb, sr = n_rows, n_cols, 0, 0
        for component in sc:
            t, l, b, r = bboxes[component]
            st, sl, sb, sr = min(t, st), min(l, sl), max(b, sb), max(r, sr)
        _sm = gt[st:sb, sl:sr]
        staffline_bboxes.append((st, sl, sb, sr))
        staffline_masks.append(_sm)

    # Check if n. of stafflines is divisible by 5
    n_stafflines = len(staffline_bboxes)
    logging.info('\tTotal stafflines: {0}'.format(n_stafflines))
    if n_stafflines % 5 != 0:
        import matplotlib.pyplot as plt
        stafllines_mask_image = numpy.zeros(gt.shape)
        for i, (_sb, _sm) in enumerate(zip(staffline_bboxes, staffline_masks)):
            t, l, b, r = _sb
            stafllines_mask_image[t:b, l:r] = min(255, (i * 333) % 255 + 40)
        plt.imshow(stafllines_mask_image, cmap='jet', interpolation='nearest')
        plt.show()
        raise ValueError('No. of stafflines is not divisible by 5!')

    logging.info('Creating staff bboxes and masks.')

    #  - Go top-down and group the stafflines by five to get staves.
    #    (The staffline bboxes are already sorted top-down.)
    staff_bboxes = []
    staff_masks = []

    for i in range(n_stafflines // 5):
        _sbb = staffline_bboxes[5 * i:5 * (i + 1)]
        _st = min([bb[0] for bb in _sbb])
        _sl = min([bb[1] for bb in _sbb])
        _sb = max([bb[2] for bb in _sbb])
        _sr = max([bb[3] for bb in _sbb])
        staff_bboxes.append((_st, _sl, _sb, _sr))
        staff_masks.append(gt[_st:_sb, _sl:_sr])

    logging.info('Total staffs: {0}'.format(len(staff_bboxes)))

    ##################################################################
    # (Optionally fill in missing pixels, based on full image.)
    logging.info('SKIP: fill in missing pixels based on full image.')
    #  - Load full image
    #  - Find gap regions
    #  - Obtain gap region masks from full image
    #  - Add gap region mask to staffline mask.

    # Create the CropObjects for stafflines and staffs:
    #  - Load corresponding annotation, to which the stafflines and
    #    staves should be added. (This is needed to correctly set docname
    #    and objids.)
    if not args.annot:
        cropobjects = []
        next_objid = 0
        dataset_namespace = 'FCNOMR'
        docname = os.path.splitext(os.path.basename(args.staff_imfile))[0]
    else:
        if not os.path.isfile(args.annot):
            raise ValueError('Annotation file {0} does not exist!'.format(
                args.annot))

        logging.info('Creating cropobjects...')
        cropobjects = parse_cropobject_list(args.annot)
        logging.info('Non-staffline cropobjects: {0}'.format(len(cropobjects)))
        next_objid = max([c.objid for c in cropobjects]) + 1
        dataset_namespace = cropobjects[0].dataset
        docname = cropobjects[0].doc

    #  - Create the staffline CropObjects
    staffline_cropobjects = []
    for sl_bb, sl_m in zip(staffline_bboxes, staffline_masks):
        uid = CropObject.build_uid(dataset_namespace, docname, next_objid)
        t, l, b, r = sl_bb
        c = CropObject(objid=next_objid,
                       clsname=STAFFLINE_CLSNAME,
                       top=t,
                       left=l,
                       height=b - t,
                       width=r - l,
                       mask=sl_m,
                       uid=uid)
        staffline_cropobjects.append(c)
        next_objid += 1

    if not args.stafflines_only:

        #  - Create the staff CropObjects
        staff_cropobjects = []
        for s_bb, s_m in zip(staff_bboxes, staff_masks):
            uid = CropObject.build_uid(dataset_namespace, docname, next_objid)
            t, l, b, r = s_bb
            c = CropObject(objid=next_objid,
                           clsname=STAFF_CLSNAME,
                           top=t,
                           left=l,
                           height=b - t,
                           width=r - l,
                           mask=s_m,
                           uid=uid)
            staff_cropobjects.append(c)
            next_objid += 1

        #  - Add the inlinks/outlinks
        for i, sc in enumerate(staff_cropobjects):
            sl_from = 5 * i
            sl_to = 5 * (i + 1)
            for sl in staffline_cropobjects[sl_from:sl_to]:
                sl.inlinks.append(sc.objid)
                sc.outlinks.append(sl.objid)

        # Add the staffspaces.
        staffspace_cropobjects = []
        for i, staff in enumerate(staff_cropobjects):
            current_stafflines = [
                sc for sc in staffline_cropobjects
                if sc.objid in staff.outlinks
            ]
            sorted_stafflines = sorted(current_stafflines, key=lambda x: x.top)

            current_staffspace_cropobjects = []

            # Percussion single-line staves do not have staffspaces.
            if len(sorted_stafflines) == 1:
                continue

            # Internal staffspace
            for s1, s2 in zip(sorted_stafflines[:-1], sorted_stafflines[1:]):
                # s1 is the UPPER staffline, s2 is the LOWER staffline
                # Left and right limits: to simplify things, we take the column
                # *intersection* of (s1, s2). This gives the invariant that
                # the staffspace is limited from top and bottom in each of its columns.
                l = max(s1.left, s2.left)
                r = min(s1.right, s2.right)

                # Shift s1, s2 to the right by this much to have the cols. align
                # All of these are non-negative.
                dl1, dl2 = l - s1.left, l - s2.left
                dr1, dr2 = s1.right - r, s2.right - r

                # The stafflines are not necessarily straight,
                # so top is given for the *topmost bottom edge* of the top staffline + 1

                # First create mask
                canvas = numpy.zeros((s2.bottom - s1.top, r - l),
                                     dtype='uint8')

                # Paste masks into canvas.
                # This assumes that the top of the bottom staffline is below
                # the top of the top staffline... and that the bottom
                # of the top staffline is above the bottom of the bottom
                # staffline. This may not hold in very weird situations,
                # but it's good for now.
                logging.debug(s1.bounding_box, s1.mask.shape)
                logging.debug(s2.bounding_box, s2.mask.shape)
                logging.debug(canvas.shape)
                logging.debug(
                    'l={0}, dl1={1}, dl2={2}, r={3}, dr1={4}, dr2={5}'
                    ''.format(l, dl1, dl2, r, dr1, dr2))
                #canvas[:s1.height, :] += s1.mask[:, dl1:s1.width-dr1]
                #canvas[-s2.height:, :] += s2.mask[:, dl2:s2.width-dr2]

                # We have to deal with staffline interruptions.
                # One way to do this
                # is watershed fill: put markers along the bottom and top
                # edge, use mask * 10000 as elevation

                s1_above, s1_below = staffline_surroundings_mask(s1)
                s2_above, s2_below = staffline_surroundings_mask(s2)

                # Get bounding boxes of the individual stafflines' masks
                # that intersect with the staffspace bounding box, in terms
                # of the staffline bounding box.
                s1_t, s1_l, s1_b, s1_r = 0, dl1, \
                                         s1.height, s1.width - dr1
                s1_h, s1_w = s1_b - s1_t, s1_r - s1_l
                s2_t, s2_l, s2_b, s2_r = canvas.shape[0] - s2.height, dl2, \
                                         canvas.shape[0], s2.width - dr2
                s2_h, s2_w = s2_b - s2_t, s2_r - s2_l

                logging.debug(s1_t, s1_l, s1_b, s1_r, (s1_h, s1_w))

                # We now take the intersection of s1_below and s2_above.
                # If there is empty space in the middle, we fill it in.
                staffspace_mask = numpy.ones(canvas.shape)
                staffspace_mask[s1_t:s1_b, :] -= (
                    1 - s1_below[:, dl1:s1.width - dr1])
                staffspace_mask[s2_t:s2_b, :] -= (
                    1 - s2_above[:, dl2:s2.width - dr2])

                ss_top = s1.top
                ss_bottom = s2.bottom
                ss_left = l
                ss_right = r

                uid = CropObject.build_uid(dataset_namespace, docname,
                                           next_objid)

                staffspace = CropObject(next_objid,
                                        STAFFSPACE_CLSNAME,
                                        top=ss_top,
                                        left=ss_left,
                                        height=ss_bottom - ss_top,
                                        width=ss_right - ss_left,
                                        mask=staffspace_mask,
                                        uid=uid)

                staffspace.inlinks.append(staff.objid)
                staff.outlinks.append(staffspace.objid)

                current_staffspace_cropobjects.append(staffspace)

                next_objid += 1

            # Add top and bottom staffspace.
            # These outer staffspaces will have the width
            # of their bottom neighbor, and height derived
            # from its mask columns.
            # This is quite approximate, but it should do.

            # Upper staffspace
            tsl = sorted_stafflines[0]
            tsl_heights = tsl.mask.sum(axis=0)
            tss = current_staffspace_cropobjects[0]
            tss_heights = tss.mask.sum(axis=0)

            uss_top = max(0, tss.top - max(tss_heights))
            uss_left = tss.left
            uss_width = tss.width
            # We use 1.5, so that large noteheads
            # do not "hang out" of the staffspace.
            uss_height = int(tss.height / 1.2)
            # Shift because of height downscaling:
            uss_top += tss.height - uss_height
            uss_mask = tss.mask[:uss_height, :] * 1

            uid = CropObject.build_uid(dataset_namespace, docname, next_objid)
            staffspace = CropObject(next_objid,
                                    STAFFSPACE_CLSNAME,
                                    top=uss_top,
                                    left=uss_left,
                                    height=uss_height,
                                    width=uss_width,
                                    mask=uss_mask,
                                    uid=uid)
            current_staffspace_cropobjects.append(staffspace)
            staff.outlinks.append(staffspace.objid)
            staffspace.inlinks.append(staff.objid)
            next_objid += 1

            # Lower staffspace
            bss = current_staffspace_cropobjects[-1]
            bss_heights = bss.mask.sum(axis=0)
            bsl = sorted_stafflines[-1]
            bsl_heights = bsl.mask.sum(axis=0)

            lss_top = bss.bottom  # + max(bsl_heights)
            lss_left = bss.left
            lss_width = bss.width
            lss_height = int(bss.height / 1.2)
            lss_mask = bss.mask[:lss_height, :] * 1

            uid = CropObject.build_uid(dataset_namespace, docname, next_objid)
            staffspace = CropObject(next_objid,
                                    STAFFSPACE_CLSNAME,
                                    top=lss_top,
                                    left=lss_left,
                                    height=lss_height,
                                    width=lss_width,
                                    mask=lss_mask,
                                    uid=uid)
            current_staffspace_cropobjects.append(staffspace)
            staff.outlinks.append(staffspace.objid)
            staffspace.inlinks.append(staff.objid)
            next_objid += 1

            # ################ End of dealing with upper/lower staffspace ######

            # Add to current list
            staffspace_cropobjects += current_staffspace_cropobjects

        # - Join the lists together
        cropobjects_with_staffs = cropobjects \
                                  + staffline_cropobjects \
                                  + staffspace_cropobjects \
                                  + staff_cropobjects

    else:
        cropobjects_with_staffs = cropobjects + staffline_cropobjects

    logging.info('Exporting the new cropobject list: {0} objects'
                 ''.format(len(cropobjects_with_staffs)))
    # - Export the combined list.
    cropobject_string = export_cropobject_list(cropobjects_with_staffs)
    if args.export is not None:
        with open(args.export, 'w') as hdl:
            hdl.write(cropobject_string)
    else:
        print(cropobject_string)

    _end_time = time.clock()
    logging.info('add_staffline_symbols.py done in {0:.3f} s'
                 ''.format(_end_time - _start_time))
Exemple #8
0
def count_cropobjects(annot_file):
    return len(parse_cropobject_list(annot_file))