def calculate_features(self):
    # This is a funny definition of aspect ratio...
    self.aspect_ratio = float(self.ncols) / self.average_thickness
    # Line fit to center points: y = mx + b (q is the gamma fit confidence)
    center_points = [run.center for run in self.runs]
    if len(center_points) > 2:
       center_points = center_points[1:-1]
    self.m, self.b, self.q = structural.least_squares_fit(center_points)
    # Angle within a single quadrant
    self.angle = (abs(atan(self.m)) / (pi / 2)) * 90.0
    start_y=[run.ul_y for run in self.runs]
    start_y.sort()
    self.ul_y = start_y[len(start_y)/2]
    end_y=[run.lr_y for run in self.runs]
    end_y.sort()
    self.lr_y = end_y[len(end_y)/2]
示例#2
0
 def calculate_features(self):
    # This is a funny definition of aspect ratio...
    self.aspect_ratio = float(self.ncols) / self.average_thickness
    # Line fit to center points: y = mx + b (q is the gamma fit confidence)
    center_points = [run.center for run in self.runs]
    if len(center_points) > 2:
       center_points = center_points[1:-1]
    self.m, self.b, self.q = structural.least_squares_fit(center_points)
    # Angle within a single quadrant
    self.angle = (abs(atan(self.m)) / (pi / 2)) * 90.0
    start_y=[run.ul_y for run in self.runs]
    start_y.sort()
    self.ul_y = start_y[len(start_y)/2]
    end_y=[run.lr_y for run in self.runs]
    end_y.sort()
    self.lr_y = end_y[len(end_y)/2]
      def recurse(direction, staffline, last_points):
         # The "projected line direction" is a combination of the current
         # line segment and the "history" of line segments we've seen
         # up until now.  This prevents little line segments with very
         # off-skew angles from overly affecting the tracing process
         if direction: # Right
            stack = staffline.right_connections[:]
            if len(staffline.runs) > num_points:
               points = [x.center for x in staffline.runs[-num_points:]]
            else:
               points = last_points[-(num_points - len(staffline.runs)):] + [x.center for x in staffline.runs]
         else:
            stack = staffline.left_connections[:]
            if len(staffline.runs) > num_points:
               points = [x.center for x in staffline.runs[:num_points]]
            else:
               points = [x.center for x in staffline.runs] + last_points[:(num_points - len(staffline.runs))]
         # This is the projected line
         m, b, q = structural.least_squares_fit(points)

         # Search A:  Try things that are directly connected in the LAG
         #            first.
         # Perform a breadth-first search in the current direction
         visited = {}
         while len(stack):
            # Sort the potential line segments by vertical distance
            # from the current line segment so the best match will be
            # found first
            stack.sort(lambda x, y: cmp(
               abs(staffline.center_y - x.center_y),
               abs(staffline.center_y - y.center_y)))

            section = stack.pop(0)
            if not visited.has_key(section):
               visited[section] = None
               if (section.average_thickness <= line_match_threshold and
                   abs(section.angle - staffline.angle) <= angle_threshold):
                  if section.avg_distance_from_line(m, b) < line_match_threshold:
                     line_groups.join(staffline, section)
                     if not section.is_staffline:
                        section.is_staffline = True
                        recurse(direction, section, points)
                     return
               if not section.is_staffline:
                  if direction:
                     stack.extend(section.right_connections)
                  else:
                     stack.extend(section.left_connections)

         # Search B: If Search A fails, search for line segments across small
         #           gaps (less than horizontal_gaps wide)
         for section in sections:
            if not section.is_staffline:
               if section.average_thickness <= line_match_threshold:
                  if ((direction and
                       section.ul_x > staffline.lr_x and
                       section.ul_x < staffline.lr_x + horizontal_gaps) or
                      (not direction and
                       section.lr_x < staffline.ul_x and
                       section.lr_x > staffline.ul_x - horizontal_gaps)):
                     if section.avg_distance_from_line(m, b) < line_match_threshold:
                        line_groups.join(staffline, section)
                        if not section.is_staffline:
                           section.is_staffline = True
                           recurse(direction, section, points)
                        return
    def melt(self, other):

        """Melts to overlapping segments together using the
        overlapping part of the segment that fits better into
        the environmental line. Returns a skeleton of the
        melted part."""

        # Remove all links to the segment to melt
        # Add links to the current segment instead
	
        for up_link in other.up_links:
            up_link.down_links.remove(other)
            if up_link.down_links.count(self) == 0:
                up_link.down_links.append(self)
            if self.up_links.count(up_link) == 0:
                self.up_links.append(up_link)
                    
        other.up_links = []
		
        for down_link in other.down_links:
            down_link.up_links.remove(other)
            if down_link.up_links.count(self) == 0:
                down_link.up_links.append(self)
            if self.down_links.count(down_link) == 0:
                self.down_links.append(down_link)
                    
        other.down_links = []

        # Calculate the least squares fit of the non-overlapping
        # parts of the segments

        points = []
        col_overlap = -1
        len_overlap = 0
        for col in range(min(self.col_start, other.col_start), \
                         max(self.col_end, other.col_end) + 1):

            in_self = col >= self.col_start and col <= self.col_end
            in_other = col >= other.col_start and col <= other.col_end

            if in_self and not in_other:
                points.append( \
                    CorePoint(col, \
                              self.skeleton[1][col - self.col_start]))
                
            elif in_other and not in_self:
                points.append( \
                    CorePoint(col, \
                              other.skeleton[1][col - other.col_start]))
                
            elif in_self and in_other:
                if col_overlap == -1: col_overlap = col
                len_overlap = len_overlap + 1
                
            else:
                raise RuntimeError, \
                      "Trying to melt non-overlapping segments!"

        if len(points) < 2:
            return

        # Do the least square fit
        (m, b, q) = least_squares_fit(points)

        # Calculate cumulative errors of overlapping parts

        self_error = 0
        other_error = 0
        for col in range(col_overlap, col_overlap + len_overlap):
            lsf_row = long(m * col + b + 0.5)
            self_row = self.skeleton[1][col - self.col_start]
            other_row = other.skeleton[1][col - other.col_start]
            self_error = self_error + abs(self_row - lsf_row)
            other_error = other_error + abs(other_row - lsf_row)

        skel = []
        melt = []
        for col in range(min(self.col_start, other.col_start), \
                         max(self.col_end, other.col_end) + 1):

            in_self = col >= self.col_start and col <= self.col_end
            in_other = col >= other.col_start and col <= other.col_end

            if in_self and not in_other:
                skel.append(self.skeleton[1][col - self.col_start])
                                       
            elif not in_self and in_other:
                skel.append(other.skeleton[1][col - other.col_start])

            elif in_other and in_self:
                 if (self_error <= other_error):
                     skel.append(self.skeleton[1][col - self.col_start])
                     melt.append(long(self.skeleton[1][col - self.col_start]))
                 else:
                     skel.append(other.skeleton[1][col - other.col_start])
                     melt.append(long(other.skeleton[1][col - other.col_start]))
                                       
            else:
                raise RuntimeError, \
                      "Trying to melt non-overlapping segments!"
			
        del self.skeleton
        self.skeleton = [min(self.col_start, other.col_start), skel]

        self.row_start = self.skeleton[1][0]
        self.row_end = self.skeleton[1][-1]
        self.col_start = self.skeleton[0]
        self.col_end = self.col_start + len(self.skeleton[1]) - 1
	    
        return [long(col_overlap), melt]
示例#5
0
    def melt(self, other):
        """Melts to overlapping segments together using the
        overlapping part of the segment that fits better into
        the environmental line. Returns a skeleton of the
        melted part."""

        # Remove all links to the segment to melt
        # Add links to the current segment instead

        for up_link in other.up_links:
            up_link.down_links.remove(other)
            if up_link.down_links.count(self) == 0:
                up_link.down_links.append(self)
            if self.up_links.count(up_link) == 0:
                self.up_links.append(up_link)

        other.up_links = []

        for down_link in other.down_links:
            down_link.up_links.remove(other)
            if down_link.up_links.count(self) == 0:
                down_link.up_links.append(self)
            if self.down_links.count(down_link) == 0:
                self.down_links.append(down_link)

        other.down_links = []

        # Calculate the least squares fit of the non-overlapping
        # parts of the segments

        points = []
        col_overlap = -1
        len_overlap = 0
        for col in range(min(self.col_start, other.col_start), \
                         max(self.col_end, other.col_end) + 1):

            in_self = col >= self.col_start and col <= self.col_end
            in_other = col >= other.col_start and col <= other.col_end

            if in_self and not in_other:
                points.append( \
                    CorePoint(col, \
                              self.skeleton[1][col - self.col_start]))

            elif in_other and not in_self:
                points.append( \
                    CorePoint(col, \
                              other.skeleton[1][col - other.col_start]))

            elif in_self and in_other:
                if col_overlap == -1: col_overlap = col
                len_overlap = len_overlap + 1

            else:
                raise RuntimeError, \
                      "Trying to melt non-overlapping segments!"

        if len(points) < 2:
            return

        # Do the least square fit
        (m, b, q) = least_squares_fit(points)

        # Calculate cumulative errors of overlapping parts

        self_error = 0
        other_error = 0
        for col in range(col_overlap, col_overlap + len_overlap):
            lsf_row = long(m * col + b + 0.5)
            self_row = self.skeleton[1][col - self.col_start]
            other_row = other.skeleton[1][col - other.col_start]
            self_error = self_error + abs(self_row - lsf_row)
            other_error = other_error + abs(other_row - lsf_row)

        skel = []
        melt = []
        for col in range(min(self.col_start, other.col_start), \
                         max(self.col_end, other.col_end) + 1):

            in_self = col >= self.col_start and col <= self.col_end
            in_other = col >= other.col_start and col <= other.col_end

            if in_self and not in_other:
                skel.append(self.skeleton[1][col - self.col_start])

            elif not in_self and in_other:
                skel.append(other.skeleton[1][col - other.col_start])

            elif in_other and in_self:
                if (self_error <= other_error):
                    skel.append(self.skeleton[1][col - self.col_start])
                    melt.append(long(self.skeleton[1][col - self.col_start]))
                else:
                    skel.append(other.skeleton[1][col - other.col_start])
                    melt.append(long(other.skeleton[1][col - other.col_start]))

            else:
                raise RuntimeError, \
                      "Trying to melt non-overlapping segments!"

        del self.skeleton
        self.skeleton = [min(self.col_start, other.col_start), skel]

        self.row_start = self.skeleton[1][0]
        self.row_end = self.skeleton[1][-1]
        self.col_start = self.skeleton[0]
        self.col_end = self.col_start + len(self.skeleton[1]) - 1

        return [long(col_overlap), melt]
示例#6
0
      def recurse(direction, staffline, last_points):
         # The "projected line direction" is a combination of the current
         # line segment and the "history" of line segments we've seen
         # up until now.  This prevents little line segments with very
         # off-skew angles from overly affecting the tracing process
         if direction: # Right
            stack = staffline.right_connections[:]
            if len(staffline.runs) > num_points:
               points = [x.center for x in staffline.runs[-num_points:]]
            else:
               points = last_points[-(num_points - len(staffline.runs)):] + [x.center for x in staffline.runs]
         else:
            stack = staffline.left_connections[:]
            if len(staffline.runs) > num_points:
               points = [x.center for x in staffline.runs[:num_points]]
            else:
               points = [x.center for x in staffline.runs] + last_points[:(num_points - len(staffline.runs))]
         # This is the projected line
         m, b, q = structural.least_squares_fit(points)

         # Search A:  Try things that are directly connected in the LAG
         #            first.
         # Perform a breadth-first search in the current direction
         visited = {}
         while len(stack):
            # Sort the potential line segments by vertical distance
            # from the current line segment so the best match will be
            # found first
            stack.sort(lambda x, y: cmp(
               abs(staffline.center_y - x.center_y),
               abs(staffline.center_y - y.center_y)))

            section = stack.pop(0)
            if not visited.has_key(section):
               visited[section] = None
               if (section.average_thickness <= line_match_threshold and
                   abs(section.angle - staffline.angle) <= angle_threshold):
                  if section.avg_distance_from_line(m, b) < line_match_threshold:
                     line_groups.join(staffline, section)
                     if not section.is_staffline:
                        section.is_staffline = True
                        recurse(direction, section, points)
                     return
               if not section.is_staffline:
                  if direction:
                     stack.extend(section.right_connections)
                  else:
                     stack.extend(section.left_connections)

         # Search B: If Search A fails, search for line segments across small
         #           gaps (less than horizontal_gaps wide)
         for section in sections:
            if not section.is_staffline:
               if section.average_thickness <= line_match_threshold:
                  if ((direction and
                       section.ul_x > staffline.lr_x and
                       section.ul_x < staffline.lr_x + horizontal_gaps) or
                      (not direction and
                       section.lr_x < staffline.ul_x and
                       section.lr_x > staffline.ul_x - horizontal_gaps)):
                     if section.avg_distance_from_line(m, b) < line_match_threshold:
                        line_groups.join(staffline, section)
                        if not section.is_staffline:
                           section.is_staffline = True
                           recurse(direction, section, points)
                        return