def __init__(self, allccs, indices): self.ccs = allccs self.indices = indices if len(indices) == 1: self.rect = Rect(allccs[indices[0]]) else: self.rect = allccs[indices[0]].union_images([allccs[i] for i in indices])
def __init__(self, run): Rect.__init__(run) # The number of black pixels in the section self.area = 0 # The average vertical thickness of all the runs in the section self.average_thickness = 0.0 # The runs that make up the section. Each run is a Rect object as # returned by the iterate_*_*_runs plugin method. self.runs = [] # The center points of all the runs. The points together make # up a line down the center of the section. self.center_points = [] # The number of connected sections to the right self.right_connections = [] # The number of connected sections to the left self.left_connections = [] # Marked True by find_potential_stafflines if the section appears to be a thin, straight, horizontal line self.is_filament = False # Marked True by find_stafflines if the section is part of an evenly spaced set of sections self.is_staffline_marker = False # Marked True by remove_stafflines if the section is aligned with a recognized staffline self.is_staffline = False # Add the first run self.add_run(run)
def __init__(self, run): Rect.__init__(self, run) # The number of black pixels in the section self.area = 0 # The average vertical thickness of all the runs in the section self.average_thickness = 0.0 # The runs that make up the section. Each run is a Rect object as # returned by the iterate_*_*_runs plugin method. self.runs = [] # The center points of all the runs. The points together make # up a line down the center of the section. self.center_points = [] # The number of connected sections to the right self.right_connections = [] # The number of connected sections to the left self.left_connections = [] # Marked True by find_potential_stafflines if the section appears to be a thin, straight, horizontal line self.is_filament = False # Marked True by find_stafflines if the section is part of an evenly spaced set of sections self.is_staffline_marker = False # Marked True by remove_stafflines if the section is aligned with a recognized staffline self.is_staffline = False # Add the first run self.add_run(run)
def extend(self, Ex, Ey, img): ul_y = max(0, self.rect.ul_y - Ey) ul_x = max(0, self.rect.ul_x - Ex) lr_y = min(img.lr_y, self.rect.lr_y + Ey) lr_x = min(img.lr_x, self.rect.lr_x + Ex) nrows = lr_y - ul_y + 1 ncols = lr_x - ul_x + 1 self.rect = Rect(Point(ul_x, ul_y), Dim(ncols, nrows))
def get_staffpos(self, x=-1): """Returns the y-positions of all staff lines at a given x-position. Can only be called *after* ``remove_staves``. Signature: ``get_staffpos(x=0)`` Since the lines are modelled as connected sets of non-horizontal line segments, *x* is relevant to the result. The return value is a list of `StaffObj`__. .. __: gamera.toolkits.musicstaves.musicstaves.StaffObj.html#staffobj """ if self.stafflines is None: raise RuntimeError("You must call remove_staves before get_staffpos") result = [] if x == -1: x = self.image.ncols / 2 for i, staff in enumerate(self.stafflines.staves.values()): staff_result = StaffObj() staff_result.staffno = i for line in staff: staff_result.yposlist.append(self.stafflines.linear_interpolate(x, line)) staff_result.staffrect = Rect(staff[0][0], staff[-1][-1]) result.append(staff_result) return result
def parse_bbox(stringIn): from gamera.core import Rect from gamera.core import Point dimensions = stringIn.split() if not dimensions[0] == 'bbox' or not len(dimensions) == 5: raise ValueError('bounding box not in proper format: "%s"'%dimensions) a_rect = Rect(Point(int(dimensions[1]),int(dimensions[2])),Point(int(dimensions[3]),int(dimensions[4]))) return (a_rect)#dimensions[1:])
class Bbox: def __init__(self, allccs, indices): self.ccs = allccs self.indices = indices if len(indices) == 1: self.rect = Rect(allccs[indices[0]]) else: self.rect = allccs[indices[0]].union_images([allccs[i] for i in indices]) def extend(self, Ex, Ey, img): ul_y = max(0, self.rect.ul_y - Ey) ul_x = max(0, self.rect.ul_x - Ex) lr_y = min(img.lr_y, self.rect.lr_y + Ey) lr_x = min(img.lr_x, self.rect.lr_x + Ex) nrows = lr_y - ul_y + 1 ncols = lr_x - ul_x + 1 self.rect = Rect(Point(ul_x, ul_y), Dim(ncols, nrows)) def merge(self, other): self.indices += other.indices self.rect.union(other.rect)
def Fudge(o, amount=FUDGE_AMOUNT): # For rectangles, just return a new rectangle that is slightly larger if isinstance(o, Rect): return Rect(Point(int(o.ul_x - amount), int(o.ul_y - amount)), Dim(int(o.ncols + amount * 2), int(o.nrows + amount * 2))) # For integers, return one of our "fudge number proxies" elif isinstance(o, int): return FudgeInt(o, amount) elif isinstance(o, float): return FudgeFloat(o, amount)
def __init__(self, filament): Rect.__init__(self, filament) self.is_staffline_marker = False
def __call__(self,im_staffonly, n_gap, p_gap, n_shift, random_seed=0, add_noshift=False ): from gamera.core import RGBPixel,Point,FloatPoint,Rect from gamera.toolkits.musicstaves.stafffinder import StafflineSkeleton seed(random_seed) bnp_gap=binomial(n_gap,p_gap) bnp_shift=binomial(n_shift,0.5) im_full=self.image_copy() im_staffless=im_full.xor_image(im_staffonly) im_staffonly=im_staffonly.image_copy() il_shifts=[im_staffless,im_staffonly,im_full] il_breaks=il_shifts if add_noshift: ns_full=im_full.image_copy() ns_staffonly=im_staffonly.image_copy() il_breaks=[im_staffless,im_staffonly,im_full,ns_full,ns_staffonly] #find stafflines [first_x, last_x, stafflines, thickness]=find_stafflines_int(im_staffonly) #find breaks (where are the symbols?) stafflinedist=stafflines[1]-stafflines[0] staffline_skel=[] for sl in range(len(stafflines)): if sl==0 or stafflines[sl]-stafflines[sl-1]>3*stafflinedist: #first staffline of a system first_line=stafflines[sl] lines_per_system=0 lines_per_system=lines_per_system+1 if sl==len(stafflines)-1 or stafflines[sl+1]-stafflines[sl]>3*stafflinedist: #last staffline of a system last_line=stafflines[sl] # a hoizontal projection of the symbols helps us to find the x positions of the symbols. syst=im_staffless.subimage(Point(0,max((0,first_line-3*stafflinedist))),Point(im_staffless.width,min((last_line+3*stafflinedist,im_full.lr_y-1)))) symbolcols=syst.projection_cols() # collect the breaks, i.e. the mid of the white spaces between two symbols breaks=[] whiterun=False for col in range(len(symbolcols)): if (not whiterun) and symbolcols[col]==0: whiterun=True runbegin=col else: if whiterun and symbolcols[col]>0: whiterun=False br=[(runbegin+col)/2,col-runbegin] if br[0]>=first_x: breaks.append(br) # replace the first break (before the first symbol) with a break at the beginning of the stafflines breaks[0]=[first_x,1] # and append a break after the last symbol if whiterun: breaks.append([(last_x+runbegin)/2,last_x-runbegin]) else: breaks.append([last_x,1]) # draw white lines at the breaks new_breaks=[] for br in breaks: w=bnp_gap.random() # draw line if it fits only if w<br[1]: for im in il_breaks: im.draw_line(FloatPoint(br[0],first_line-stafflinedist), FloatPoint(br[0],last_line+stafflinedist), RGBPixel(0,0,0), w) new_breaks.append(br) breaks=new_breaks skeleton=[] # do the vertical shift by making a temporary copy (orig_type), white them out (draw_filled_rect) and "or" them again in with a new y-position for t in range(len(breaks)-1): vertical_shift=bnp_shift.random()-n_shift/2 typerect=Rect(Point(breaks[t][0],max((first_line-3*stafflinedist,0))), Point(breaks[t+1][0],min((last_line+3*stafflinedist,im_full.lr_y)))) moveto=Rect(Point(typerect.ul_x, typerect.ul_y+vertical_shift), typerect.size) if moveto.ul_y<0: typerect.ul_y=typerect.ul_y-moveto.ul_y moveto.ul_y=0 if moveto.lr_y>im_full.lr_y: typerect.lr_y=typerect.lr_y-(moveto.lr_y-im_full.lr_y) moveto.lr_y=im_full.lr_y for im in il_shifts: orig_type=im.subimage(typerect) orig_type=orig_type.image_copy() im.draw_filled_rect(typerect,RGBPixel(0,0,0)) im.subimage(moveto).or_image(orig_type,True) # collect data for later construction of the skeletons for line in range(lines_per_system): if len(skeleton)<=line: skeleton.append([]) st_line=stafflines[sl-lines_per_system+1+line] y=st_line+vertical_shift skeleton[line].append(Point(typerect.ul_x,y)) skeleton[line].append(Point(typerect.ur_x,y)) # now construct the skeletons for sk in skeleton: x=sk[0].x y=sk[0].y left_x=x y_list=[] i=1 while i<len(sk): y_list.append(y) if x>=sk[i].x: y=sk[i].y i=i+1 x=x+1 o=StafflineSkeleton() o.left_x=left_x o.y_list=y_list staffline_skel.append(o) if add_noshift: return [im_full,im_staffonly,staffline_skel,ns_full,ns_staffonly] else: return [im_full,im_staffonly,staffline_skel]
def expand_ccs(image,ccs,Ex,Ey): # two helper functions for merging rectangles def find_intersecting_rects(glyphs, index): g = glyphs[index] inter = [] for i in range(len(glyphs)): if i == index: continue if g.intersects(glyphs[i]): inter.append(i) return inter def list_union_rects(big_rects): current = 0 rects = big_rects while(1): inter = find_intersecting_rects(rects, current) if len(inter): g = rects[current] new_rects = [g] for i in range(len(rects)): if i == current: continue if i in inter: g.union(rects[i]) else: new_rects.append(rects[i]) rects = new_rects current = 0 else: current += 1 if(current >= len(rects)): break return rects # the actual plugin from gamera.core import Dim, Rect, Point, Cc from gamera.plugins.image_utilities import union_images page = image # extend CC bounding boxes big_rects = [] for c in ccs: ul_y = max(0, c.ul_y - Ey) ul_x = max(0, c.ul_x - Ex) lr_y = min(page.lr_y, c.lr_y + Ey) lr_x = min(page.lr_x, c.lr_x + Ex) nrows = lr_y - ul_y + 1 ncols = lr_x - ul_x + 1 big_rects.append(Rect(Point(ul_x, ul_y), Dim(ncols, nrows))) extended_segs = list_union_rects(big_rects) # build new merged CCs tmplist = ccs[:] dellist = [] seg_ccs = [] seg_cc = [] if(len(extended_segs) > 0): label = 1 for seg in extended_segs: label += 1 for cc in tmplist: if(seg.intersects(cc)): # mark original image with segment label #self.highlight(cc, label) seg_cc.append(cc) dellist.append(cc) if len(seg_cc) == 0: continue seg_rect = seg_cc[0].union_rects(seg_cc) new_seg = Cc(image, label, seg_rect.ul, seg_rect.lr) seg_cc = [] for item in dellist: tmplist.remove(item) dellist = [] seg_ccs.append(new_seg) return seg_ccs
def __init__(self, filament): Rect.__init__(filament) self.is_staffline_marker = False
def generateCCsFromHocr(parser, image): from gamera.core import Point, Cc, Rect extended_segs = [] for span in parser.spans: ## print "line_span found:", span boxes = span.split(';')[0].split() point1 = Point(int(boxes[1]), int(boxes[2])) point2 = Point(int(boxes[3]), int(boxes[4])) try: extended_segs.append(Rect(point1, point2)) except RuntimeError as e: #TODO we should do something here print e print "failed to make Cc from Hocr box: " print boxes pass page = image.image_copy() ccs = page.cc_analysis() #The following copied from bbox_merging. Simply making Ccs with #the appropriate dimensions does not seem to work, but did in a #previous version... #extended_segs are the line bboxes; ccs are the glyphs #found by page analysis # build new merged CCs tmplist = ccs[:] dellist = [] seg_ccs = [] seg_cc = [] if (len(extended_segs) > 0): label = 1 for seg in extended_segs: label += 1 # print "new line!" for cc in tmplist: #changed in this revision; the divisor used to be seg.height, that is, the line's height #avoid divbyzero error if cc.height > 0: descender = (float(cc.lr_y - seg.lr_y) / float(cc.height)) else: descender = float(0) # print "desc: ", str(descender), " downness: ", str(downness), " ccheight: ", str(cc.height) #for more closed texts: #this matches if: # 1. the character's bottom is above the lines, or; # 2. if the character is higher than half the line height # AND the portion of the character that goes below the line is less # than 20% of its total height. #if(seg.intersects(cc) and ((cc.lr_y < seg.lr_y) or ((float(cc.height) > float(seg.height)/2.0) and (descender < 0.2) )): #for more open texts: #if(seg.intersects(cc) and ((cc.lr_y < seg.lr_y) or (descender < 0.4)) ): # mark original image with segment label #new, experimental universal solution: #This matches if: #1. the character's bottom is above the line, or; #2. The character's bottom is below the line, and the amount of the character that is below the line is less than 40% of its height if (seg.intersects(cc) and ((cc.lr_y <= seg.lr_y) or ((cc.lr_y > seg.lr_y) and (descender < 0.3)))): # print "\tpassed" image.highlight(cc, label) seg_cc.append(cc) dellist.append(cc) if len(seg_cc) == 0: #continue #try to output, rather than ignore, empty line #this should make alignment easier, but is it wise? seg_rect = seg else: seg_rect = seg_cc[0].union_rects(seg_cc) #TODO fix these errors, caused by new_seg being beyond the bounds of the image, I believe #They seem to appear with tesseract hocr output try: new_seg = Cc(image, label, seg_rect.ul, seg_rect.lr) seg_ccs.append(new_seg) except RuntimeError as e: print "HOCR ERROR -- failed to append segment" print e seg_cc = [] for item in dellist: tmplist.remove(item) dellist = [] #seg_ccs.append(new_seg) return seg_ccs
def __call__(self, im_staffonly, n_gap, p_gap, n_shift, random_seed=0, add_noshift=False): from gamera.core import RGBPixel, Point, FloatPoint, Rect from gamera.toolkits.musicstaves.stafffinder import StafflineSkeleton seed(random_seed) bnp_gap = binomial(n_gap, p_gap) bnp_shift = binomial(n_shift, 0.5) im_full = self.image_copy() im_staffless = im_full.xor_image(im_staffonly) im_staffonly = im_staffonly.image_copy() il_shifts = [im_staffless, im_staffonly, im_full] il_breaks = il_shifts if add_noshift: ns_full = im_full.image_copy() ns_staffonly = im_staffonly.image_copy() il_breaks = [ im_staffless, im_staffonly, im_full, ns_full, ns_staffonly ] #find stafflines [first_x, last_x, stafflines, thickness] = find_stafflines_int(im_staffonly) #find breaks (where are the symbols?) stafflinedist = stafflines[1] - stafflines[0] staffline_skel = [] for sl in range(len(stafflines)): if sl == 0 or stafflines[sl] - stafflines[sl - 1] > 3 * stafflinedist: #first staffline of a system first_line = stafflines[sl] lines_per_system = 0 lines_per_system = lines_per_system + 1 if sl == len(stafflines) - 1 or stafflines[ sl + 1] - stafflines[sl] > 3 * stafflinedist: #last staffline of a system last_line = stafflines[sl] # a hoizontal projection of the symbols helps us to find the x positions of the symbols. syst = im_staffless.subimage( Point(0, max((0, first_line - 3 * stafflinedist))), Point( im_staffless.width, min((last_line + 3 * stafflinedist, im_full.lr_y - 1)))) symbolcols = syst.projection_cols() # collect the breaks, i.e. the mid of the white spaces between two symbols breaks = [] whiterun = False for col in range(len(symbolcols)): if (not whiterun) and symbolcols[col] == 0: whiterun = True runbegin = col else: if whiterun and symbolcols[col] > 0: whiterun = False br = [(runbegin + col) / 2, col - runbegin] if br[0] >= first_x: breaks.append(br) # replace the first break (before the first symbol) with a break at the beginning of the stafflines breaks[0] = [first_x, 1] # and append a break after the last symbol if whiterun: breaks.append([(last_x + runbegin) / 2, last_x - runbegin]) else: breaks.append([last_x, 1]) # draw white lines at the breaks new_breaks = [] for br in breaks: w = bnp_gap.random() # draw line if it fits only if w < br[1]: for im in il_breaks: im.draw_line( FloatPoint(br[0], first_line - stafflinedist), FloatPoint(br[0], last_line + stafflinedist), RGBPixel(0, 0, 0), w) new_breaks.append(br) breaks = new_breaks skeleton = [] # do the vertical shift by making a temporary copy (orig_type), white them out (draw_filled_rect) and "or" them again in with a new y-position for t in range(len(breaks) - 1): vertical_shift = bnp_shift.random() - n_shift / 2 typerect = Rect( Point(breaks[t][0], max((first_line - 3 * stafflinedist, 0))), Point( breaks[t + 1][0], min((last_line + 3 * stafflinedist, im_full.lr_y)))) moveto = Rect( Point(typerect.ul_x, typerect.ul_y + vertical_shift), typerect.size) if moveto.ul_y < 0: typerect.ul_y = typerect.ul_y - moveto.ul_y moveto.ul_y = 0 if moveto.lr_y > im_full.lr_y: typerect.lr_y = typerect.lr_y - (moveto.lr_y - im_full.lr_y) moveto.lr_y = im_full.lr_y for im in il_shifts: orig_type = im.subimage(typerect) orig_type = orig_type.image_copy() im.draw_filled_rect(typerect, RGBPixel(0, 0, 0)) im.subimage(moveto).or_image(orig_type, True) # collect data for later construction of the skeletons for line in range(lines_per_system): if len(skeleton) <= line: skeleton.append([]) st_line = stafflines[sl - lines_per_system + 1 + line] y = st_line + vertical_shift skeleton[line].append(Point(typerect.ul_x, y)) skeleton[line].append(Point(typerect.ur_x, y)) # now construct the skeletons for sk in skeleton: x = sk[0].x y = sk[0].y left_x = x y_list = [] i = 1 while i < len(sk): y_list.append(y) if x >= sk[i].x: y = sk[i].y i = i + 1 x = x + 1 o = StafflineSkeleton() o.left_x = left_x o.y_list = y_list staffline_skel.append(o) if add_noshift: return [ im_full, im_staffonly, staffline_skel, ns_full, ns_staffonly ] else: return [im_full, im_staffonly, staffline_skel]
def __init__(self): Rect.__init__(self)
def rspikes(self, width, height_threshold=None): return [ Rect((0,s['start']),(width,s['stop'])) \ for s in self.spikes(height_threshold) ]