All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.intel.analytics.zoo.feature.image3d.Affine.scala Maven / Gradle / Ivy

There is a newer version: 0.11.2
Show newest version
/*
 * Copyright 2018 Analytics Zoo Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intel.analytics.zoo.feature.image3d

import com.intel.analytics.bigdl.tensor.TensorNumericMath.TensorNumeric
import com.intel.analytics.bigdl.tensor.{DoubleType, FloatType, Tensor}

import scala.reflect.ClassTag

object AffineTransform3D{
  /**
   * Affine transformer implements affine transformation on a given tensor.
   * To avoid defects in resampling, the mapping is from destination to source.
   * dst(z,y,x) = src(f(z),f(y),f(x)) where f: dst -> src
   *
   * @param mat [Tensor[Double], dim: DxHxW] defines affine transformation from dst to src.
   * @param translation [Tensor[Double], dim: 3, default: (0,0,0)]
    *                    defines translation in each axis.
   * @param clampMode [String, (default: "clamp",'padding')] defines how to handle interpolation
    *                  off the input image.
   * @param padVal [Double, default: 0] defines padding value when clampMode="padding".
   *               Setting this value when clampMode="clamp" will cause an error.
   */
  def apply(mat: Tensor[Double],
            translation: Tensor[Double] = Tensor[Double](3).fill(0),
            clampMode: String = "clamp",
            padVal: Double = 0): AffineTransform3D =
      new AffineTransform3D(mat, translation, clampMode, padVal)
}

class AffineTransform3D(mat: Tensor[Double],
                        translation: Tensor[Double],
                        clampMode: String,
                        padVal: Double)
extends ImageProcessing3D {

  override def transformTensor(tensor: Tensor[Float]): Tensor[Float] = {
    require(tensor.dim >=3 && tensor.size(4) == 1,
      "Currently 3D affine transformation only supports 1 channel 3D image.")
    val src = tensor.squeeze(4)
    val dst = Tensor[Float](src.size())
    val depth = dst.size(1)
    val height = dst.size(2)
    val width = dst.size(3)
    var grid_xyz = Tensor[Double](Array[Int](3, depth, height, width))
    val cz = (depth + 1)/2.0
    val cy = (height + 1)/2.0
    val cx = (width + 1)/2.0
    for(z <- 1 to depth; y <- 1 to height; x <- 1 to width) {
      grid_xyz.setValue(1, z, y, x, cz-z)
      grid_xyz.setValue(2, z, y, x, cy-y)
      grid_xyz.setValue(3, z, y, x, cx-x)
    }
    val view_xyz = grid_xyz.reshape(Array[Int](3, depth * height * width))
    val field = mat * view_xyz
    grid_xyz = grid_xyz.sub(field.reshape(Array[Int](3, depth, height, width)))
    val translation_mat = Tensor[Double](Array[Int](3, depth, height, width))
    translation_mat(1).fill(translation.valueAt(1))
    translation_mat(2).fill(translation.valueAt(2))
    translation_mat(3).fill(translation.valueAt(3))
    grid_xyz(1) = grid_xyz(1).sub(translation_mat(1))
    grid_xyz(2) = grid_xyz(2).sub(translation_mat(2))
    grid_xyz(3) = grid_xyz(3).sub(translation_mat(3))
    val offset_mode = true
    val warp_transformer = WarpTransformer(grid_xyz, offset_mode, clampMode, padVal)
    warp_transformer(src, dst)
    dst.resize(dst.size(1), dst.size(2), dst.size(3), 1)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy