/** * Perform segmentation * * @return segmentation interpretation */ private Segmentation doSegmentation() { Segmentation seg = new Segmentation(); ArrayList<Stroke> substrokes = new ArrayList<Stroke>(); Stroke s1 = new Stroke(); Stroke s2 = new Stroke(); for (int i = 0; i < m_features.getNumOrigPoints(); i++) { if ((double) i / m_features.getNumOrigPoints() >= 0.5) s2.addPoint(m_features.getOrigPoints().get(i)); else s1.addPoint(m_features.getOrigPoints().get(i)); } substrokes.add(s1); substrokes.add(s2); // Set the parent for (Stroke substroke : substrokes) { substroke.setParent(m_features.getOrigStroke()); } seg.setSegmentedStrokes(substrokes); seg.setSegmenterName(S_SEGMENTER_NAME); return seg; }
/** * Construct a rectangle fit for a stroke * * @param features features of the stroke * @param ellipseFit ellipse fit of the stroke * @param segmentation corner finding interpretation */ public RectangleFit(StrokeFeatures features, EllipseFit ellipseFit, Segmentation segmentation) { super(features); m_ellipseFit = ellipseFit; // test 1: feature area error must be low try { m_err = FeatureArea.toRectangle(m_features.getOrigPoints(), m_features.getBounds()) / m_features.getBounds().getArea(); } catch (Exception e) { m_passed = false; m_fail = 0; return; } if (m_err > Thresholds.active.M_RECTANGLE_ERROR) { m_passed = false; m_fail = 1; } // test 2: diagonal of bounding box should be similar to major axis m_ratio = Math.abs( 1.0 - m_ellipseFit.getMajorAxisLength() / m_features.getBounds().getDiagonalLength()); if (m_ratio > Thresholds.active.M_BB_MAJOR_AXIS_RATIO) { m_passed = false; m_fail = 2; } // test 3: endpoints of stroke must be close if (m_features.getEndptStrokeLengthRatio() > 0.09) { // 0.075) m_passed = false; m_fail = 3; } // test 4: check number of corners to make sure its not too high // if (segmentation.getSegmentedStrokes().size() > 6) // m_passed = false; // this is a check that checks for triangles m_numCorners = segmentation.getSegmentedStrokes().size(); double perimeter = m_features.getBounds().getPerimeter(); m_perimeterStrokeLengthRatio = m_features.getStrokeLength() / perimeter; if (m_perimeterStrokeLengthRatio < 0.85 && m_numCorners < 4) { m_passed = false; m_fail = 4; } // new test: corner distance if (m_features.getAvgCornerStrokeDistance() > 0.16) m_passed = false; // create shape/beautified object generateRectangle(); try { computeBeautified(); m_beautified.setAttribute(IsAConstants.CLOSED, "true"); } catch (Exception e) { log.error("Could not create shape object: " + e.getMessage(), e); e.printStackTrace(); } // log.debug("Rectangle Fit: passed = " + m_passed + "(" + m_fail // + ") err = " + m_err + " lsqe = " + m_lsqe + " ellipse err = " // + m_ellipseFit.getError() + " major:bbdiag ratio = " + m_ratio // + " dcr = " + m_features.getDCR() + " ndde = " // + m_features.getNDDE() + " endpt:sl ratio = " // + m_features.getEndptStrokeLengthRatio() + " num ss = " // + m_numCorners + " avg corner/stroke dist = " // + m_features.getAvgCornerStrokeDistance() + " num revs = " // + m_features.numRevolutions() + " perimeter:sl ratio = " // + m_perimeterStrokeLengthRatio); }