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

com.intel.analytics.bigdl.transform.vision.image.augmentation.Resize.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2016 The BigDL 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.bigdl.transform.vision.image.augmentation

import com.intel.analytics.bigdl.transform.vision.image.opencv.OpenCVMat
import com.intel.analytics.bigdl.transform.vision.image.{FeatureTransformer, ImageFeature}
import org.apache.log4j.Logger
import org.opencv.core.Size
import org.opencv.imgproc.Imgproc

import scala.util.Random

/**
 * Resize image
 * @param resizeH height after resize
 * @param resizeW width after resize
 * @param resizeMode if resizeMode = -1, random select a mode from
 * (Imgproc.INTER_LINEAR, Imgproc.INTER_CUBIC, Imgproc.INTER_AREA,
 *                   Imgproc.INTER_NEAREST, Imgproc.INTER_LANCZOS4)
 * @param useScaleFactor if true, scale factor fx and fy is used, fx = fy = 0
 * note that the result of the following are different
 * Imgproc.resize(mat, mat, new Size(resizeWH, resizeWH), 0, 0, Imgproc.INTER_LINEAR)
 * Imgproc.resize(mat, mat, new Size(resizeWH, resizeWH))
 */
class Resize(resizeH: Int, resizeW: Int,
  resizeMode: Int = Imgproc.INTER_LINEAR,
  useScaleFactor: Boolean = true)
  extends FeatureTransformer {

  private val interpMethods = Array(Imgproc.INTER_LINEAR, Imgproc.INTER_CUBIC, Imgproc.INTER_AREA,
    Imgproc.INTER_NEAREST, Imgproc.INTER_LANCZOS4)

  override def transformMat(feature: ImageFeature): Unit = {
    val interpMethod = if (resizeMode == -1) {
      interpMethods(new Random().nextInt(interpMethods.length))
    } else {
      resizeMode
    }
    Resize.transform(feature.opencvMat(), feature.opencvMat(), resizeW, resizeH, interpMethod,
      useScaleFactor)
  }
}

object Resize {
  val logger = Logger.getLogger(getClass)

  def apply(resizeH: Int, resizeW: Int,
    resizeMode: Int = Imgproc.INTER_LINEAR, useScaleFactor: Boolean = true): Resize =
    new Resize(resizeH, resizeW, resizeMode, useScaleFactor)

  def transform(input: OpenCVMat, output: OpenCVMat, resizeW: Int, resizeH: Int,
                mode: Int = Imgproc.INTER_LINEAR, useScaleFactor: Boolean = true)
  : OpenCVMat = {
    if (useScaleFactor) {
      Imgproc.resize(input, output, new Size(resizeW, resizeH), 0, 0, mode)
    } else {
      Imgproc.resize(input, output, new Size(resizeW, resizeH))
    }
    output
  }
}

/**
 * Resize the image, keep the aspect ratio. scale according to the short edge
 * @param minSize scale size, apply to short edge
 * @param scaleMultipleOf make the scaled size multiple of some value
 * @param maxSize max size after scale
 * @param resizeMode if resizeMode = -1, random select a mode from
 * (Imgproc.INTER_LINEAR, Imgproc.INTER_CUBIC, Imgproc.INTER_AREA,
 *                   Imgproc.INTER_NEAREST, Imgproc.INTER_LANCZOS4)
 * @param useScaleFactor if true, scale factor fx and fy is used, fx = fy = 0
 * @param minScale control the minimum scale up for image
 */
class AspectScale(minSize: Int,
  scaleMultipleOf: Int = 1,
  maxSize: Int = 1000,
  resizeMode: Int = Imgproc.INTER_LINEAR,
  useScaleFactor: Boolean = true,
  minScale: Option[Float] = None)
  extends FeatureTransformer {

  override def transformMat(feature: ImageFeature): Unit = {
    val (height, width) = AspectScale.getHeightWidthAfterRatioScale(feature.opencvMat(),
      minSize, maxSize, scaleMultipleOf, minScale)
    Resize.transform(feature.opencvMat(), feature.opencvMat(),
      width, height, resizeMode, useScaleFactor)
  }
}

object AspectScale {

  def apply(minSize: Int,
    scaleMultipleOf: Int = 1,
    maxSize: Int = 1000,
    mode: Int = Imgproc.INTER_LINEAR,
    useScaleFactor: Boolean = true,
    minScale: Option[Float] = None): AspectScale =
    new AspectScale(minSize, scaleMultipleOf, maxSize, mode, useScaleFactor, minScale)
  /**
   * get the width and height of scaled image
   * @param img original image
   */
  def getHeightWidthAfterRatioScale(img: OpenCVMat, scaleTo: Float,
    maxSize: Int, scaleMultipleOf: Int, minScale: Option[Float] = None): (Int, Int) = {
    val imSizeMin = Math.min(img.width(), img.height())
    val imSizeMax = Math.max(img.width(), img.height())
    var imScale = scaleTo.toFloat / imSizeMin.toFloat
    if (minScale.isDefined) {
      imScale = Math.max(minScale.get, imScale)
    }
    // Prevent the biggest axis from being more than MAX_SIZE
    if (Math.round(imScale * imSizeMax) > maxSize) {
      imScale = maxSize / imSizeMax.toFloat
    }

    var imScaleH, imScaleW = imScale
    if (scaleMultipleOf > 1) {
      imScaleH = (Math.floor(img.height() * imScale / scaleMultipleOf) *
        scaleMultipleOf / img.height()).toFloat
      imScaleW = (Math.floor(img.width() * imScale / scaleMultipleOf) *
        scaleMultipleOf / img.width()).toFloat
    }

    val width = imScaleW * img.width()
    val height = imScaleH * img.height()
    (height.round, width.round)
  }
}


/**
 * resize the image by randomly choosing a scale
 * @param scales array of scale options that for random choice
 * @param scaleMultipleOf Resize test images so that its width and height are multiples of
 * @param maxSize Max pixel size of the longest side of a scaled input image
 */
class RandomAspectScale(scales: Array[Int], scaleMultipleOf: Int = 1,
  maxSize: Int = 1000) extends FeatureTransformer {

  override def transformMat(feature: ImageFeature): Unit = {
    val scaleTo = scales(Random.nextInt(scales.length))
    val (height, width) = AspectScale.getHeightWidthAfterRatioScale(feature.opencvMat(),
      scaleTo, maxSize, scaleMultipleOf)
    Resize.transform(feature.opencvMat(), feature.opencvMat(), width, height)
  }
}

object RandomAspectScale {
  def apply(scales: Array[Int], scaleMultipleOf: Int = 1,
    maxSize: Int = 1000): RandomAspectScale =
    new RandomAspectScale(scales, scaleMultipleOf, maxSize)
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy