Пример #1
0
  /** All the corners should be in increasing order from the first anchor. */
  boolean sanityCheckCornerOrder(int numLines, GrowQueue_I32 corners) {
    int contourAnchor0 = corners.get(anchor0);
    int previous = 0;
    for (int i = 1; i < numLines; i++) {
      int contourIndex = corners.get(CircularIndex.addOffset(anchor0, i, corners.size()));
      int pixelsFromAnchor0 = CircularIndex.distanceP(contourAnchor0, contourIndex, contour.size());

      if (pixelsFromAnchor0 < previous) {
        return false;
      } else {
        previous = pixelsFromAnchor0;
      }
    }
    return true;
  }
Пример #2
0
  /**
   * Fits line segments along the contour with the first and last corner fixed at the original
   * corners. The output will be a new set of corner indexes. Since the corner list is circular, it
   * is assumed that anchor1 comes after anchor0. The same index can be specified for an anchor, it
   * will just go around the entire circle
   *
   * @param anchor0 corner index of the first end point
   * @param anchor1 corner index of the second end point.
   * @param corners Initial location of the corners
   * @param output Optimized location of the corners
   */
  public boolean fitAnchored(
      int anchor0, int anchor1, GrowQueue_I32 corners, GrowQueue_I32 output) {
    this.anchor0 = anchor0;
    this.anchor1 = anchor1;

    int numLines =
        anchor0 == anchor1
            ? corners.size()
            : CircularIndex.distanceP(anchor0, anchor1, corners.size);
    if (numLines < 2) {
      throw new RuntimeException("The one line is anchored and can't be optimized");
    }

    lines.resize(numLines);

    if (verbose) System.out.println("ENTER FitLinesToContour");

    // Check pre-condition
    //		checkDuplicateCorner(corners);

    workCorners.setTo(corners);

    for (int iteration = 0; iteration < maxIterations; iteration++) {
      // fit the lines to the contour using only lines between each corner for each line
      if (!fitLinesUsingCorners(numLines, workCorners)) {
        return false;
      }

      // intersect each line and find the closest point on the contour as the new corner
      if (!linesIntoCorners(numLines, workCorners)) {
        return false;
      }

      // sanity check to see if corner order is still met
      if (!sanityCheckCornerOrder(numLines, workCorners)) {
        return false; // TODO detect and handle this condition better
      }

      // TODO check for convergence
    }

    if (verbose)
      System.out.println("EXIT FitLinesToContour. " + corners.size() + "  " + workCorners.size());
    output.setTo(workCorners);
    return true;
  }
Пример #3
0
  /**
   * Given a sequence of points on the contour find the best fit line.
   *
   * @param contourIndex0 contour index of first point in the sequence
   * @param contourIndex1 contour index of last point (exclusive) in the sequence
   * @param line storage for the found line
   * @return true if successful or false if it failed
   */
  boolean fitLine(int contourIndex0, int contourIndex1, LineGeneral2D_F64 line) {
    int numPixels = CircularIndex.distanceP(contourIndex0, contourIndex1, contour.size());

    // if its too small
    if (numPixels < minimumLineLength) return false;

    Point2D_I32 c0 = contour.get(contourIndex0);
    Point2D_I32 c1 = contour.get(contourIndex1);

    double scale = c0.distance(c1);
    double centerX = (c1.x + c0.x) / 2.0;
    double centerY = (c1.y + c0.y) / 2.0;

    int numSamples = Math.min(20, numPixels);

    pointsFit.reset();
    for (int i = 0; i < numSamples; i++) {

      int index = i * (numPixels - 1) / (numSamples - 1);

      Point2D_I32 c = contour.get(CircularIndex.addOffset(contourIndex0, index, contour.size()));

      Point2D_F64 p = pointsFit.grow();
      p.x = (c.x - centerX) / scale;
      p.y = (c.y - centerY) / scale;
    }

    if (null == FitLine_F64.polar(pointsFit.toList(), linePolar)) {
      return false;
    }
    UtilLine2D_F64.convert(linePolar, line);

    // go from local coordinates into global
    line.C = scale * line.C - centerX * line.A - centerY * line.B;

    return true;
  }