@Test
  public void elementMultConjB() {
    InterleavedF64 a = new InterleavedF64(width, height, 2);
    InterleavedF64 b = new InterleavedF64(width, height, 2);
    InterleavedF64 c = new InterleavedF64(width, height, 2);

    ImageMiscOps.fillUniform(a, rand, -10, 10);
    ImageMiscOps.fillUniform(b, rand, -10, 10);
    ImageMiscOps.fillUniform(c, rand, -10, 10);

    CirculantTracker.elementMultConjB(a, b, c);

    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        Complex64F aa = new Complex64F(a.getBand(x, y, 0), a.getBand(x, y, 1));
        Complex64F bb = new Complex64F(b.getBand(x, y, 0), b.getBand(x, y, 1));

        Complex64F cc = new Complex64F();
        ComplexMath64F.conj(bb, bb);
        ComplexMath64F.mult(aa, bb, cc);

        double foundReal = c.getBand(x, y, 0);
        double foundImg = c.getBand(x, y, 1);

        assertEquals(cc.real, foundReal, 1e-4);
        assertEquals(cc.imaginary, foundImg, 1e-4);
      }
    }
  }
  @Test
  public void computeAlphas() {
    InterleavedF64 yf = new InterleavedF64(width, height, 2);
    InterleavedF64 kf = new InterleavedF64(width, height, 2);
    InterleavedF64 alphaf = new InterleavedF64(width, height, 2);

    ImageMiscOps.fillUniform(yf, rand, -10, 10);
    ImageMiscOps.fillUniform(kf, rand, -10, 10);
    ImageMiscOps.fillUniform(alphaf, rand, -10, 10);

    float lambda = 0.01f;
    CirculantTracker.computeAlphas(yf, kf, lambda, alphaf);

    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        Complex64F a = new Complex64F(yf.getBand(x, y, 0), yf.getBand(x, y, 1));
        Complex64F b = new Complex64F(kf.getBand(x, y, 0) + lambda, kf.getBand(x, y, 1));

        Complex64F c = new Complex64F();
        ComplexMath64F.div(a, b, c);

        double foundReal = alphaf.getBand(x, y, 0);
        double foundImg = alphaf.getBand(x, y, 1);

        assertEquals(c.real, foundReal, 1e-4);
        assertEquals(c.imaginary, foundImg, 1e-4);
      }
    }
  }
  private void setTargetLocation(int x, int y) {
    ImageMiscOps.fillUniform(image, rand, 0, 1);
    ImageMiscOps.fillRectangle(image, 100, cornerX, cornerY, 20, 20);
    pyramid.process(image);

    for (int i = 0; i < pyramid.getNumLayers(); i++) {
      GradientSobel.process(
          pyramid.getLayer(i),
          derivX[i],
          derivY[i],
          new ImageBorder1D_F32(BorderIndex1D_Extend.class));
    }
  }
  public BenchmarkConvolveNormalizeEdge() {
    imgInt8 = new ImageUInt8(imgWidth, imgHeight);
    imgInt16 = new ImageSInt16(imgWidth, imgHeight);
    out_I32 = new ImageSInt32(imgWidth, imgHeight);
    out_I16 = new ImageSInt16(imgWidth, imgHeight);
    out_I8 = new ImageUInt8(imgWidth, imgHeight);
    imgFloat32 = new ImageFloat32(imgWidth, imgHeight);
    out_F32 = new ImageFloat32(imgWidth, imgHeight);

    Random rand = new Random(234234);
    ImageMiscOps.fillUniform(imgInt8, rand, 0, 100);
    ImageMiscOps.fillUniform(imgInt16, rand, 0, 200);
    ImageMiscOps.fillUniform(imgFloat32, rand, 0, 200);
  }
  protected void checkMotion(double tranX, double tranY, double rot) {
    ImageUInt8 frame0 = new ImageUInt8(320, 240);
    ImageUInt8 frame1 = new ImageUInt8(320, 240);
    ImageMiscOps.fillUniform(frame0, rand, 0, 256);

    double c = Math.cos(rot);
    double s = Math.sin(rot);

    DistortImageOps.affine(frame0, frame1, TypeInterpolate.BILINEAR, c, -s, s, c, tranX, tranY);

    SfotConfig config = new SfotConfig();

    ImageGradient<ImageUInt8, ImageSInt16> gradient =
        FactoryDerivative.sobel(ImageUInt8.class, ImageSInt16.class);

    SparseFlowObjectTracker<ImageUInt8, ImageSInt16> alg =
        new SparseFlowObjectTracker<ImageUInt8, ImageSInt16>(
            config, ImageUInt8.class, ImageSInt16.class, gradient);

    RectangleRotate_F64 region0 = new RectangleRotate_F64(120, 140, 30, 40, 0.1);
    RectangleRotate_F64 region1 = new RectangleRotate_F64();

    alg.init(frame0, region0);
    assertTrue(alg.update(frame1, region1));

    double expectedX = c * region0.cx - s * region0.cy + tranX;
    double expectedY = s * region0.cx + c * region0.cy + tranY;
    double expectedYaw = UtilAngle.bound(region0.theta + rot);

    assertEquals(expectedX, region1.cx, 0.5);
    assertEquals(expectedY, region1.cy, 0.5);
    assertEquals(expectedYaw, region1.theta, 0.01);
  }
  @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);
  }
  /**
   * Creates a random image and looks for corners in it. Sees if the naive and fast algorithm
   * produce exactly the same results.
   */
  @Test
  public void compareToNaive() {
    GrayU8 img = new GrayU8(width, height);
    ImageMiscOps.fillUniform(img, new Random(0xfeed), 0, 100);

    GrayS16 derivX = new GrayS16(img.getWidth(), img.getHeight());
    GrayS16 derivY = new GrayS16(img.getWidth(), img.getHeight());

    GradientSobel.process(img, derivX, derivY, new ImageBorder1D_S32(BorderIndex1D_Extend.class));

    BoofTesting.checkSubImage(this, "compareToNaive", true, derivX, derivY);
  }
  @Override
  public void renderTarget(ImageFloat32 original, List<CalibrationObservation> solutions) {
    ImageMiscOps.fill(original, 255);

    int numRows = config.numRows * 2 - 1;
    int numCols = config.numCols * 2 - 1;

    int square = original.getWidth() / (Math.max(numRows, numCols) + 4);

    int targetWidth = square * numCols;
    int targetHeight = square * numRows;

    int x0 = (original.width - targetWidth) / 2;
    int y0 = (original.height - targetHeight) / 2;

    for (int i = 0; i < numRows; i += 2) {
      int y = y0 + i * square;

      for (int j = 0; j < numCols; j += 2) {
        int x = x0 + j * square;
        ImageMiscOps.fillRectangle(original, 0, x, y, square, square);
      }
    }

    int pointsRow = numRows + 1;
    int pointsCol = numCols + 1;

    CalibrationObservation set = new CalibrationObservation();
    int gridIndex = 0;
    for (int i = 0; i < pointsRow; i++) {
      for (int j = 0; j < pointsCol; j++, gridIndex++) {
        double y = y0 + i * square;
        double x = x0 + j * square;
        set.add(new Point2D_F64(x, y), gridIndex);
      }
    }
    solutions.add(set);
  }
  @Test
  public void imageDotProduct() {
    ImageFloat64 a = new ImageFloat64(width, height);
    ImageMiscOps.fillUniform(a, rand, 0, 10);

    double total = 0;
    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        total += a.get(x, y) * a.get(x, y);
      }
    }
    double found = CirculantTracker.imageDotProduct(a);
    assertEquals(total, found, 1e-8);
  }
  protected void performThresholding(float threshLow, float threshHigh, ImageUInt8 output) {
    if (hysteresisPts != null) {
      hysteresisPts.process(suppressed, direction, threshLow, threshHigh);

      // if there is an output image write the contour to it
      if (output != null) {
        ImageMiscOps.fill(output, 0);
        for (EdgeContour e : hysteresisPts.getContours()) {
          for (EdgeSegment s : e.segments)
            for (Point2D_I32 p : s.points) output.unsafe_set(p.x, p.y, 1);
        }
      }
    } else {
      hysteresisMark.process(suppressed, direction, threshLow, threshHigh, output);
    }
  }
  @Test
  public void compareToConvolve_I8() throws NoSuchMethodException {
    CompareDerivativeToConvolution validator = new CompareDerivativeToConvolution();
    validator.setTarget(
        HessianThree_Standard.class.getMethod(
            "process", ImageUInt8.class, ImageSInt16.class, ImageSInt16.class, ImageSInt16.class));

    validator.setKernel(0, HessianThree.kernelXXYY_I32, true);
    validator.setKernel(1, HessianThree.kernelXXYY_I32, false);
    validator.setKernel(2, HessianThree.kernelCross_I32);

    ImageUInt8 input = new ImageUInt8(width, height);
    ImageMiscOps.fillUniform(input, rand, 0, 10);
    ImageSInt16 derivXX = new ImageSInt16(width, height);
    ImageSInt16 derivYY = new ImageSInt16(width, height);
    ImageSInt16 derivXY = new ImageSInt16(width, height);

    validator.compare(false, input, derivXX, derivYY, derivXY);
  }
Beispiel #12
0
  @Test
  public void compareToConvolve_F32() throws NoSuchMethodException {
    CompareDerivativeToConvolution validator = new CompareDerivativeToConvolution();
    validator.setTarget(
        GradientPrewitt.class.getMethod(
            "process",
            ImageFloat32.class,
            ImageFloat32.class,
            ImageFloat32.class,
            ImageBorder_F32.class));

    validator.setKernel(0, GradientPrewitt.kernelDerivX_F32);
    validator.setKernel(1, GradientPrewitt.kernelDerivY_F32);

    ImageFloat32 input = new ImageFloat32(width, height);
    ImageMiscOps.fillUniform(input, rand, 0, 10);
    ImageFloat32 derivX = new ImageFloat32(width, height);
    ImageFloat32 derivY = new ImageFloat32(width, height);

    validator.compare(input, derivX, derivY);
  }
  @Test
  public void checkRender() {
    // Easier to make up a plane in this direction
    Se3_F64 cameraToPlane = new Se3_F64();
    ConvertRotation3D_F64.eulerToMatrix(
        EulerType.XYZ, UtilAngle.degreeToRadian(0), 0, 0, cameraToPlane.getR());
    cameraToPlane.getT().set(0, -5, 0);

    Se3_F64 planeToCamera = cameraToPlane.invert(null);

    CreateSyntheticOverheadViewMS<ImageFloat32> alg =
        new CreateSyntheticOverheadViewMS<ImageFloat32>(
            TypeInterpolate.BILINEAR, 3, ImageFloat32.class);

    alg.configure(param, planeToCamera, centerX, centerY, cellSize, overheadW, overheadH);

    MultiSpectral<ImageFloat32> input =
        new MultiSpectral<ImageFloat32>(ImageFloat32.class, width, height, 3);
    for (int i = 0; i < 3; i++) ImageMiscOps.fill(input.getBand(i), 10 + i);

    MultiSpectral<ImageFloat32> output =
        new MultiSpectral<ImageFloat32>(ImageFloat32.class, overheadW, overheadH, 3);

    alg.process(input, output);

    for (int i = 0; i < 3; i++) {
      ImageFloat32 o = output.getBand(i);

      // check parts that shouldn't be in view
      assertEquals(0, o.get(0, 300), 1e-8);
      assertEquals(0, o.get(5, 0), 1e-8);
      assertEquals(0, o.get(5, 599), 1e-8);

      // check areas that should be in view
      assertEquals(10 + i, o.get(499, 300), 1e-8);
    }
  }
  @Test
  public void basic() {
    ImageUInt8 image = new ImageUInt8(400, 500);

    int value = 200;
    ImageMiscOps.fillRectangle(image, value, 20, 30, 40, 40);

    PolygonEdgeScore<ImageUInt8> alg =
        new PolygonEdgeScore<ImageUInt8>(2, 2, 10, value * 0.9, ImageUInt8.class);

    Polygon2D_F64 polygon = new Polygon2D_F64(4);

    UtilPolygons2D_F64.convert(new Rectangle2D_F64(20, 30, 60, 70), polygon);

    alg.setImage(image);
    assertTrue(alg.validate(polygon));
    assertEquals(value, alg.getAverageEdgeIntensity(), 1e-8);

    UtilPolygons2D_F64.convert(new Rectangle2D_F64(24, 30, 60, 70), polygon);

    // test a negative case
    assertFalse(alg.validate(polygon));
    assertEquals(value * 3.0 / 4.0, alg.getAverageEdgeIntensity(), 1e-8);
  }