/** Associates the features together. */
  public void associate() {
    // initialize data structures
    matches.reset();
    unassociatedSrc.reset();

    // find and add the matches
    assoc.setSource((FastQueue) srcPositive);
    assoc.setDestination((FastQueue) dstPositive);
    assoc.associate();
    FastQueue<AssociatedIndex> m = assoc.getMatches();
    for (int i = 0; i < m.size; i++) {
      AssociatedIndex a = m.data[i];
      int globalSrcIndex = srcPositive.data[a.src].index;
      int globalDstIndex = dstPositive.data[a.dst].index;
      matches.grow().setAssociation(globalSrcIndex, globalDstIndex, a.fitScore);
    }
    GrowQueue_I32 un = assoc.getUnassociatedSource();
    for (int i = 0; i < un.size; i++) {
      unassociatedSrc.add(srcPositive.data[un.get(i)].index);
    }
    assoc.setSource((FastQueue) srcNegative);
    assoc.setDestination((FastQueue) dstNegative);
    assoc.associate();
    m = assoc.getMatches();
    for (int i = 0; i < m.size; i++) {
      AssociatedIndex a = m.data[i];
      int globalSrcIndex = srcNegative.data[a.src].index;
      int globalDstIndex = dstNegative.data[a.dst].index;
      matches.grow().setAssociation(globalSrcIndex, globalDstIndex, a.fitScore);
    }
    un = assoc.getUnassociatedSource();
    for (int i = 0; i < un.size; i++) {
      unassociatedSrc.add(srcNegative.data[un.get(i)].index);
    }
  }
  private void processImage() {
    final List<Point2D_F64> leftPts = new ArrayList<Point2D_F64>();
    final List<Point2D_F64> rightPts = new ArrayList<Point2D_F64>();
    FastQueue<TupleDesc> leftDesc = UtilFeature.createQueue(describe, 10);
    FastQueue<TupleDesc> rightDesc = UtilFeature.createQueue(describe, 10);

    final ProgressMonitor progressMonitor =
        new ProgressMonitor(this, "Associating Features", "Detecting Left", 0, 3);

    // show a progress dialog if it is slow.  Needs to be in its own thread so if this stalls
    // the window will pop up
    progress = 0;
    new Thread() {
      public synchronized void run() {
        while (progress < 3) {
          SwingUtilities.invokeLater(
              new Runnable() {
                public void run() {
                  progressMonitor.setProgress(progress);
                }
              });
          try {
            wait(100);
          } catch (InterruptedException e) {
          }
        }
        progressMonitor.close();
      }
    }.start();

    // find feature points  and descriptions
    extractImageFeatures(imageLeft, grayLeft, leftDesc, leftPts);
    progress++;
    extractImageFeatures(imageRight, grayRight, rightDesc, rightPts);
    progress++;
    matcher.setSource(leftDesc);
    matcher.setDestination(rightDesc);
    matcher.associate();
    progress = 3;

    SwingUtilities.invokeLater(
        new Runnable() {
          public void run() {
            panel.setAssociation(leftPts, rightPts, matcher.getMatches());
            repaint();
          }
        });
  }