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)
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