def onStrokeAdded(self, stroke):
        "Tags 1's and 0's as letters (TextAnnotation)"
        closedDistRatio = 0.22
        circularityThresh_0 = 0.80
        circularityThresh_1 = 0.20
        strokeLen = max(GeomUtils.strokeLength(stroke), 1)
        normDist = max(3, strokeLen / 5)
        head, tail = stroke.Points[0], stroke.Points[-1]

        endDist = GeomUtils.pointDistance(head.X, head.Y, tail.X, tail.Y)
        #If the endpoints are 1/thresh apart, actually close the thing
        isClosedShape = GeomUtils.pointDistanceSquared(head.X, head.Y, tail.X, tail.Y) \
                        < (strokeLen * closedDistRatio) ** 2

        if isClosedShape: #Close the shape back up
            s_norm = GeomUtils.strokeNormalizeSpacing( Stroke(stroke.Points + [stroke.Points[0]]) , normDist ) 
        else:
            s_norm = GeomUtils.strokeNormalizeSpacing( stroke , normDist ) 
        curvatures = GeomUtils.strokeGetPointsCurvature(s_norm)
        circularity = GeomUtils.strokeCircularity( s_norm ) 

        if isClosedShape and circularity > circularityThresh_0:
            height = stroke.BoundTopLeft.Y - stroke.BoundBottomRight.Y
            oAnnotation = TextAnnotation("0", height)
            l_logger.debug("Annotating %s with %s" % ( stroke, oAnnotation))
            BoardSingleton().AnnotateStrokes( [stroke],  oAnnotation)
            l_logger.debug(" Afterward: %s.annotations is %s" % ( stroke, stroke.Annotations))

        elif len(stroke.Points) >= 2 \
            and max(curvatures) < 0.5 \
            and circularity < circularityThresh_1:
                if stroke.Points[0].X < stroke.Points[-1].X + strokeLen / 2.0 \
                and stroke.Points[0].X > stroke.Points[-1].X - strokeLen / 2.0:
                    height = stroke.BoundTopLeft.Y - stroke.BoundBottomRight.Y
                    oneAnnotation = TextAnnotation("1", height)
                    l_logger.debug("Annotating %s with %s" % ( stroke, oneAnnotation.text))
                    BoardSingleton().AnnotateStrokes( [stroke],  oneAnnotation)
                    l_logger.debug(" Afterward: %s.annotations is %s" % ( stroke, stroke.Annotations))
                elif stroke.Points[0].Y < stroke.Points[-1].Y + strokeLen / 2.0 \
                and stroke.Points[0].Y > stroke.Points[-1].Y - strokeLen / 2.0:
                    width = stroke.BoundBottomRight.X - stroke.BoundTopLeft.X 
                    dashAnnotation = TextAnnotation("-", width * 1.5) #Treat the dash's (boosted) width as its scale 
                    l_logger.debug("Annotating %s with %s" % ( stroke, dashAnnotation.text))
                    BoardSingleton().AnnotateStrokes( [stroke],  dashAnnotation)
        else:
            if not isClosedShape:
                l_logger.debug("0: Not a closed shape")
            if not (circularity > circularityThresh_0):
                l_logger.debug("0: Not circular enough: %s" % (circularity))
            if not len(stroke.Points) >= 2:
                l_logger.debug("1: Not enough points")
            if not (circularity < circularityThresh_1):
                l_logger.debug("1: Too circular")
            if not (max(curvatures) < 0.5):
                l_logger.debug("1: Max curvature too big %s" % max(curvatures))
            if not ( stroke.Points[0].X < stroke.Points[-1].X + strokeLen / 3 \
               and   stroke.Points[0].X > stroke.Points[-1].X - strokeLen / 3):
                l_logger.debug("1: Not vertical enough: \nX1 %s, \nX2 %s, \nLen %s" % (stroke.Points[0].X, stroke.Points[-1].X, strokeLen))
    def onStrokeAdded( self, stroke ):
        "Watches for Strokes with Circularity > threshold to Annotate"
        # need at least 6 points to be a circle
	if stroke.length()<6:
            return
	s_norm = GeomUtils.strokeNormalizeSpacing( stroke, 20 ) 
	s_chop = GeomUtils.strokeChopEnds( s_norm, 0.20 ) 
        circ_norm = GeomUtils.strokeCircularity( s_norm ) 
        circ_chop = GeomUtils.strokeCircularity( s_chop ) 

        logger.debug( "stroke: %s", [str(p) for p in s_norm.Points] )
        logger.debug( "potential circles (%f,%f) <> %f", circ_norm, circ_chop, self.threshold )

        if( circ_norm>self.threshold or circ_chop>self.threshold):
            cen = stroke.Center
            avgDist = GeomUtils.averageDistance( cen, stroke.Points )
            anno = CircleAnnotation( circ_norm, cen, avgDist )
            BoardSingleton().AnnotateStrokes( [stroke],  anno)
Example #3
0
def _scoreStrokesForLetter(strokelist, letter):
    """Get the confidence score for a group of strokes matching a letter, normalized [0.0-1.0]"""
    retConfidence = 0.0
    #Recognition thresholds
    closedDistRatio = 0.22
    circularityThresh_0 = 0.80
    circularityThresh_1 = 0.20
    maxStraightCurvature = 0.6
    strokesBB = GeomUtils.strokelistBoundingBox(strokelist)

    if len(strokelist) == 0:
        return 0.0

    #The case of a single point
    if strokesBB[0].X == strokesBB[1].X and strokesBB[0].Y == strokesBB[1].Y:
        return 0.0

    #Recognize a zero
    if letter.upper() == "0":
        stroke = strokelist[0]
        strokeLen = max(GeomUtils.strokeLength(stroke), 1)
        normDist = max(3, strokeLen / 5) #granularity of point spacing -- at least 3
        head, tail = stroke.Points[0], stroke.Points[-1]

        endDist = GeomUtils.pointDistance(head.X, head.Y, tail.X, tail.Y)
        #If the endpoints are 1/thresh apart, actually close the thing
        isClosedShape = GeomUtils.pointDistanceSquared(head.X, head.Y, tail.X, tail.Y) \
                        < ( (strokeLen * closedDistRatio) ** 2 )

        if isClosedShape: #Close the shape back up
            s_norm = GeomUtils.strokeNormalizeSpacing( Stroke(stroke.Points + [stroke.Points[0]]) , normDist ) 
        else:
            s_norm = GeomUtils.strokeNormalizeSpacing( stroke , normDist ) 
        #curvatures = GeomUtils.strokeGetPointsCurvature(s_norm)
        circularity = GeomUtils.strokeCircularity( s_norm ) 

        if isClosedShape:
            retConfidence += 0.5
        if circularity > circularityThresh_0:
            retConfidence += 0.5
        return retConfidence
    #Recognize a one
    elif letter.upper() == "1":
        stroke = strokelist[0]
        strokeLen = max(GeomUtils.strokeLength(stroke), 1)
        normDist = max(3, strokeLen / 5) #granularity of point spacing -- at least 3
        s_norm = GeomUtils.strokeNormalizeSpacing( stroke , normDist ) 

        circularity = GeomUtils.strokeCircularity( s_norm ) 
        curvatures = GeomUtils.strokeGetPointsCurvature(s_norm)
        if max(curvatures) < maxStraightCurvature:
            retConfidence += 0.30
        if circularity < circularityThresh_1:
            retConfidence += 0.5
            if stroke.Points[0].X < stroke.Points[-1].X + strokeLen / 2.0 \
            and stroke.Points[0].X > stroke.Points[-1].X - strokeLen / 2.0:
                retConfidence += 0.2
        return retConfidence
    #Recognize a dash
    elif letter.upper() == "-":
        stroke = strokelist[0]
        strokeLen = max(GeomUtils.strokeLength(stroke), 1)
        normDist = max(3, strokeLen / 5) #granularity of point spacing -- at least 3
        s_norm = GeomUtils.strokeNormalizeSpacing( stroke , normDist ) 

        circularity = GeomUtils.strokeCircularity( s_norm ) 
        curvatures = GeomUtils.strokeGetPointsCurvature(s_norm)
        if max(curvatures) < maxStraightCurvature:
            retConfidence += 0.30
        if circularity < circularityThresh_1:
            retConfidence += 0.5
            if stroke.Points[0].Y < stroke.Points[-1].Y + strokeLen / 2.0 \
            and stroke.Points[0].Y > stroke.Points[-1].Y - strokeLen / 2.0:
                retConfidence += 0.2
        return retConfidence
    else:
        return 0.0