@Override
    protected void declareImages(int width, int height) {
      super.declareImages(width, height);

      outputWidth = width * 2;
      outputHeight = height;

      int tx = outputWidth / 2 - width / 4;
      int ty = outputHeight / 2 - height / 4;

      Affine2D_F64 init = new Affine2D_F64(0.5, 0, 0, 0.5, tx, ty);
      init = init.invert(null);

      alg.configure(outputWidth, outputHeight, init);
      bitmap = Bitmap.createBitmap(outputWidth, outputHeight, Bitmap.Config.ARGB_8888);
      storage = ConvertBitmap.declareStorage(bitmap, storage);
    }
    @Override
    protected void process(GrayU8 gray) {
      if (paused) return;

      if (!resetRequested && alg.process(gray)) {
        GrayU8 stitched = alg.getStitchedImage();

        synchronized (lockGui) {
          ConvertBitmap.grayToBitmap(stitched, bitmap, storage);

          ImageMotion2D<?, ?> motion = alg.getMotion();
          if (showFeatures && (motion instanceof AccessPointTracks)) {
            AccessPointTracks access = (AccessPointTracks) motion;

            alg.getWorldToCurr(imageToDistorted);
            imageToDistorted.invert(distortedToImage);
            inliersGui.reset();
            outliersGui.reset();
            List<Point2D_F64> points = access.getAllTracks();
            for (int i = 0; i < points.size(); i++) {
              HomographyPointOps_F64.transform(distortedToImage, points.get(i), distPt);

              if (access.isInlier(i)) {
                inliersGui.grow().set(distPt.x, distPt.y);
              } else {
                outliersGui.grow().set(distPt.x, distPt.y);
              }
            }
          }

          alg.getImageCorners(gray.width, gray.height, corners);
        }

        boolean inside = true;
        inside &= BoofMiscOps.checkInside(stitched, corners.p0.x, corners.p0.y, 5);
        inside &= BoofMiscOps.checkInside(stitched, corners.p1.x, corners.p1.y, 5);
        inside &= BoofMiscOps.checkInside(stitched, corners.p2.x, corners.p2.y, 5);
        inside &= BoofMiscOps.checkInside(stitched, corners.p3.x, corners.p3.y, 5);
        if (!inside) {
          alg.setOriginToCurrent();
        }

      } else {
        resetRequested = false;
        alg.reset();
      }
    }