//TODO: do we only want 1 neighbor from the 9 as a continuation?
// yes for now, but this requires edges be only 1 pixel wide
// inserting back at the top of the stack assures that the 
// search continues next from an associated point
public List<PairIntArray> findEdges() {
        // DFS search for sequential neighbors.
        Stack<PairInt> stack = new Stack<PairInt>();
        int thresh0 = 1;
        for (int i = 0; i < img.getWidth(); i++) {
            for (int j = 0; j < img.getHeight(); j++) {
                //for now, choosing to look only at the blue
                int bPix = img.getValue(i, j);
                if (bPix >= thresh0) {
                    stack.add(new PairInt(i, j));
                }
            }
        }
        numberOfPixelsAboveThreshold = stack.size();
        log.log(Level.FINE, "Number of pixels that exceed threshhold={0}", 
            Long.toString(numberOfPixelsAboveThreshold));
        List<PairIntArray> output = new ArrayList<PairIntArray>();
        int[] uNodeEdgeIdx = new int[img.getWidth() * img.getHeight()];
        Arrays.fill(uNodeEdgeIdx, -1);
        while (!stack.isEmpty()) {
            PairInt uNode = stack.pop();
            int uX = uNode.getX();
            int uY = uNode.getY();
            int uIdx = (uY * img.getWidth()) + uX;
            boolean foundNeighbor = false;
            // for each neighbor v of u
            for (int vX = (uX - 1); vX < (uX + 2); vX++) {
                if (foundNeighbor) {
                    break;
                }
                if (vX < 0 || vX > (img.getWidth() - 1)) {
                    continue;
                }
                for (int vY = (uY - 1); vY < (uY + 2); vY++) {
                    if (vY < 0 || vY > (img.getHeight() - 1)) {
                        continue;
                    }
                    int vIdx = (vY * img.getWidth()) + vX;
                    if (uNodeEdgeIdx[vIdx] != -1 || (uIdx == vIdx)) {
                        continue;
                    }
                    if (img.getValue(vX, vY) < thresh0) {
                        continue;
                    }
                    // if u is not in an edge already, create a new one
                    if (uNodeEdgeIdx[uIdx] == -1) {
                        PairIntArray edge = new PairIntArray();
                        edge.add(uX, uY);
                        uNodeEdgeIdx[uIdx] = output.size();
                        output.add(edge);                        
                    }
                    // keep the curve points ordered
                    // add v to the edge u if u is the last node in it's edge
                    PairIntArray appendToNode = output.get(uNodeEdgeIdx[uIdx]);
                    int aIdx = appendToNode.getN() - 1;
                    if ((appendToNode.getX(aIdx) != uX) || 
                        (appendToNode.getY(aIdx) != uY)) {
                        continue;
                    }
                    appendToNode.add(vX, vY);
                    uNodeEdgeIdx[vIdx] = uNodeEdgeIdx[uIdx];
                    //TODO: do we only want 1 neighbor from the 9 as a continuation?
                    // yes for now, but this requires edges be only 1 pixel wide
                   // inserting back at the top of the stack assures that the 
                   // search continues next from an associated point
                   stack.add(new PairInt(vX, vY));
                   foundNeighbor = true;
                   break;
                }
            }
        }
        log.fine(output.size() + " edges after DFS");
        int nIterMax = 100;
        int n, sz, lastSize;
        // count the number of points in edges
        long sum = countPixelsInEdges(output);
        log.log(Level.FINE, 
            "==> {0} pixels are in edges out of {1} pixels > threshhold", 
            new Object[]{Long.toString(sum), 
                Long.toString(numberOfPixelsAboveThreshold)});
        log.log(Level.FINE, "there are {0} edges", 
            Integer.toString(output.size()));
        output = mergeAdjacentEndPoints(output);
        log.log(Level.FINE, "{0} edges after merge adjacent", 
            Integer.toString(output.size()));
        /*
        //not necessary now that lines from CannyEdgeFilter are 1 pix width.
        MiscellaneousCurveHelper ch = new MiscellaneousCurveHelper();
        n = 0;
        sz = output.size();
        lastSize = Integer.MAX_VALUE;
        while ((sz < lastSize) && (n < nIterMax)) {
            lastSize = sz;
            output = ch.pruneAndIncludeAdjacentCurves(output, img.getWidth());
            sz = output.size();
            log.log(Level.FINE, "{0}) {1} edges after prune overlapping", 
                new Object[]{Integer.toString(n), Integer.toString(sz)});
            n++;
        }
        */
        // This helps to merge edges (that is extracted curves) at adjacent 
        // points that resemble an intersection of the lines, but it's not 
        // necessarily useful if only interested in corners and not inflection
        // points because the curvature is determined correctly 
        // whether the curves are merged or not.
        output = connectClosestPointsIfCanTrim(output);
        log.fine(output.size() + " edges after connect closest");
        output = fillInGaps(output);
        log.log(Level.FINE, "{0} edges after fill in gaps", 
            new Object[]{Integer.toString(output.size())});
        //TODO:  this may need to change
        removeEdgesShorterThan(output, edgeSizeLowerLimit);
        sz = output.size();
        log.log(Level.FINE, "{0} edges after removing those shorter", 
            new Object[]{Integer.toString(sz)});
        long sum2 = countPixelsInEdges(output);
        log.log(Level.FINE, 
            "==> {0}) pixels are in edges out of {1} pixels > threshhold", 
            new Object[]{Long.toString(sum2), 
                Long.toString(numberOfPixelsAboveThreshold)});
        //pruneSpurs(output);
        adjustEdgesTowardsBrightPixels(output);
        return output;
    }
appendToNode.add(vX, vY);
uNodeEdgeIdx[vIdx] = uNodeEdgeIdx[uIdx];
//TODO: do we only want 1 neighbor from the 9 as a continuation?
// yes for now, but this requires edges be only 1 pixel wide
// inserting back at the top of the stack assures that the
// search continues next from an associated point
stack.add(new PairInt(vX, vY));
foundNeighbor = true;
// keep the curve points ordered
// add v to the edge u if u is the last node in it's edge
PairIntArray appendToNode = output.get(uNodeEdgeIdx[uIdx]);
int aIdx = appendToNode.getN() - 1;
if ((appendToNode.getX(aIdx) != uX) ||
(appendToNode.getY(aIdx) != uY)) {
continue;
}
appendToNode.add(vX, vY);
uNodeEdgeIdx[vIdx] = uNodeEdgeIdx[uIdx];
//TODO: do we only want 1 neighbor from the 9 as a continuation?
// yes for now, but this requires edges be only 1 pixel wide
// inserting back at the top of the stack assures that the
// search continues next from an associated point
stack.add(new PairInt(vX, vY));
foundNeighbor = true;
break;
}
}
}
log.fine(output.size() + " edges after DFS");
int nIterMax = 100;
int n, sz, lastSize;
// count the number of points in edges
if (img.getValue(vX, vY) < thresh0) {
continue;
}
// if u is not in an edge already, create a new one
if (uNodeEdgeIdx[uIdx] == -1) {
PairIntArray edge = new PairIntArray();
edge.add(uX, uY);
uNodeEdgeIdx[uIdx] = output.size();
output.add(edge);
}
// keep the curve points ordered
// add v to the edge u if u is the last node in it's edge
PairIntArray appendToNode = output.get(uNodeEdgeIdx[uIdx]);
int aIdx = appendToNode.getN() - 1;
if ((appendToNode.getX(aIdx) != uX) ||
(appendToNode.getY(aIdx) != uY)) {
continue;
}
appendToNode.add(vX, vY);
uNodeEdgeIdx[vIdx] = uNodeEdgeIdx[uIdx];
//TODO: do we only want 1 neighbor from the 9 as a continuation?
// yes for now, but this requires edges be only 1 pixel wide
// inserting back at the top of the stack assures that the
// search continues next from an associated point
stack.add(new PairInt(vX, vY));
foundNeighbor = true;
break;
}
}
}
log.fine(output.size() + " edges after DFS");
int nIterMax = 100;
int n, sz, lastSize;
// count the number of points in edges
long sum = countPixelsInEdges(output);
log.log(Level.FINE,
"==> {0} pixels are in edges out of {1} pixels > threshhold",
new Object[]{Long.toString(sum),
Long.toString(numberOfPixelsAboveThreshold)});
log.log(Level.FINE, "there are {0} edges",
Integer.toString(output.size()));
output = mergeAdjacentEndPoints(output);
log.log(Level.FINE, "{0} edges after merge adjacent",
Integer.toString(output.size()));