/**
   * The number of octaves is too large for input image and should stop processing before it gets
   * too small
   */
  @Test
  public void smallImages() {
    SiftImageScaleSpace ss = new SiftImageScaleSpace(1.6f, 5, 4, false);

    ImageFloat32 input = new ImageFloat32(10, 15);
    GImageMiscOps.fillUniform(input, rand, 0, 100);

    ss.constructPyramid(input);
    ss.computeFeatureIntensity();
    ss.computeDerivatives();

    assertEquals(2, ss.actualOctaves);

    // images in rest of the octaves should be zero
    int index = 3 * 5;
    for (; index < ss.scale.length; index++) {
      ImageFloat32 s = ss.scale[index];
      ImageFloat32 gx = ss.derivX[index];
      ImageFloat32 gy = ss.derivY[index];
      assertTrue(ImageStatistics.sum(s) == 0);
      assertTrue(ImageStatistics.sum(gx) == 0);
      assertTrue(ImageStatistics.sum(gy) == 0);
    }

    index = 3 * 4;
    for (; index < ss.dog.length; index++) {
      ImageFloat32 dog = ss.dog[index];
      assertTrue(ImageStatistics.sum(dog) == 0);
    }
  }
Example #2
0
  public static BufferedImage standard(ImageSingleBand<?> src, BufferedImage dst) {
    if (src.getDataType().isInteger()) {
      ImageInteger srcInt = (ImageInteger) src;

      if (src.getDataType().isSigned()) {
        double max = GImageStatistics.maxAbs(srcInt);
        return colorizeSign(srcInt, dst, (int) max);
      } else {
        if (src.getDataType().getNumBits() == 8) {
          dst = ConvertBufferedImage.convertTo((ImageUInt8) src, dst);
        } else {
          double max = GImageStatistics.maxAbs(srcInt);
          dst = grayUnsigned(srcInt, dst, (int) max);
        }
      }
    } else if (ImageFloat32.class.isAssignableFrom(src.getClass())) {
      ImageFloat32 img = (ImageFloat32) src;
      float max = ImageStatistics.maxAbs(img);

      boolean hasNegative = false;
      for (int i = 0; i < img.getHeight(); i++) {
        for (int j = 0; j < img.getWidth(); j++) {
          if (img.get(j, i) < 0) {
            hasNegative = true;
            break;
          }
        }
      }

      if (hasNegative) return colorizeSign(img, dst, (int) max);
      else return grayMagnitude((ImageFloat32) src, dst, max);
    }

    return dst;
  }
  @Test
  public void performLearning() {
    float interp_factor = 0.075f;

    ImageFloat32 a = new ImageFloat32(20, 25);
    ImageFloat32 b = new ImageFloat32(20, 25);

    ImageMiscOps.fill(a, 100);
    ImageMiscOps.fill(b, 200);

    CirculantTracker<ImageFloat32> alg =
        new CirculantTracker<ImageFloat32>(1f / 16, 0.2, 1e-2, 0.075, 1.0, 64, 255, interp);
    alg.initialize(a, 0, 0, 20, 25);

    // copy its internal value
    ImageFloat64 templateC = new ImageFloat64(alg.template.width, alg.template.height);
    templateC.setTo(alg.template);

    // give it two images
    alg.performLearning(b);

    // make sure the images aren't full of zero
    assertTrue(Math.abs(ImageStatistics.sum(templateC)) > 0.1);
    assertTrue(Math.abs(ImageStatistics.sum(alg.template)) > 0.1);

    int numNotSame = 0;
    // the result should be an average of the two
    for (int i = 0; i < a.data.length; i++) {
      if (Math.abs(a.data[i] - alg.templateNew.data[i]) > 1e-4) numNotSame++;

      // should be more like the original one than the new one
      double expected =
          templateC.data[i] * (1 - interp_factor) + interp_factor * alg.templateNew.data[i];
      double found = alg.template.data[i];

      assertEquals(expected, found, 1e-4);
    }

    // make sure it is actually different
    assertTrue(numNotSame > 100);
  }
  /** Process two images, one is a sub-image of the first. See if it produces the same results */
  @Test
  public void checkSubImage() {
    SiftImageScaleSpace ss1 = new SiftImageScaleSpace(1.6f, 5, 4, false);
    SiftImageScaleSpace ss2 = new SiftImageScaleSpace(1.6f, 5, 4, false);

    ImageFloat32 input = new ImageFloat32(60, 70);
    GImageMiscOps.fillUniform(input, rand, 0, 100);
    ImageFloat32 sub = BoofTesting.createSubImageOf(input);

    ss1.constructPyramid(input);
    ss2.constructPyramid(sub);

    for (int index = 0; index < ss1.scale.length; index++) {
      ImageFloat32 s1 = ss1.scale[index];
      ImageFloat32 s2 = ss2.scale[index];

      float sum1 = ImageStatistics.sum(s1);
      float sum2 = ImageStatistics.sum(s2);

      assertTrue(sum1 != 0);
      assertEquals(sum1, sum2, 1e-6);
    }
  }
Example #5
0
  public static BufferedImage graySign(ImageFloat32 src, BufferedImage dst, float maxAbsValue) {
    dst = checkInputs(src, dst);

    if (maxAbsValue < 0) maxAbsValue = ImageStatistics.maxAbs(src);

    for (int y = 0; y < src.height; y++) {
      for (int x = 0; x < src.width; x++) {
        float v = src.get(x, y);

        int rgb = 127 + (int) (127 * v / maxAbsValue);

        dst.setRGB(x, y, rgb << 16 | rgb << 8 | rgb);
      }
    }

    return dst;
  }
  /** Fits polygons to found contours around binary blobs. */
  public static void fitBinaryImage(ImageFloat32 input) {

    ImageUInt8 binary = new ImageUInt8(input.width, input.height);
    BufferedImage polygon =
        new BufferedImage(input.width, input.height, BufferedImage.TYPE_INT_RGB);

    // the mean pixel value is often a reasonable threshold when creating a binary image
    double mean = ImageStatistics.mean(input);

    // create a binary image by thresholding
    ThresholdImageOps.threshold(input, binary, (float) mean, true);

    // reduce noise with some filtering
    ImageUInt8 filtered = BinaryImageOps.erode8(binary, null);
    filtered = BinaryImageOps.dilate8(filtered, null);

    // Find the contour around the shapes
    List<Contour> contours = BinaryImageOps.contour(filtered, 8, null);

    // Fit a polygon to each shape and draw the results
    Graphics2D g2 = polygon.createGraphics();
    g2.setStroke(new BasicStroke(2));

    for (Contour c : contours) {
      // Fit the polygon to the found external contour.  Note loop = true
      List<PointIndex_I32> vertexes =
          ShapeFittingOps.fitPolygon(c.external, true, toleranceDist, toleranceAngle, 100);

      g2.setColor(Color.RED);
      VisualizeShapes.drawPolygon(vertexes, true, g2);

      // handle internal contours now
      g2.setColor(Color.BLUE);
      for (List<Point2D_I32> internal : c.internal) {
        vertexes = ShapeFittingOps.fitPolygon(internal, true, toleranceDist, toleranceAngle, 100);
        VisualizeShapes.drawPolygon(vertexes, true, g2);
      }
    }

    ShowImages.showWindow(polygon, "Binary Blob Contours");
  }