예제 #1
0
  /**
   * method to compute the epipolar line integrals that state the epipolar consistency conditions by
   * comparison of two views
   *
   * @param kappa_RAD: angle of epipolar plane
   * @return double[] array containing two values (one for each view's line integral)
   */
  public double[] computeEpipolarLineIntegrals(double kappa_RAD) {

    // compute points on unit-circle (3x1) //
    SimpleVector x_kappa = new SimpleVector(Math.cos(kappa_RAD), Math.sin(kappa_RAD), 1);

    // compute epipolar plane E_kappa (4x1 = 4x3 * 3x1) //
    SimpleVector E_kappa = SimpleOperators.multiply(this.K, x_kappa);

    // compute line integral out of derived radon transform //
    double value1 = view1.getValueByAlphaAndT(E_kappa);
    double value2 = view2.getValueByAlphaAndT(E_kappa);

    // both values are returned //
    return new double[] {value1, value2};
  }
예제 #2
0
    /**
     * constructor to create a view
     *
     * @param projection: projection image as Grid2D
     * @param radon: radon transformed and derived image as Grid2D
     * @param projMatrix: projection matrix as Projection
     */
    public View(Grid2D projection, Grid2D radon, Projection projMatrix) {

      // Initialize center matrix //
      CENTER = new SimpleMatrix(3, 4);
      CENTER.setDiagValue(new SimpleVector(1.0, 1.0, 1.0));

      // get data out of projection //
      this.projectionWidth = projection.getWidth();
      this.projectionHeight = projection.getHeight();

      // get data out of radon transformed image //
      this.radonWidth = radon.getWidth();
      this.radonHeight = radon.getHeight();
      this.projectionDiag =
          Math.sqrt(projectionWidth * projectionWidth + projectionHeight * projectionHeight);
      this.lineIncrement = radonWidth / projectionDiag;
      this.angleIncrement = radonHeight / Math.PI;

      // store radon transformed image //
      this.radon = radon;

      // get projection matrix P (3x4) //
      this.P = SimpleOperators.multiplyMatrixProd(projMatrix.getK(), CENTER);
      this.P = SimpleOperators.multiplyMatrixProd(this.P, projMatrix.getRt());

      // get source position C (nullspace of the projection) //
      DecompositionSVD decoP = new DecompositionSVD(this.P);
      this.C = decoP.getV().getCol(3);

      // normalize source vectors by last component //
      // it is important that the last component is positive to have a positive center
      // as it is defined in oriented projective geometry
      this.C = this.C.dividedBy(this.C.getElement(3));
    }
예제 #3
0
  /**
   * method to compute the metric for the epipolar consistency conditions between two views with
   * varying angle kappa from lowerBorderAngle to upperBorderAngle with an increment of
   * angleIncrement
   *
   * @param lowerBorderAngle
   * @param upperBorderAngle
   * @param angleIncrement
   * @return: 2D-array containing the line integral values of two different views of all angles
   *     running in the range defined by the input parameters the stored format is [angle,
   *     valueView1, valueView2] in the first dimension, increasing/decreasing angle in the second
   */
  public double[][] evaluateConsistency(
      double lowerBorderAngle, double upperBorderAngle, double angleIncrement) {

    // compute the mapping matrix to the epipolar plane //
    createMappingToEpipolarPlane();
    // (K is a 4x3 matrix)

    // calculate inverses of projection matrices and save to view //
    this.view1.P_Inverse = this.view1.P.inverse(InversionType.INVERT_SVD);
    this.view2.P_Inverse = this.view2.P.inverse(InversionType.INVERT_SVD);

    // get number of decimal places of the angleIncrement //
    String[] split = Double.toString(angleIncrement).split("\\.");
    int decimalPlaces = split[1].length();

    // obtain size parameter for results array //
    int height = (int) ((upperBorderAngle - lowerBorderAngle) / angleIncrement + 1);

    // results are saved in an array in the format [angle,valueView1,valueView2]
    double[][] results = new double[height][3];
    int count = 0;

    // go through angles //
    for (double kappa = lowerBorderAngle; kappa <= upperBorderAngle; kappa += angleIncrement) {

      double kappa_RAD = kappa / 180.0 * Math.PI;

      // get values for line integrals that fulfill the epipolar consistency conditions //
      double[] values = computeEpipolarLineIntegrals(kappa_RAD);

      // store values in results array //
      results[count][0] =
          Math.round(kappa * Math.pow(10, decimalPlaces)) / (Math.pow(10, decimalPlaces) + 0.0);
      results[count][1] = values[0];
      results[count][2] = values[1];
      count++;
    }

    // show results //
    for (int i = 0; i < results.length; i++) {
      System.out.println(
          "at angle kappa: " + results[i][0] + " P1: " + results[i][1] + " P2: " + results[i][2]);
    }

    return results;
  }
예제 #4
0
  /**
   * method to compute the squared radon transformed and derived image for one view the derivation
   * is done in t-direction (distance to origin)
   *
   * @param data: Grid2D which represents the projection
   * @param radonSize: value to determine the size of the squared radon transformed and derived
   *     image
   * @return: radon transformed image as Grid2D (its size is radonSize x radonSize)
   */
  public static Grid2D computeRadonTrafoAndDerive(Grid2D data, int radonSize) {

    Grid2D radon = null;

    // optional: preprocessing can be done here
    // for example:
    /*
    float value;
    for (int i = 0; i < data.getWidth(); i++) {
    	for (int j = 0; j < data.getHeight(); j++) {
    		if (j < 10 || j > data.getHeight() - 11) {
    			// set border to zero
    			value = 0.0f;
    		} else {
    			value = (float)(-Math.log(data.getAtIndex(i, j) / 0.842f));
    		}
    		data.setAtIndex(i, j, value);
    	}
    }

    data.show("preprocessed image");
    */

    // * get some dimensions out of data (projection) *//
    int projSizeX = data.getWidth();
    int projSizeY = data.getHeight();
    double projectionDiag = Math.sqrt(projSizeX * projSizeX + projSizeY * projSizeY);

    double deltaS = projectionDiag / radonSize;
    double deltaTheta = Math.PI / radonSize;

    // * create a parallel projector in order to compute the radon transformation *//
    ParallelProjector2D projector =
        new ParallelProjector2D(Math.PI, deltaTheta, projectionDiag, deltaS);

    // * create radon transformation *//
    radon = projector.projectRayDriven(data);
    // for a faster GPU implementation use: (possibly not working):
    // radon = projector.projectRayDrivenCL(data);

    // * derivative by Sobel operator in t-direction *//
    final int size = 1024;
    SobelKernel1D kernel = new SobelKernel1D(size, 9);
    kernel.applyToGrid(radon);

    // * optional: save file in tiff-format *//
    /*
    FileSaver saveRadon = new FileSaver(ImageUtil.wrapGrid(radon, ""));
    saveRadon.saveAsTiff();
    */

    return radon;
  }
예제 #5
0
    /**
     * Method to calculate alpha and t as indices from the radon transformed image of a view.
     * Neccessary are the inverse projection image (as SimpleMatrix) and the epipolar plane E
     *
     * @param E: epipolar plane E as SimpleVector (4 entries)
     * @return: line integral value as double
     */
    private double getValueByAlphaAndT(SimpleVector E) {

      // compute corresponding epipolar lines //
      // (epipolar lines are of 3x1 = 3x4 * 4x1)
      SimpleVector l_kappa = SimpleOperators.multiply(this.P_Inverse.transposed(), E);

      // init the coordinate shift //
      int t_u = this.projectionWidth / 2;
      int t_v = this.projectionHeight / 2;

      // compute angle alpha and distance to origin t //
      double l0 = l_kappa.getElement(0);
      double l1 = l_kappa.getElement(1);
      double l2 = l_kappa.getElement(2);

      double alpha_kappa_RAD = Math.atan2(-l0, l1) + Math.PI / 2;

      double t_kappa = -l2 / Math.sqrt(l0 * l0 + l1 * l1);
      // correct the coordinate shift //
      t_kappa -= t_u * Math.cos(alpha_kappa_RAD) + t_v * Math.sin(alpha_kappa_RAD);

      // correct some alpha falling out of the radon window //
      if (alpha_kappa_RAD < 0) {
        alpha_kappa_RAD *= -1.0;
      } else if (alpha_kappa_RAD > Math.PI) {
        alpha_kappa_RAD = 2.0 * Math.PI - alpha_kappa_RAD;
      }

      // write back to l_kappa //
      l_kappa.setElementValue(0, Math.cos(alpha_kappa_RAD));
      l_kappa.setElementValue(1, Math.sin(alpha_kappa_RAD));
      l_kappa.setElementValue(2, -t_kappa);

      // calculate x and y coordinates for derived radon transformed image //
      double x = t_kappa * this.lineIncrement + 0.5 * this.radonWidth;
      double y = alpha_kappa_RAD * this.angleIncrement;

      // get intensity value out of radon transformed image //
      // (interpolation needed)
      return InterpolationOperators.interpolateLinear(this.radon, x, y);
    }