void findAllContours() {
    outerContours = new ArrayList<Contour>(50);
    innerContours = new ArrayList<Contour>(50);
    int label = 0; // current label

    // scan top to bottom, left to right
    for (int v = 1; v < pixelArray.length - 1; v++) {
      label = 0; // no label
      for (int u = 1; u < pixelArray[v].length - 1; u++) {

        if (pixelArray[v][u] == FOREGROUND) {
          if (label != 0) { // keep using same label
            labelArray[v][u] = label;
          } else {
            label = labelArray[v][u];
            if (label == 0) { // unlabeled - new outer contour
              regionId = regionId + 1;
              label = regionId;
              Contour oc = traceOuterContour(u, v, label);
              outerContours.add(oc);
              labelArray[v][u] = label;
            }
          }
        } else { // BACKGROUND pixel
          if (label != 0) {
            if (labelArray[v][u] == 0) { // unlabeled - new inner contour
              Contour ic = traceInnerContour(u - 1, v, label);
              innerContours.add(ic);
            }
            label = 0;
          }
        }
      }
    }
    // shift back to original coordinates
    Contour.moveContoursBy(outerContours, -1, -1);
    Contour.moveContoursBy(innerContours, -1, -1);
  }